diff options
Diffstat (limited to 'sal/osl/os2')
48 files changed, 25055 insertions, 0 deletions
diff --git a/sal/osl/os2/conditn.c b/sal/osl/os2/conditn.c new file mode 100644 index 000000000000..3497bbd37237 --- /dev/null +++ b/sal/osl/os2/conditn.c @@ -0,0 +1,127 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: conditn.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "system.h" + +#include <osl/conditn.h> +#include <osl/diagnose.h> +#include <osl/time.h> + + + +/* + under WIN32, we use the void* oslCondition + as a WIN32 HANDLE (which is also a 32-bit value) +*/ + +/*****************************************************************************/ +/* osl_createCondition */ +/*****************************************************************************/ +oslCondition SAL_CALL osl_createCondition() +{ + HEV hevCondition; + APIRET rc; + + rc = DosCreateEventSem( NULL, /* unnamed semaphore */ + &hevCondition, /* pointer to variable */ + /* for the sem-handle */ + DC_SEM_SHARED, /* shared semaphore */ + FALSE ); /* initial state is posted */ + + if( rc == NO_ERROR ) + return (oslCondition)hevCondition; + else + return NULL; +} + +/*****************************************************************************/ +/* osl_destroyCondition */ +/*****************************************************************************/ +void SAL_CALL osl_destroyCondition(oslCondition Condition) +{ + if( Condition ) + DosCloseEventSem( (HEV) Condition ); +} + +/*****************************************************************************/ +/* osl_setCondition */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_setCondition(oslCondition Condition) +{ + OSL_ASSERT(Condition); + + return DosPostEventSem((HEV)Condition) == NO_ERROR; +} + +/*****************************************************************************/ +/* osl_resetCondition */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition) +{ + ULONG ulPostCount; + + OSL_ASSERT(Condition); + + return DosResetEventSem((HEV)Condition, &ulPostCount) == NO_ERROR; +} + +/*****************************************************************************/ +/* osl_waitCondition */ +/*****************************************************************************/ +oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition, const TimeValue * pTimeout ) +{ + long nTimeout; + APIRET rc; + OSL_ASSERT(Condition); + + if( pTimeout ) + nTimeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000; + else + nTimeout = SEM_INDEFINITE_WAIT; + + rc = DosWaitEventSem((HEV)Condition, nTimeout ); + if( rc == ERROR_TIMEOUT ) + return osl_cond_result_timeout; + if( rc != NO_ERROR ) + return osl_cond_result_error; + + return osl_cond_result_ok; +} + +/*****************************************************************************/ +/* osl_checkCondition */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition) +{ + OSL_ASSERT(Condition); + + return( DosWaitEventSem((HEV)Condition, SEM_IMMEDIATE_RETURN) == NO_ERROR); +} + diff --git a/sal/osl/os2/debug.c b/sal/osl/os2/debug.c new file mode 100644 index 000000000000..78a2df07056e --- /dev/null +++ b/sal/osl/os2/debug.c @@ -0,0 +1,2155 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile:$ + * $Revision:$ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + *@@sourcefile debug.c: + * this file contains debugging functions for the + * exception handlers in except.c. + * + * This code is capable of unwinding the stack from + * a given address and trying to get function names + * and source line numbers, either from the respective + * module's debug code (if present) or from a SYM file, + * which is searched for in the directory of the module + * or in ?:\OS2\PDPSI\PMDF\WARP4. + * + * This file incorporates code from the following: + * -- Marc Fiammante, John Currier, Kim Rasmussen, + * Anthony Cruise (EXCEPT3.ZIP package for a generic + * exception handling DLL, available at Hobbes). + * + * Usage: All OS/2 programs. + * + * Note: Version numbering in this file relates to XWorkplace version + * numbering. + * + *@@changed V0.9.0 [umoeller]: made some declarations C++-compatible + *@@changed V0.9.1 (2000-01-30) [umoeller]: greatly cleaned up this file + * + *@@header "helpers\debug.h" + */ + +/* + * This file Copyright (C) 1992-99 Ulrich M�ller, + * Kim Rasmussen, + * Marc Fiammante, + * John Currier, + * Anthony Cruise. + * This file is part of the "XWorkplace helpers" source package. + * + * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. + * + */ + +//#define DEBUG_SYMDUMP // enable to dump sym file to log + +//YD commented, since we need unsigned char BYTE! +//#define OS2EMX_PLAIN_CHAR +//Also gcc char is signed, while most structures requires unsigned data! +//Raised limits for all fields! + + // this is needed for "os2emx.h"; if this is defined, + // emx will define PSZ as _signed_ char, otherwise + // as unsigned char + +#define INCL_DOSPROCESS +#define INCL_DOSMODULEMGR +#define INCL_DOSMISC +#define INCL_DOSERRORS +#include <os2.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define DONT_REPLACE_MALLOC +#include "helpers\setup.h" // code generation and debugging options + +#include "helpers\debug.h" +#include "helpers\dosh.h" + +#pragma hdrstop + +#include <fcntl.h> +#ifdef __EMX__ + #include <sys\types.h> // required for sys\stat.h; UM 99-10-22 +#endif +#include <sys\stat.h> +#include <share.h> +#include <io.h> + +#ifndef DWORD +#define DWORD unsigned long +#endif +#ifndef WORD +#define WORD unsigned short +#endif + +#pragma stack16(512) +#define HF_STDERR 2 + +/* + *@@category: Helpers\Control program helpers\Exceptions/debugging + * See except.c and debug.c. + */ + +/* ****************************************************************** + * + * Global variables + * + ********************************************************************/ + +// this specifies whether we're dealing with 32-bit code; +// this gets changed whenever 16-bit count is detected +static BOOL f32bit = TRUE; + +/* + * Global variables for Read32PmDebug: + * + */ + +ULONG func_ofs; +ULONG pubfunc_ofs; +//YD 17/07/06 c++ namespace can generate really long +//YD names, use a large buffer! +char func_name[16*1024]; +ULONG var_ofs = 0; + +struct { + BYTE name[128]; + ULONG stack_offset; + USHORT type_idx; +} autovar_def[1024]; + +#pragma pack(1) + +BYTE *type_name[] = +{ + "8 bit signed ", + "16 bit signed ", + "32 bit signed ", + "Unknown (0x83) ", + "8 bit unsigned ", + "16 bit unsigned ", + "32 bit unsigned ", + "Unknown (0x87) ", + "32 bit real ", + "64 bit real ", + "80 bit real ", + "Unknown (0x8B) ", + "64 bit complex ", + "128 bit complex ", + "160 bit complex ", + "Unknown (0x8F) ", + "8 bit boolean ", + "16 bit boolean ", + "32 bit boolean ", + "Unknown (0x93) ", + "8 bit character ", + "16 bit characters ", + "32 bit characters ", + "void ", + "15 bit unsigned ", + "24 bit unsigned ", + "31 bit unsigned ", + "Unknown (0x9B) ", + "Unknown (0x9C) ", + "Unknown (0x9D) ", + "Unknown (0x9E) ", + "Unknown (0x9F) ", + "near pointer to 8 bit signed ", + "near pointer to 16 bit signed ", + "near pointer to 32 bit signed ", + "Unknown (0xA3) ", + "near pointer to 8 bit unsigned ", + "near pointer to 16 bit unsigned ", + "near pointer to 32 bit unsigned ", + "Unknown (0xA7) ", + "near pointer to 32 bit real ", + "near pointer to 64 bit real ", + "near pointer to 80 bit real ", + "Unknown (0xAB) ", + "near pointer to 64 bit complex ", + "near pointer to 128 bit complex ", + "near pointer to 160 bit complex ", + "Unknown (0xAF) ", + "near pointer to 8 bit boolean ", + "near pointer to 16 bit boolean ", + "near pointer to 32 bit boolean ", + "Unknown (0xB3) ", + "near pointer to 8 bit character ", + "near pointer to 16 bit characters", + "near pointer to 32 bit characters", + "near pointer to void ", + "near pointer to 15 bit unsigned ", + "near pointer to 24 bit unsigned ", + "near pointer to 31 bit unsigned ", + "Unknown (0xBB) ", + "Unknown (0xBC) ", + "Unknown (0xBD) ", + "Unknown (0xBE) ", + "Unknown (0xBF) ", + "far pointer to 8 bit signed ", + "far pointer to 16 bit signed ", + "far pointer to 32 bit signed ", + "Unknown (0xC3) ", + "far pointer to 8 bit unsigned ", + "far pointer to 16 bit unsigned ", + "far pointer to 32 bit unsigned ", + "Unknown (0xC7) ", + "far pointer to 32 bit real ", + "far pointer to 64 bit real ", + "far pointer to 80 bit real ", + "Unknown (0xCB) ", + "far pointer to 64 bit complex ", + "far pointer to 128 bit complex ", + "far pointer to 160 bit complex ", + "Unknown (0xCF) ", + "far pointer to 8 bit boolean ", + "far pointer to 16 bit boolean ", + "far pointer to 32 bit boolean ", + "Unknown (0xD3) ", + "far pointer to 8 bit character ", + "far pointer to 16 bit characters ", + "far pointer to 32 bit characters ", + "far pointer to void ", + "far pointer to 15 bit unsigned ", + "far pointer to 24 bit unsigned ", + "far pointer to 31 bit unsigned ", +}; + +// Thanks to John Currier: +// Do not call 16 bit code in myHandler function to prevent call +// to __EDCThunkProlog and problems is guard page exception handling +// Also reduce the stack size to 1K for true 16 bit calls. +// 16 bit calls thunk will now only occur on fatal exceptions +#pragma stack16(1024) + +// ------------------------------------------------------------------ +// Last 8 bytes of 16:16 file when CODEVIEW debugging info is present +#pragma pack(1) +struct _eodbug +{ + unsigned short dbug; // 'NB' signature + unsigned short ver; // version + unsigned long dfaBase; // size of codeview info +} G_eodbug; + +#define DBUGSIG 0x424E +#define SSTMODULES 0x0101 +#define SSTPUBLICS 0x0102 +#define SSTTYPES 0x0103 +#define SSTSYMBOLS 0x0104 +#define SSTSRCLINES 0x0105 +#define SSTLIBRARIES 0x0106 +#define SSTSRCLINES2 0x0109 +#define SSTSRCLINES32 0x010B + +typedef struct _SYMBASE +{ + unsigned short dbug; // 'NB' signature + unsigned short ver; // version + unsigned long lfoDir; // file offset to dir entries +} SYMBASE; + +typedef struct _SSDIR +{ + unsigned short sst; // SubSection Type + unsigned short modindex; // Module index number + unsigned long lfoStart; // Start of section + unsigned short cb; // Size of section +} SSDIR; + +typedef struct _SSDIR32 +{ + unsigned short sst; // SubSection Type + unsigned short modindex; // Module index number + unsigned long lfoStart; // Start of section + unsigned long cb; // Size of section +} SSDIR32; + +typedef struct _SSMODULE +{ + unsigned short csBase; // code segment base + unsigned short csOff; // code segment offset + unsigned short csLen; // code segment length + unsigned short ovrNum; // overlay number + unsigned short indxSS; // Index into sstLib or 0 + unsigned short reserved; + BYTE csize; // size of prefix string +} SSMODULE; + +typedef struct _SSMOD32 +{ + unsigned short csBase; // code segment base + unsigned long csOff; // code segment offset + unsigned long csLen; // code segment length + unsigned long ovrNum; // overlay number + unsigned short indxSS; // Index into sstLib or 0 + unsigned long reserved; + BYTE csize; // size of prefix string +} SSMOD32; + +typedef struct _SSPUBLIC +{ + unsigned short offset; + unsigned short segment; + unsigned short type; + BYTE csize; +} SSPUBLIC; + +typedef struct _SSPUBLIC32 +{ + unsigned long offset; + unsigned short segment; + unsigned short type; + BYTE csize; +} SSPUBLIC32; + +typedef struct _SSLINEENTRY32 +{ + unsigned short LineNum; + unsigned short FileNum; + unsigned long Offset; +} SSLINEENTRY32; + +typedef struct _FIRSTLINEENTRY32 +{ + unsigned short LineNum; + unsigned char entry_type; + unsigned char reserved; + unsigned short numlines; + unsigned short segnum; +} FIRSTLINEENTRY32; + +typedef struct _SSFILENUM32 +{ + unsigned long first_displayable; // Not used + unsigned long number_displayable; // Not used + unsigned long file_count; // number of source files +} SSFILENUM32; + +/* + *@@ XDEBUGINFO: + * buffers for Read... funcs. + * + *@@added V0.9.4 (2000-06-15) [umoeller] + */ + +typedef struct _XDEBUGINFO +{ + char szNrFile[300]; // receives source file + char szNrLine[300]; // receives line number + //YD 17/07/06 c++ namespace can generate really long + //YD names, use a large buffer! + char szNrPub[16*1024]; // receives function name + + struct new_seg *pseg; + struct o32_obj *pobj; // flat .EXE object table entry + + SYMBASE base; + + SSDIR *pDirTab; + SSDIR32 *pDirTab32; + unsigned char *pEntTab; + unsigned long lfaBase; + SSMOD32 ssmod32; + SSPUBLIC32 sspub32; + + SSMODULE ssmod; + SSPUBLIC sspub; +} XDEBUGINFO, *PXDEBUGINFO; + + +USHORT _THUNK_FUNCTION (Dos16SizeSeg) (); +//APIRET16 APIENTRY16 DOS16SIZESEG(USHORT Seg, PULONG16 Size); +USHORT DosSizeSeg (USHORT Seg, PULONG16 Size) +{ + return ((USHORT) + (_THUNK_PROLOG (2+4); + _THUNK_SHORT (Seg); + _THUNK_FLAT (Size); + _THUNK_CALL (Dos16SizeSeg))); +} + +#pragma pack() + +/* ****************************************************************** + * + * PART 1: ANALYZE DEBUG CODE + * + ********************************************************************/ + +static int Read16CodeView(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName); +static int Read32PmDebug(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName); + +/* + *@@ WriteAddressInfo: + * formats and writes a line into the trap log + * file. + * + * This gets called for each line from the + * stack dump. At this point, the line in the + * trap log already has: + * + + CS:EIP : 000109FF XMLVIEW :0 + + ^^^ and we write here + * After this call, we have. + * + + CS:EIP : 000109FF XMLVIEW :0 xxx.c 123 ConfirmCreate__Fv + + ^^^ and we write here + * + *@@added V0.9.12 (2001-05-12) [umoeller] + */ + +static VOID WriteDebugInfo(FILE *LogFile, // in: open log file + PXDEBUGINFO pxdi) // in: debug info +{ + fprintf(LogFile, + "%s%s%s", + pxdi->szNrFile, + pxdi->szNrLine, + pxdi->szNrPub); +} + +/* + *@@ dbgPrintDebugInfo: + * this is the main entry point into analyzing debug + * code. + * + * This analyzes a given address and tries to find + * debug code descriptions for this address. If found, + * the information is written to the given log file. + * + * Gets called from dbgPrintStack. + * + * This returns NO_ERROR if the could was successfully + * analyzed or something != 0 if we failed. + * + * New with V0.84. + */ + +APIRET dbgPrintDebugInfo(FILE *LogFile, // out: log file to write to + CHAR *FileName, // in: EXE/DLL module file name + ULONG Object, // in: trapping object (from DosQueryModFromEIP) + ULONG TrapOffset) // in: trapping address (from DosQueryModFromEIP) +{ + APIRET rc = 0; + int ModuleFile = 0; + static struct exe_hdr OldExeHeader; + static struct new_exe NewExeHeader; + + ULONG ulSegment = Object + 1; // segment no. is object no. + 1 + + XDEBUGINFO xdi; + memset(&xdi, 0, sizeof(xdi)); + + // open the module file for reading to analyze the code + ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO); + + if (ModuleFile != -1) + { + // file found: + // read old Exe header + if (read(ModuleFile, (void*)&OldExeHeader, 64) == -1L) + { + fprintf(LogFile, "errno %d reading old exe header\n", errno); + close(ModuleFile); + return 2; + } + // seek to new Exe header + if (lseek(ModuleFile, (long)E_LFANEW(OldExeHeader), SEEK_SET) == -1L) + { + fprintf(LogFile, "errno %d seeking to new exe header\n", errno); + close(ModuleFile); + return 3; + } + if (read(ModuleFile, (void *)&NewExeHeader, 64) == -1L) + { + fprintf(LogFile, "errno %d reading new exe header\n", errno); + close(ModuleFile); + return 4; + } + + // check EXE signature + if (NE_MAGIC(NewExeHeader) == E32MAGIC) + { + /* + * flat 32 executable: + * + */ + + // do analysis for 32-bit code + if (!(rc = Read32PmDebug(LogFile, + &xdi, // output + ModuleFile, + ulSegment, + TrapOffset, + FileName))) + WriteDebugInfo(LogFile, &xdi); + + close(ModuleFile); + + // rc !=0 try with DBG file + if (rc != 0) + { + strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name + ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO); + if (ModuleFile != -1) + { + if (!(rc = Read32PmDebug(LogFile, + &xdi, + ModuleFile, + ulSegment, + TrapOffset, + FileName))) + WriteDebugInfo(LogFile, &xdi); + + close(ModuleFile); + } + } + + return rc; + } + else + { + if (NE_MAGIC(NewExeHeader) == NEMAGIC) + { + /* + * 16:16 executable: + * + */ + + if ((xdi.pseg = (struct new_seg *)calloc(NE_CSEG(NewExeHeader), + sizeof(struct new_seg))) + == NULL) + { + fprintf(LogFile, "Out of memory!"); + close(ModuleFile); + return -1; + } + if ( lseek(ModuleFile, + E_LFANEW(OldExeHeader) + NE_SEGTAB(NewExeHeader), + SEEK_SET) == -1L) + { + fprintf(LogFile, "Error %u seeking segment table in %s\n", errno, FileName); + free(xdi.pseg); + close(ModuleFile); + return 9; + } + + if (read(ModuleFile, + (void *)xdi.pseg, + NE_CSEG(NewExeHeader) * sizeof(struct new_seg)) + == -1) + { + fprintf(LogFile, "Error %u reading segment table from %s\n", errno, FileName); + free(xdi.pseg); + close(ModuleFile); + return 10; + } + + if (!(rc = Read16CodeView(LogFile, + &xdi, + ModuleFile, + ulSegment, + TrapOffset, + FileName))) + WriteDebugInfo(LogFile, &xdi); + + free(xdi.pseg); + close(ModuleFile); + + // rc !=0 try with DBG file + if (rc != 0) + { + strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name + ModuleFile = sopen(FileName, + O_RDONLY | O_BINARY, SH_DENYNO); + if (ModuleFile != -1) + { + if (!(rc = Read16CodeView(LogFile, + &xdi, + ModuleFile, + ulSegment, + TrapOffset, + FileName))) + WriteDebugInfo(LogFile, &xdi); + + close(ModuleFile); + } + } + return rc; + } + else + { + /* + * Unknown executable: + * + */ + + fprintf(LogFile, "Error, could not find exe signature"); + close(ModuleFile); + return 11; + } + } + } // end if (ModuleFile != -1) + else + { + fprintf(LogFile, "Error %d opening module file %s", errno, FileName); + return 1; + } // endif + + // return 0; we never get here +} + +char fname[256], + ModName[80]; +char ename[256], + dummy[256]; + +#define MAX_USERDEFS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller] +#define MAX_POINTERS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller] + +USHORT userdef_count; +USHORT pointer_count; + +struct one_userdef_rec +{ + USHORT idx; + USHORT type_index; + BYTE name[33]; +} one_userdef[MAX_USERDEFS]; + +struct one_pointer_rec +{ + USHORT idx; + USHORT type_index; + BYTE type_qual; + BYTE name[33]; +} one_pointer[MAX_POINTERS]; + +/* + * Read32PmDebug: + * parses 32-bit debug code. + * Called from dbgPrintDebugInfo for 32-bit modules. + */ + +static int Read32PmDebug(FILE *LogFile, // in: text log file to write to + PXDEBUGINFO pxdi, + int ModuleFile, // in: module file opened with sopen() + int TrapSeg, + int TrapOff, + CHAR *FileName) +{ + static unsigned int CurrSymSeg, NrSymbol, + /* offset, */ NrPublic, + NrFile, NrLine, /* NrEntry */ + numdir, namelen, + numlines /* , line */; + static int ModIndex; + static int bytesread, i, j; + static SSLINEENTRY32 LineEntry; + static SSFILENUM32 FileInfo; + static FIRSTLINEENTRY32 FirstLine; + static BYTE dump_vars = FALSE; + static USHORT idx; + static BOOL read_types; + static LONG lSize; + + ModIndex = 0; + // See if any CODEVIEW info + if (lseek(ModuleFile, -8L, SEEK_END) == -1) + { + fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName); + return (18); + } + + if (read(ModuleFile, + (void *)&G_eodbug, 8) + == -1) + { + fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName); + return (19); + } + if (G_eodbug.dbug != DBUGSIG) + { + // fprintf(LogFile,"\nNo CodeView information stored.\n"); + return (100); + } + + if ( (pxdi->lfaBase = lseek(ModuleFile, + -(LONG)G_eodbug.dfaBase, + SEEK_END)) + == -1L) + { + fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName); + return (20); + } + + if (read(ModuleFile, + (void *)&pxdi->base, 8) + == -1) + { + fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName); + return (21); + } + + if (lseek(ModuleFile, + pxdi->base.lfoDir - 8 + 4, + SEEK_CUR) + == -1) + { + fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName); + return (22); + } + + if (read(ModuleFile, + (void *)&numdir, 4) + == -1) + { + fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName); + return (23); + } + + // Read dir table into buffer + if ( (pxdi->pDirTab32 = (SSDIR32*)calloc(numdir, + sizeof(SSDIR32))) + == NULL) + { + fprintf(LogFile, "Out of memory!"); + return (-1); + } + + if (read(ModuleFile, + (void*)pxdi->pDirTab32, + numdir * sizeof(SSDIR32)) + == -1) + { + fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName); + free(pxdi->pDirTab32); + return (24); + } + + i = 0; + while (i < numdir) + { + if (pxdi->pDirTab32[i].sst != SSTMODULES) + { + i++; + continue; + } + + NrPublic = 0x0; + NrSymbol = 0; + NrLine = 0x0; + NrFile = 0x0; + CurrSymSeg = 0; + // point to subsection + lseek(ModuleFile, + pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase, + SEEK_SET); + read(ModuleFile, + (void*)&pxdi->ssmod32.csBase, + sizeof(SSMOD32)); + read(ModuleFile, + (void*)ModName, + (unsigned)pxdi->ssmod32.csize); + ModIndex = pxdi->pDirTab32[i].modindex; + ModName[pxdi->ssmod32.csize] = '\0'; + i++; + + read_types = FALSE; + + while ( (pxdi->pDirTab32[i].modindex == ModIndex) + && (i < numdir) + ) + { + // point to subsection + lseek(ModuleFile, + pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase, + SEEK_SET); + + switch (pxdi->pDirTab32[i].sst) + { + case SSTPUBLICS: + bytesread = 0; + while (bytesread < pxdi->pDirTab32[i].cb) + { + bytesread += read(ModuleFile, + (void *)&pxdi->sspub32.offset, + sizeof(pxdi->sspub32)); + bytesread += read(ModuleFile, + (void*)ename, + (unsigned)pxdi->sspub32.csize); + ename[pxdi->sspub32.csize] = '\0'; + if ( (pxdi->sspub32.segment == TrapSeg) + && (pxdi->sspub32.offset <= TrapOff) + && (pxdi->sspub32.offset >= NrPublic) + ) + { + NrPublic = pubfunc_ofs = pxdi->sspub32.offset; + read_types = TRUE; + sprintf(pxdi->szNrPub, + "%s %s (%s)\n", + (pxdi->sspub32.type == 1) + ? " Abs" + : " ", + ename, + ModName + ); + // but continue, because there might be a + // symbol that comes closer + } + } + break; + + // Read symbols, so we can dump the variables on the stack + case SSTSYMBOLS: + if (TrapSeg != pxdi->ssmod32.csBase) + break; + + bytesread = 0; + while (bytesread < pxdi->pDirTab32[i].cb) + { + static USHORT usLength; + static USHORT usLengthSym; + static BYTE b1, + b2; + static BYTE bType; + // *ptr; + static ULONG ofs; + // static ULONG last_addr = 0; + //YD 17/07/06 c++ namespace can generate really long + //YD names, use a large buffer! + static BYTE str[16*1024]; + static struct symseg_rec symseg; + static struct symauto_rec symauto; + static struct symproc_rec symproc; + + // Read the length of this subentry + bytesread += read(ModuleFile, &b1, 1); + if (b1 & 0x80) + { + bytesread += read(ModuleFile, &b2, 1); + usLength = ((b1 & 0x7F) << 8) + b2; + } + else + usLength = b1; + + ofs = tell(ModuleFile); + + bytesread += read(ModuleFile, &bType, 1); + + switch (bType) + { + case SYM_CHANGESEG: + read(ModuleFile, &symseg, sizeof(symseg)); + CurrSymSeg = symseg.seg_no; + break; + + case SYM_PROC: + case SYM_CPPPROC: + read(ModuleFile, &symproc, sizeof(symproc)); + if (symproc.name_len & 0x80) + { + read(ModuleFile, &b2, 1); + usLengthSym = ((symproc.name_len & 0x7F) << 8) + b2; + } + else + { + usLengthSym = symproc.name_len; + } + read(ModuleFile, str, usLengthSym); + str[usLengthSym] = 0; + + if ((CurrSymSeg == TrapSeg) && + (symproc.offset <= TrapOff) && + (symproc.offset >= NrSymbol)) + { + + dump_vars = TRUE; + var_ofs = 0; + NrSymbol = symproc.offset; + func_ofs = symproc.offset; + + strcpy(func_name, str); + } + else + { + dump_vars = FALSE; + } + break; + + case SYM_AUTO: + if (!dump_vars) + break; + + read(ModuleFile, &symauto, sizeof(symauto)); + read(ModuleFile, str, symauto.name_len); + if (symauto.name_len==0x80) + printf("symauto.name_len==0x80\n"); + str[symauto.name_len] = 0; + + strcpy(autovar_def[var_ofs].name, str); + autovar_def[var_ofs].stack_offset = symauto.stack_offset; + autovar_def[var_ofs].type_idx = symauto.type_idx; + var_ofs++; + break; + + } + + bytesread += usLength; + + lseek(ModuleFile, ofs + usLength, SEEK_SET); + } + break; + + case SSTTYPES: + // if (ModIndex != TrapSeg) + if (!read_types) + break; + + bytesread = 0; + idx = 0x200; + userdef_count = 0; + pointer_count = 0; + while (bytesread < pxdi->pDirTab32[i].cb) + { + static struct type_rec type; + static struct type_userdefrec udef; + static struct type_pointerrec point; + static ULONG ofs; + static BYTE str[256]; + + // Read the length of this subentry + ofs = tell(ModuleFile); + + read(ModuleFile, &type, sizeof(type)); + bytesread += sizeof(type); + + switch (type.type) + { + case TYPE_USERDEF: + if (userdef_count >= MAX_USERDEFS) + break; + + read(ModuleFile, &udef, sizeof(udef)); + read(ModuleFile, str, udef.name_len); + str[udef.name_len] = 0; + + // Insert userdef in table + one_userdef[userdef_count].idx = idx; + one_userdef[userdef_count].type_index = udef.type_index; + memcpy(one_userdef[userdef_count].name, + str, + _min(udef.name_len + 1, 32)); + one_userdef[userdef_count].name[32] = 0; + userdef_count++; + break; + + case TYPE_POINTER: + if (pointer_count >= MAX_POINTERS) + break; + + read(ModuleFile, &point, sizeof(point)); + read(ModuleFile, str, point.name_len); + str[point.name_len] = 0; + + // Insert userdef in table + one_pointer[pointer_count].idx = idx; + one_pointer[pointer_count].type_index = point.type_index; + memcpy(one_pointer[pointer_count].name, + str, + _min(point.name_len + 1, 32)); + one_pointer[pointer_count].name[32] = 0; + one_pointer[pointer_count].type_qual = type.type_qual; + pointer_count++; + break; + } + + ++idx; + + bytesread += type.length; + + lseek(ModuleFile, ofs + type.length + 2, SEEK_SET); + } + break; + + case SSTSRCLINES32: + if (TrapSeg != pxdi->ssmod32.csBase) + break; + + // read first line + do + { + read(ModuleFile, (void *)&FirstLine, sizeof(FirstLine)); + + if (FirstLine.LineNum != 0) + { + fprintf(LogFile, "Missing Line table information\n"); + break; + } // endif + numlines = FirstLine.numlines; + // Other type of data skip 4 more bytes + if (FirstLine.entry_type < 4) + { + read(ModuleFile, (void *)&lSize, 4); + if (FirstLine.entry_type == 3) + lseek(ModuleFile, lSize, SEEK_CUR); + } + } + while (FirstLine.entry_type == 3); + + for (j = 0; j < numlines; j++) + { + switch (FirstLine.entry_type) + { + case 0: + read(ModuleFile, (void *)&LineEntry, sizeof(LineEntry)); + // Changed by Kim Rasmussen 26/06 1996 to ignore linenumber 0 + // if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) { + if ( (LineEntry.LineNum) + && (LineEntry.Offset + pxdi->ssmod32.csOff + <= TrapOff) + && (LineEntry.Offset + pxdi->ssmod32.csOff >= NrLine) + ) + { + NrLine = LineEntry.Offset; + NrFile = LineEntry.FileNum; + /*pOffset =sprintf(szNrLine,"%04X:%08X line #%hu ", + * ssmod32.csBase,LineEntry.Offset, + * LineEntry.LineNum); */ + sprintf(pxdi->szNrLine, "% 6hu", LineEntry.LineNum); + } + break; + + case 1: + lseek(ModuleFile, sizeof(struct linlist_rec), SEEK_CUR); + break; + + case 2: + lseek(ModuleFile, sizeof(struct linsourcelist_rec), SEEK_CUR); + break; + + case 3: + lseek(ModuleFile, sizeof(struct filenam_rec), SEEK_CUR); + break; + + case 4: + lseek(ModuleFile, sizeof(struct pathtab_rec), SEEK_CUR); + break; + + } + } + + if (NrFile != 0) + { + // file found: + read(ModuleFile, (void*)&FileInfo, sizeof(FileInfo)); + namelen = 0; + for (j = 1; j <= FileInfo.file_count; j++) + { + namelen = 0; + read(ModuleFile, (void *)&namelen, 1); + read(ModuleFile, (void *)ename, namelen); + if (j == NrFile) + break; + } + ename[namelen] = '\0'; + // pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName); + sprintf(pxdi->szNrFile, "%11.11s ", ename); + } + else + { + // strcat(szNrLine,"\n"); avoid new line for empty name fill + strcpy(pxdi->szNrFile, "file? "); + } // endif + break; + } // end switch + + i++; + } // end while modindex + } // End While i < numdir + free(pxdi->pDirTab32); + return (0); +} + +/* + * Read16CodeView: + * parses 16-bit debug code. + * Called from dbgPrintDebugInfo for 16-bit modules. + */ + +static int Read16CodeView(FILE *LogFile, // in: text log file to write to + PXDEBUGINFO pxdi, + int fh, + int TrapSeg, + int TrapOff, + CHAR *FileName) +{ + static unsigned short int offset, + NrPublic, NrLine, + numdir, + namelen, numlines, + line; + static int ModIndex; + static int bytesread, i, j; + + ModIndex = 0; + // See if any CODEVIEW info + if (lseek(fh, -8L, SEEK_END) == -1) + { + fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName); + return (18); + } + + if (read(fh, (void *)&G_eodbug, 8) == -1) + { + fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName); + return (19); + } + if (G_eodbug.dbug != DBUGSIG) + { + // fprintf(LogFile,"\nNo CodeView information stored.\n"); + return (100); + } + + if ((pxdi->lfaBase = lseek(fh, -(LONG)G_eodbug.dfaBase, SEEK_END)) == -1L) + { + fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName); + return (20); + } + + if (read(fh, (void *)&pxdi->base, 8) == -1) + { + fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName); + return (21); + } + + if (lseek(fh, pxdi->base.lfoDir - 8, SEEK_CUR) == -1) + { + fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName); + return (22); + } + + if (read(fh, (void *)&numdir, 2) == -1) + { + fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName); + return (23); + } + + // Read dir table into buffer + if ((pxdi->pDirTab = (SSDIR*)calloc(numdir, sizeof(SSDIR))) == NULL) + { + fprintf(LogFile, "Out of memory!"); + return (-1); + } + + if (read(fh, (void*)pxdi->pDirTab, numdir * sizeof(SSDIR)) == -1) + { + fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName); + free(pxdi->pDirTab); + return (24); + } + + i = 0; + while (i < numdir) + { + if (pxdi->pDirTab[i].sst != SSTMODULES) + { + i++; + continue; + } + NrPublic = 0x0; + NrLine = 0x0; + // point to subsection + lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET); + read(fh, (void *)&pxdi->ssmod.csBase, sizeof(SSMODULE)); + read(fh, (void *)ModName, (unsigned)pxdi->ssmod.csize); + ModIndex = pxdi->pDirTab[i].modindex; + ModName[pxdi->ssmod.csize] = '\0'; + i++; + while (pxdi->pDirTab[i].modindex == ModIndex && i < numdir) + { + // point to subsection + lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET); + switch (pxdi->pDirTab[i].sst) + { + case SSTPUBLICS: + bytesread = 0; + while (bytesread < pxdi->pDirTab[i].cb) + { + bytesread += read(fh, (void *)&pxdi->sspub.offset, sizeof(pxdi->sspub)); + bytesread += read(fh, (void *)ename, (unsigned)pxdi->sspub.csize); + ename[pxdi->sspub.csize] = '\0'; + if ((pxdi->sspub.segment == TrapSeg) && + (pxdi->sspub.offset <= TrapOff) && + (pxdi->sspub.offset >= NrPublic)) + { + NrPublic = pxdi->sspub.offset; + sprintf(pxdi->szNrPub, "%s %s (%s) %04hX:%04hX\n", + (pxdi->sspub.type == 1) ? " Abs" : " ", ename, + ModName, // () + pxdi->sspub.segment, + pxdi->sspub.offset + ); + } + } + break; + + case SSTSRCLINES2: + case SSTSRCLINES: + if (TrapSeg != pxdi->ssmod.csBase) + break; + namelen = 0; + read(fh, (void *)&namelen, 1); + read(fh, (void *)ename, namelen); + ename[namelen] = '\0'; + // skip 2 zero bytes + if (pxdi->pDirTab[i].sst == SSTSRCLINES2) + read(fh, (void *)&numlines, 2); + read(fh, (void *)&numlines, 2); + for (j = 0; j < numlines; j++) + { + read(fh, (void *)&line, 2); + read(fh, (void *)&offset, 2); + if (offset <= TrapOff && offset >= NrLine) + { + NrLine = offset; + sprintf(pxdi->szNrFile, "% 12.12s ", ename); + sprintf(pxdi->szNrLine, "% 6hu", line); + /*sprintf(szNrLine,"%04hX:%04hX line #%hu (%s) (%s)\n", + * ssmod.csBase,offset,line,ModName,ename); */ + } + } + break; + } // end switch + i++; + } // end while modindex + } // End While i < numdir + free(pxdi->pDirTab); + return (0); +} + +/* ****************************************************************** + * + * PART 2: ANALYZE VARIABLES + * + ********************************************************************/ + +/* + * var_value: + * writes a description of a variable type to + * the specified buffer, depending on "type". + * + *@@changed V0.9.1 (2000-01-30) [umoeller]: changed prototype to use external buffer + */ + +static VOID var_value(void *varptr, // in: address of the variable on the stack + char *pszBuf, // out: information + BYTE type) // in: type; if >= 32, we'll call DosQueryMem +{ + ULONG Size = 1, + Attr = 0; + + if (DosQueryMem(varptr, &Size, &Attr) != NO_ERROR) + { + sprintf(pszBuf, "type %d, DosQueryMem failed", type); + return; + } + + if ((Attr & PAG_READ) == 0) + { + sprintf(pszBuf, "type %d, read-access to value denied", type); + return; + } + + if (type == 0) + sprintf(pszBuf, "%hd", *(signed char*)varptr); + else if (type == 1) + sprintf(pszBuf, "%hd", *(signed short*)varptr); + else if (type == 2) + sprintf(pszBuf, "%ld", *(signed long*)varptr); + else if (type == 4) + sprintf(pszBuf, "%hu", *(BYTE*) varptr); + else if (type == 5) + sprintf(pszBuf, "%hu", *(USHORT*)varptr); + else if (type == 6) + sprintf(pszBuf, "0x%lX (%lu)", *((ULONG*)varptr), *((ULONG*)varptr)); + else if (type == 8) + sprintf(pszBuf, "%f", *(float*)varptr); + else if (type == 9) + sprintf(pszBuf, "%f", *(double*)varptr); + else if (type == 10) + sprintf(pszBuf, "%f", (double)(*(long double*)varptr)); + else if (type == 16) + sprintf(pszBuf, "%s", *(char*)varptr ? "TRUE" : "FALSE"); + else if (type == 17) + sprintf(pszBuf, "%s", *(short*)varptr ? "TRUE" : "FALSE"); + else if (type == 18) + sprintf(pszBuf, "%s", *(long*)varptr ? "TRUE" : "FALSE"); + else if (type == 20) + sprintf(pszBuf, "%c", *(char*)varptr); + else if (type == 21) + sprintf(pszBuf, "%hd", (*(short*)varptr)); + else if (type == 22) + sprintf(pszBuf, "%ld", *(long*)varptr); + else if (type == 23) + sprintf(pszBuf, "void"); + else if (type >= 32) + { + sprintf(pszBuf, "0x%p", (void*)(*(ULONG*)varptr)); + if (Attr & PAG_FREE) + { + strcat(pszBuf, " unallocated memory"); + } + else + { + if ((Attr & PAG_COMMIT) == 0x0U) + { + strcat(pszBuf, " uncommitted"); + } // endif + if ((Attr & PAG_WRITE) == 0x0U) + { + strcat(pszBuf, " unwritable"); + } // endif + if ((Attr & PAG_READ) == 0x0U) + { + strcat(pszBuf, " unreadable"); + } // endif + } // endif + } // endif + else + sprintf(pszBuf, "Unknown type %d", type); +} + +/* + * search_userdefs: + * searches the table of userdef's- + * Return TRUE if found. + */ + +static BOOL search_userdefs(FILE *LogFile, // in: text log file to write to + ULONG stackofs, + USHORT var_no) +{ + USHORT pos; + + for (pos = 0; + pos < userdef_count; + pos++) + { + if (one_userdef[pos].idx == autovar_def[var_no].type_idx) + { + if ( (one_userdef[pos].type_index >= 0x80) + // && (one_userdef[pos].type_index <= 0xDA) + ) + { + static char sszVar3[500] = "complex"; + if (one_userdef[pos].type_index <= 0xDA) + var_value((void*)(stackofs + autovar_def[var_no].stack_offset), + sszVar3, + one_userdef[pos].type_index - 0x80); + + fprintf(LogFile, + " %- 6ld %- 20.20s %- 33.33s %s (user)\n", + autovar_def[var_no].stack_offset, // stack offset + autovar_def[var_no].name, // identifier + one_userdef[pos].name, // type name + sszVar3 // composed by var_value + ); + return TRUE; + } + else + return FALSE; + } + } + + return FALSE; +} + +/* + * search_pointers: + * + */ + +static BOOL search_pointers(FILE *LogFile, // in: text log file to write to + ULONG stackofs, + USHORT var_no) +{ + USHORT pos, upos; + static BYTE str[35]; + static char sszVar[500]; + + // BYTE type_index; + + for (pos = 0; + ( (pos < pointer_count) + && (one_pointer[pos].idx != autovar_def[var_no].type_idx) + ); + pos++); + + if (pos < pointer_count) + { + if ( (one_pointer[pos].type_index >= 0x80) + && (one_pointer[pos].type_index <= 0xDA) + ) + { + strcpy(str, type_name[one_pointer[pos].type_index - 0x80]); + strcat(str, " *"); + var_value((void*)(stackofs + autovar_def[var_no].stack_offset), + sszVar, + 32); + fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr1)\n", + autovar_def[var_no].stack_offset, + autovar_def[var_no].name, + str, + sszVar); + return TRUE; + } + else + { + // If the result isn't a simple type, look for it in the other lists + for (upos = 0; + ( (upos < userdef_count) + && (one_userdef[upos].idx != one_pointer[pos].type_index) + ); + upos++) + ; + + if (upos < userdef_count) + { + strcpy(str, one_userdef[upos].name); + strcat(str, " *"); + var_value((void *)(stackofs + autovar_def[var_no].stack_offset), + sszVar, + 32); + fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr2)\n", + autovar_def[var_no].stack_offset, + autovar_def[var_no].name, + str, + sszVar); + return TRUE; + } + else + { + // if it isn't a userdef, for now give up and just print + // as much as we know + sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index); + + var_value((void *)(stackofs + autovar_def[var_no].stack_offset), + sszVar, + 32); + fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr3)\n", + autovar_def[var_no].stack_offset, + autovar_def[var_no].name, + str, + sszVar); + + return TRUE; + } + } + } + + return FALSE; +} + +/* + *@@ dbgPrintVariables: + * Dumps variables for the specified stack offset + * to the specified log file. + * + * New with V0.84. + */ + +void dbgPrintVariables(FILE *LogFile, // in: text log file to write to + ULONG stackofs) +{ + USHORT n; // , pos; + BOOL AutoVarsFound = FALSE; + + if (/* 1 || */ func_ofs == pubfunc_ofs) + { + for (n = 0; + n < var_ofs; + n++) + { + if (AutoVarsFound == FALSE) + { + AutoVarsFound = TRUE; + fprintf(LogFile, " List of auto variables at EBP %p in %s:\n", + (PVOID)stackofs, + func_name); + fprintf(LogFile, " Offset Name Type Value \n"); + fprintf(LogFile, " ������ �������������������� ��������������������������������� �����������������\n"); + } + + // If it's one of the simple types + if ( (autovar_def[n].type_idx >= 0x80) + && (autovar_def[n].type_idx <= 0xDA) + ) + { + static char sszVar2[500]; + + var_value((void *)(stackofs + autovar_def[n].stack_offset), + sszVar2, + autovar_def[n].type_idx - 0x80); + + fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (simple)\n", + autovar_def[n].stack_offset, + autovar_def[n].name, + type_name[autovar_def[n].type_idx - 0x80], + sszVar2); + } + else + { // Complex type, check if we know what it is + if (!search_userdefs(LogFile, stackofs, n)) + { + if (!search_pointers(LogFile, stackofs, n)) + { + fprintf(LogFile, " %- 6ld %-20.20s 0x%X (unknown)\n", + autovar_def[n].stack_offset, + autovar_def[n].name, + autovar_def[n].type_idx); + } + } + } + } + /* if (AutoVarsFound == FALSE) + { + fprintf(LogFile, " No auto variables found in %s.\n", func_name); + } */ + fprintf(LogFile, "\n"); + } +} + +/* ****************************************************************** + * + * PART 3: ANALYZE SYMBOL (.SYM) FILE + * + ********************************************************************/ + +/* + *@@ dbgPrintSYMInfo: + * this gets called by dbgPrintStack if dbgPrintDebugInfo + * failed (because no debug code was found) to check if + * maybe a SYM file with the same filename exists and try + * to get the info from there. + * + * This gets called for every line of the stack + * walk, but only if getting the information from + * the debug code failed, e.g. because no debug code + * was available for an address. + * + * The file pointer is in the "Source file" column + * every time this gets called. + * + * New with V0.84. + * + * Returns 0 if reading the SYM file was successful. + * + *@@changed V0.9.1 (2000-01-30) [umoeller]: added return code; this used to be VOID + */ + +int dbgPrintSYMInfo(FILE *LogFile, // in: text log file to write to + CHAR *SymFileName, // in: SYM file name (can be fully q'fied) + ULONG Object, + ULONG TrapOffset) +{ + static FILE *SymFile; + static MAPDEF MapDef; + static SEGDEF SegDef; + static SYMDEF32 SymDef32; + static SYMDEF16 SymDef16; + static char Buffer[256]; + static int SegNum, SymNum, LastVal; + static unsigned long int SegOffset, + SymOffset, SymPtrOffset; + + // open .SYM file +#ifdef DEBUG_SYMDUMP + fprintf(LogFile,"Dump of '%s' for object %d\n",SymFileName,Object); +#endif + SymFile = fopen(SymFileName, "rb"); + if (SymFile == 0) + return (2); + + // read in first map definition + fread(&MapDef, sizeof(MAPDEF), 1, SymFile); +#ifdef DEBUG_SYMDUMP + Buffer[0] = MapDef.achModName[0]; + fread(&Buffer[1], 1, MapDef.cbModName-1, SymFile); + Buffer[MapDef.cbModName] = 0x00; + fprintf(LogFile,"Module name '%s'\n",Buffer); +#endif + + SegOffset = SEGDEFOFFSET(MapDef); +#ifdef DEBUG_SYMDUMP + fprintf(LogFile,"SegOffset %0x\n",SegOffset); +#endif + + // go thru all segments + for (SegNum = 0; + SegNum < MapDef.cSegs; + SegNum++) + { +#ifdef DEBUG_SYMDUMP + fprintf(LogFile,"Scanning segment #%d Offset %08X\n",SegNum,SegOffset); +#endif + if (fseek(SymFile, SegOffset, SEEK_SET)) + // seek error + return (3); + + // read in segment definition + fread(&SegDef, sizeof(SEGDEF), 1, SymFile); +#ifdef DEBUG_SYMDUMP + Buffer[0] = 0x00; + if (SegDef.cbSegName>0) { + Buffer[0] = SegDef.achSegName[0]; + fread(&Buffer[1], 1, SegDef.cbSegName-1, SymFile); + Buffer[SegDef.cbSegName] = 0x00; + } + fprintf(LogFile,"Segment name '%s', number %d, flags %02x\n",Buffer,SegNum,SegDef.bFlags); +#endif + + if (SegNum == Object) + { + // stack object found: + Buffer[0] = 0x00; + LastVal = 0; + + // go thru all symbols in this object +#ifdef DEBUG_SYMDUMP + fprintf(LogFile,"Scanning #%d symbols\n",SegDef.cSymbols); +#endif + for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++) + { + SymPtrOffset=SYMDEFOFFSET(SegOffset,SegDef,SymNum); + fseek(SymFile,SymPtrOffset,SEEK_SET); + fread(&SymOffset,sizeof(unsigned short int),1,SymFile); + fseek(SymFile,SymOffset+SegOffset,SEEK_SET); + if (SegDef.bFlags & 0x01) + { + // 32-bit symbol: + fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile); + if (SymDef32.wSymVal > TrapOffset) + { + // symbol found + fprintf(LogFile, + "between %s + 0x%lX ", + Buffer, + TrapOffset - LastVal); + /* fprintf(LogFile, "(ppLineDef: 0x%lX) ", + LINEDEFOFFSET(SegDef) + ); */ + fprintf(LogFile, "\n"); + } + + LastVal = SymDef32.wSymVal; + Buffer[0] = SymDef32.achSymName[0]; + fread(&Buffer[1], 1, SymDef32.cbSymName-1, SymFile); + Buffer[SymDef32.cbSymName] = 0x00; +#ifdef DEBUG_SYMDUMP + fprintf(LogFile,"32 Bit Symbol Address %08p <%s> \n",SymDef32.wSymVal,Buffer); +#endif + + if (SymDef32.wSymVal > TrapOffset) + { + // symbol found, as above + fprintf(LogFile, + " " + "and %s - 0x%lX ", + Buffer, + LastVal - TrapOffset); + fprintf(LogFile, "\n"); + break; + } + } + else + { + // 16-bit symbol: + fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile); + if (SymDef16.wSymVal > TrapOffset) + { + fprintf(LogFile, + "between %s + %lX\n", + Buffer, + TrapOffset - LastVal); + } + LastVal = SymDef16.wSymVal; + Buffer[0] = SymDef16.achSymName[0]; + fread(&Buffer[1], 1, SymDef16.cbSymName-1, SymFile); + Buffer[SymDef16.cbSymName] = 0x00; + if (SymDef16.wSymVal > TrapOffset) + { + fprintf(LogFile, + " " + "and %s - %lX\n", + Buffer, + LastVal - TrapOffset); + break; + } +#ifdef DEBUG_SYMDUMP + fprintf(LogFile,"16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal); +#endif + } // endif + } + break; + } // endif + SegOffset = NEXTSEGDEFOFFSET(SegDef); + } // endwhile + fclose(SymFile); + return (0); // no error +} + +/* ****************************************************************** + * + * PART 4: dbgPrintStack + * + ********************************************************************/ + +/* + *@@ dbgPrintStackFrame: + * parses and dumps one stack frame. + * Called from excPrintStackFrame. + * + * This calls dbgPrintDebugInfo and, if + * that fails, dbgPrintSYMInfo. + * + *@@added V0.9.2 (2000-03-10) [umoeller] + *@@changed V0.9.3 (2000-04-10) [umoeller]: added support for non-Warp 4 SYM files + *@@changed V0.9.3 (2000-04-26) [umoeller]: this broke Warp 4 FP 13, fixed + */ + +BOOL dbgPrintStackFrame(FILE *LogFile, + PSZ pszModuleName, // in: module name (fully q'fied) + ULONG ulObject, + ULONG ulOffset) +{ + APIRET arc = 0; + // "Source file"... columns + +//YD do not use debug info +#define ENABLE_DEBUG_INFO +#ifdef ENABLE_DEBUG_INFO + // first attempt to analyze the debug code + arc = dbgPrintDebugInfo(LogFile, + pszModuleName, + ulObject, + ulOffset); +#else + arc = 1; +#endif + + // if no debug code is available, analyze + // the SYM file instead + if (arc != NO_ERROR) + { + CHAR szSymName[CCHMAXPATH]; + strcpy(szSymName, pszModuleName); + strcpy(szSymName + strlen(szSymName) - 3, "SYM"); + arc = dbgPrintSYMInfo(LogFile, + szSymName, + ulObject, + ulOffset); + if (arc != 0) + { + // SYM file not found in current directory: + // check the SYM files in the \OS2 directory, + // depending on the OS/2 version level: + CHAR szSymFile2[CCHMAXPATH]; + PSZ pszFilename = strrchr(szSymName, '\\'); + if (pszFilename) + { + PSZ pszVersionDir = "WARP4"; + ULONG aulBuf[3]; + + DosQuerySysInfo(QSV_VERSION_MAJOR, // 11 + QSV_VERSION_MINOR, // 12 + &aulBuf, sizeof(aulBuf)); + // Warp 3 is reported as 20.30 + // Warp 4 is reported as 20.40 + // Aurora is reported as 20.45 + + if (aulBuf[0] == 20) + { + if (aulBuf[1] == 30) + // Warp 3: + pszVersionDir = "WARP3"; + else if (aulBuf[1] >= 40) + // Warp 4 or higher: + // (NOTE: Warp 4 FP 13 now returns 45 also, + // but the SYM files are still in the WARP4 directory...) + // V0.9.3 (2000-04-26) [umoeller] + pszVersionDir = "WARP4"; + } + + pszFilename++; + sprintf(szSymFile2, + "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s", + doshQueryBootDrive(), + pszVersionDir, + pszFilename); + arc = dbgPrintSYMInfo(LogFile, + szSymFile2, + ulObject, + ulOffset); + + // V0.9.3 (2000-04-26) [umoeller] + if ( (arc != 0) // still not found + && (aulBuf[1] == 45) // and running Aurora or Warp 4 FP13? + ) + { + // Warp Server for e-Business (aka Warp 4.5): + // we use the SYM files for the UNI kernel, + // I have found no way to find out whether + // we're running on an SMP kernel + sprintf(szSymFile2, + "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s", + doshQueryBootDrive(), + "WARP45_U", + pszFilename); + arc = dbgPrintSYMInfo(LogFile, + szSymFile2, + ulObject, + ulOffset); + } + } + } + + if (arc == 2) // file not found + fprintf(LogFile, + "Cannot find symbol file %s\n", + szSymName); + else if (arc != 0) + fprintf(LogFile, + "Error %lu reading symbol file %s\n", + arc, + szSymName); + } + + return (arc == NO_ERROR); +} + +/* + *@@ dbgPrintStack: + * this takes stack data from the TIB and + * context record data structures and tries + * to analyse what the different stack frames + * point to. + * + * For each stack frame, this calls dbgPrintDebugInfo, + * and, if that fails, dbgPrintSYMInfo. + * + * New with V0.84. + * + *@@changed V0.9.2 (2000-03-08) [umoeller]: now searching OS2\PDPSI\PMDF for SYM files also + */ + +VOID dbgPrintStack(FILE *LogFile, // in: text log file to write to + PUSHORT StackBottom, + PUSHORT StackTop, + PUSHORT Ebp, + PUSHORT ExceptionAddress) +{ + PUSHORT RetAddr = 0; + PUSHORT LastEbp = 0; + APIRET rc = 0; + ULONG Size = 0, + Attr = 0; + USHORT Cs = 0, + Ip = 0, + // Bp, + Sp = 0; + static char Name[CCHMAXPATH]; + HMODULE hMod = 0; + ULONG ObjNum = 0; + ULONG Offset = 0; + BOOL fExceptionAddress = TRUE; // Use Exception Addr 1st time thru + + // Note: we can't handle stacks bigger than 64K for now... + Sp = (USHORT) (((ULONG) StackBottom) >> 16); + // Bp = ; + + if (!f32bit) + Ebp = (PUSHORT) MAKEULONG(((USHORT)(ULONG)Ebp), Sp); + + fprintf(LogFile, "\n\nCall stack:\n"); + fprintf(LogFile, " Source Line Nearest\n"); + fprintf(LogFile, " EBP Address Module Obj# File Numbr Public Symbol\n"); + fprintf(LogFile, " �������� ��������- �������� ���� ������������ ����� ������������-\n"); + + do + { + Size = 10; + rc = DosQueryMem((PVOID) (Ebp + 2), &Size, &Attr); + if (rc != NO_ERROR) + { + fprintf(LogFile, "Invalid EBP %8.8lX (DosQueryMem returned %lu)\n", (ULONG)Ebp, rc); + break; + } + if (!(Attr & PAG_COMMIT)) + { + fprintf(LogFile, "Invalid EBP %8.8lX (not committed)\n", (ULONG)Ebp); + break; + } + if (Size < 10) + { + fprintf(LogFile, "Invalid EBP %8.8lX (mem block size < 10)\n", (ULONG)Ebp); + break; + } + + if (fExceptionAddress) + RetAddr = ExceptionAddress; + else + RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2))); + + if (RetAddr == (PUSHORT) 0x00000053) + { + // For some reason there's a "return address" of 0x53 following + // EBP on the stack and we have to adjust EBP by 44 bytes to get + // at the real return address. This has something to do with + // thunking from 32bits to 16bits... + // Serious kludge, and it's probably dependent on versions of C(++) + // runtime or OS, but it works for now! + Ebp += 22; + RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2))); + } + + // Get the (possibly) 16bit CS and IP + if (fExceptionAddress) + { + Cs = (USHORT) (((ULONG) ExceptionAddress) >> 16); + Ip = (USHORT) (ULONG) ExceptionAddress; + } + else + { + Cs = *(Ebp + 2); + Ip = *(Ebp + 1); + } + + // if the return address points to the stack then it's really just + // a pointer to the return address (UGH!). + if ( (USHORT) (((ULONG) RetAddr) >> 16) == Sp + ) + RetAddr = (PUSHORT) (*((PULONG) RetAddr)); + + if (Ip == 0 && *Ebp == 0) + { + // End of the stack so these are both shifted by 2 bytes: + Cs = *(Ebp + 3); + Ip = *(Ebp + 2); + } + + // 16bit programs have on the stack: + // BP:IP:CS + // where CS may be thunked + // + // in dump swapped + // BP IP CS BP CS IP + // 4677 53B5 F7D0 7746 D0F7 B553 + // + // 32bit programs have: + // EBP:EIP + // and you'd have something like this (with SP added) (not + // accurate values) + // + // in dump swapped + // EBP EIP EBP EIP + // 4677 2900 53B5 F7D0 0029 7746 D0F7 B553 + // + // So the basic difference is that 32bit programs have a 32bit + // EBP and we can attempt to determine whether we have a 32bit + // EBP by checking to see if its 'selector' is the same as SP. + // Note that this technique limits us to checking stacks < 64K. + // + // Soooo, if IP (which maps into the same USHORT as the swapped + // stack page in EBP) doesn't point to the stack (i.e. it could + // be a 16bit IP) then see if CS is valid (as is or thunked). + // + // Note that there's the possibility of a 16bit return address + // that has an offset that's the same as SP so we'll think it's + // a 32bit return address and won't be able to successfully resolve + // its details. + if (Ip != Sp) + { + if (DosSizeSeg(Cs, &Size) == NO_ERROR) + { + RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs); + f32bit = FALSE; + } + else if (DosSizeSeg((Cs << 3) + 7, &Size) == NO_ERROR) + { + Cs = (Cs << 3) + 7; + RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs); + f32bit = FALSE; + } + else + f32bit = TRUE; + } + else + f32bit = TRUE; + + + // "EBP" column + if (fExceptionAddress) + fprintf(LogFile, " Trap -> "); + else + fprintf(LogFile, " %8.8lX ", (ULONG)Ebp); + + // "Address" column + if (f32bit) + fprintf(LogFile, ":%8.8lX ", (ULONG)RetAddr); + else + fprintf(LogFile, "%04.04X:%04.04X ", Cs, Ip); + + // Version check omitted; the following requires + // OS/2 2.10 or later (*UM) + // if (Version[0] >= 20 && Version[1] >= 10) + { + // Make a 'tick' sound to let the user know we're still alive + DosBeep(2000, 10); + + Size = 10; // Inserted by Kim Rasmussen 26/06 1996 to avoid error 87 when Size is 0 + + // "Module"/"Object" columns + rc = DosQueryMem((PVOID) RetAddr, &Size, &Attr); + if (rc != NO_ERROR || !(Attr & PAG_COMMIT)) + { + fprintf(LogFile, "Invalid RetAddr: %8.8lX\n", (ULONG)RetAddr); + break; // avoid infinite loops + } + else + { + rc = DosQueryModFromEIP(&hMod, + &ObjNum, + sizeof(Name), Name, + &Offset, + (PVOID)RetAddr); + if ( (rc == NO_ERROR) + // && (ObjNum != -1) + ) + { + // static char szJunk[_MAX_FNAME]; + static char szName[_MAX_FNAME]; + + DosQueryModuleName(hMod, sizeof(Name), Name); + // _splitpath(Name, szJunk, szJunk, szName, szJunk); + + // print module and object + fprintf(LogFile, "%-8s %04lX ", szName, ObjNum + 1); + + if (strlen(Name) > 3) + { + dbgPrintStackFrame(LogFile, + Name, + ObjNum, + Offset); + } + } + else + fprintf(LogFile, + "DosQueryModFromEIP failed, returned %lu\n", + rc); + } + } + + if ( ((*Ebp) == 0) + && ((*Ebp + 1) == 0) + ) + { + fprintf(LogFile, "End of call stack\n"); + break; + } + + if (!fExceptionAddress) + { + LastEbp = Ebp; +#if 0 + Ebp = (PUSHORT) MAKEULONG(Bp, Sp); +#else // Inserted by Kim Rasmussen 26/06 1996 to allow big stacks + if (f32bit) + Ebp = (PUSHORT) *(PULONG) LastEbp; + else + Ebp = (PUSHORT) MAKEULONG((*Ebp), Sp); +#endif + if (f32bit) + { + dbgPrintVariables(LogFile, (ULONG) Ebp); + } // endif + + if (Ebp < LastEbp) + { + fprintf(LogFile, "... lost stack chain - new EBP below previous\n"); + break; + } + } + else + fExceptionAddress = FALSE; + + Size = 4; + rc = DosQueryMem((PVOID) Ebp, &Size, &Attr); + if ((rc != NO_ERROR) || (Size < 4)) + { + fprintf(LogFile, "... lost stack chain - invalid EBP: %8.8lX\n", (ULONG)Ebp); + break; + } + } while (TRUE); + + fprintf(LogFile, "\n"); +} + +/* + *@@ doshQueryBootDrive: + * returns the letter of the boot drive as a + * single (capital) character, which is useful for + * constructing file names using sprintf and such. + * + *@@changed V0.9.16 (2002-01-13) [umoeller]: optimized + */ + +CHAR doshQueryBootDrive(VOID) +{ + // this can never change, so query this only once + // V0.9.16 (2002-01-13) [umoeller] + static CHAR cBootDrive = '\0'; + + if (!cBootDrive) + { + ULONG ulBootDrive; + DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, + &ulBootDrive, + sizeof(ulBootDrive)); + cBootDrive = (CHAR)ulBootDrive + 'A' - 1; + } + + return (cBootDrive); +} diff --git a/sal/osl/os2/diagnose.c b/sal/osl/os2/diagnose.c new file mode 100644 index 000000000000..b33c1491f77d --- /dev/null +++ b/sal/osl/os2/diagnose.c @@ -0,0 +1,181 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: diagnose.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "system.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#include <osl/diagnose.h> +#include <osl/thread.h> + +BYTE oslTraceEnv[] = "OSL_TRACE_TO_FILE"; + +typedef pfunc_osl_printDebugMessage oslDebugMessageFunc; +static oslDebugMessageFunc volatile g_pDebugMessageFunc = 0; + +typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc; +static oslDetailedDebugMessageFunc volatile g_pDetailedDebugMessageFunc = 0; + +/*----------------------------------------------------------------------------*/ + +void SAL_CALL osl_breakDebug() +{ + __asm__("int $3\n"); +} + +/************************************************************************/ +/* osl_trace */ +/************************************************************************/ +/* comment this define to stop output thread identifier*/ +#define OSL_TRACE_THREAD 1 +void SAL_CALL osl_trace ( + const sal_Char* lpszFormat, ...) +{ + va_list args; + +#if defined(OSL_PROFILING) + fprintf(stderr, "Time: %06lu : ", osl_getGlobalTimer() ); +#else +#if defined(OSL_TRACE_THREAD) + fprintf(stderr,"Thread: %6d :",osl_getThreadIdentifier(NULL)); +#else + fprintf(stderr, "Trace Message: "); +#endif +#endif + + va_start(args, lpszFormat); + vfprintf(stderr, lpszFormat, args); + va_end(args); + + fprintf(stderr,"\n"); + fflush(stderr); +} + +/*----------------------------------------------------------------------------*/ + +void SAL_CALL osl_trace__yd_os2(const sal_Char* lpszFormat, ...) +{ + + int nBuf; + sal_Char szBuffer[512]; + sal_Char szPID[ 12 ]; + va_list args; + FILE* pFile; + PID pid; + PSZ pszOslTraceFile; + + /* if environment variable not set, do nothing */ + if(DosScanEnv(oslTraceEnv, (PSZ*)&pszOslTraceFile)) + { + return; + } + + va_start(args, lpszFormat); + + nBuf = vsprintf(szBuffer, lpszFormat, args); + OSL_ASSERT(nBuf < sizeof(szBuffer)); + + va_end(args); + + /* get process ID */ + { + PTIB pptib = NULL; + PPIB pppib = NULL; + + DosGetInfoBlocks( &pptib, &pppib ); + pid = pppib->pib_ulpid; + } + + pFile = fopen( (const char*)pszOslTraceFile, "a+" ); + fputs(_itoa( pid, szPID, 10 ), pFile ); + fputs( ": ", pFile ); + fputs(szBuffer, pFile); + fclose( pFile ); + +} + +/*----------------------------------------------------------------------------*/ + +sal_Bool SAL_CALL osl_assertFailedLine( const sal_Char* pszFileName, sal_Int32 nLine, const sal_Char* pszMessage) +{ + sal_Char szMessage[512]; + + /* get app name or NULL if unknown (don't call assert) */ + sal_Char* lpszAppName = "OSL"; + + /* format message into buffer */ + sprintf(szMessage, "Assertion Failed: %s: File %s, Line %d:\n", + lpszAppName, pszFileName, nLine); + if(pszMessage != 0) + strcat( szMessage, pszMessage ); + + szMessage[sizeof(szMessage)-1] = '\0'; + + fputs(szMessage, stderr); + + return sal_True; /* abort */ +} + +/*----------------------------------------------------------------------------*/ + +sal_Int32 SAL_CALL osl_reportError(sal_uInt32 nType, const sal_Char* pszMessage) +{ + fputs(pszMessage, stderr); + + return 0; +} + +/*----------------------------------------------------------------------------*/ + + +/************************************************************************/ +/* osl_setDebugMessageFunc */ +/************************************************************************/ +oslDebugMessageFunc SAL_CALL osl_setDebugMessageFunc ( + oslDebugMessageFunc pNewFunc) +{ + oslDebugMessageFunc pOldFunc = g_pDebugMessageFunc; + g_pDebugMessageFunc = pNewFunc; + return pOldFunc; +} + +/************************************************************************/ +/* osl_setDetailedDebugMessageFunc */ +/************************************************************************/ +pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc ( + pfunc_osl_printDetailedDebugMessage pNewFunc) +{ + oslDetailedDebugMessageFunc pOldFunc = g_pDetailedDebugMessageFunc; + g_pDetailedDebugMessageFunc = pNewFunc; + return pOldFunc; +} diff --git a/sal/osl/os2/dllentry.c b/sal/osl/os2/dllentry.c new file mode 100644 index 000000000000..d0ea57e00127 --- /dev/null +++ b/sal/osl/os2/dllentry.c @@ -0,0 +1,78 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dllentry.c,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "system.h" +#include "sockimpl.h" +#include "secimpl.h" +//#include "daemimpl.h" + +#include <osl/diagnose.h> + +#ifndef GCC +sal_uInt32 _System _DLL_InitTerm( sal_uInt32 nModule, + sal_uInt32 nFlag ) +{ + switch( nFlag ) + { + case 0: + { + /* initialize C runtime library */ + _CRT_init(); + { + LONG fhToAdd = 0; + ULONG fhOld = 0; + ULONG ngLastError = DosSetRelMaxFH(&fhToAdd, &fhOld); + if (fhOld < 200) + ngLastError = DosSetMaxFH(200); + } + + /* turn off hardware-errors and exception popups */ + DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION); + + break; + } + + case 1: + { + /* unload libs (sockets) */ + ImplFreeTCPIP(); + + /* unload libs (security) */ + ImplFreeUPM(); + + break; + } + } + + return (sal_True); +} +#endif + + diff --git a/sal/osl/os2/except.c b/sal/osl/os2/except.c new file mode 100644 index 000000000000..0dd2a35d1fcd --- /dev/null +++ b/sal/osl/os2/except.c @@ -0,0 +1,1062 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile:$ + * $Revision:$ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + *@@sourcefile except.c: + * this file contains powerful exception handlers. + * except.h also defines easy-to-use macros for them. + * + * Usage: All OS/2 programs, PM or text mode. + * + * <B>Introduction</B> + * + * OS/2 exception handlers are a mess to program and, + * if installed wrongly, almost impossible to debug. + * The problem is that for any program that does a bit + * more than showing a message box, using exception + * handlers is a must to avoid system hangs. This + * especially applies to multi-thread programs using + * mutex semaphores (more on that below). The functions + * and macros in here are designed to make that more + * simple. + * + * The macros in except.h automatically insert code for + * properly registering and deregistering the handlers + * in except.c. You should ALWAYS use these macros + * instead of directly registering the handlers to avoid + * accidentally forgetting to deregister them. If you + * forget to deregister an exception handler, this can + * lead to really strange errors (crashes, hangs) which + * are nearly impossible to debug because the thread's + * stack probably got completely messed up. + * + * The general idea of these macros is to define + * TRY / CATCH blocks similar to C++. If an exception + * occurs in the TRY block, execution is transferred to + * the CATCH block. (This works in both C and C++, by the + * way.) + * + * The "OnKill" function that was added with V0.9.0 has + * been removed again with V0.9.7. + * + * The general usage is like this: + * + + int your_protected_func(int ...) + + { + + TRY_LOUD(excptid) // or: TRY_QUIET(excptid) + + { + + char *p = NULL; + + + + .... // the stuff in here is protected by + + // the excHandlerLoud or excHandlerQuiet + + // exception handler + + *p = "A"; + + } + + CATCH(excptid) + + { + + .... // exception occured: react here + + } END_CATCH(); // always needed! + + } // end of your_func + * + * TRY_LOUD is for installing excHandlerLoud. + * TRY_QUIET is for installing excHandlerQuiet. + * CATCH / END_CATCH are the same for the two. This + * is where the exception handler jumps to if an + * exception occurs. + * The CATCH block is _required_ even if you do nothing + * in there, because the CATCH() macro will deregister + * the handler. + * + * "excptid" can be any C identifier which is not used in + * your current variable scope, e.g. "excpt1". This + * is used for creating an EXCEPTSTRUCT variable of + * that name on the stack. The "excptid"'s in TRY_* and + * CATCH must match, since this is where the macros + * store the exception handler data. + * + * These macros may be nested if you use different + * "excptid"'s for sub-macros. + * + * Inside the TRY and CATCH blocks, you must not use + * "goto" (to a location outside the block) or "return", + * because this will not deregister the handler. + * + * Keep in mind that all the code in the TRY_* block is + * protected by the handler, including all functions that + * get called. So if you enclose your main() code in a + * TRY_* block, your entire application is protected. + * If any subfunction fails, execution is transferred to + * the closest CATCH() that was installed (as with C++ + * try and catch). + * + * <B>Asynchronous exceptions</B> + * + * The exception handlers in this file (which are installed + * with the TRY/CATCH mechanism) only intercept synchronous + * exceptions, most importantly, XCPT_ACCESS_VIOLATION (see + * excHandlerLoud for a list). They do not protect your code + * against asynchronous exceptions. + * + * OS/2 defines asynchronous exceptions to be those that + * can be delayed. With OS/2, there are only three of these: + * + * -- XCPT_PROCESS_TERMINATE + * -- XCPT_ASYNC_PROCESS_TERMINATE + * -- XCPT_SIGNAL (thread 1 only) + * + * To protect yourself against these also, put the section + * in question in a DosEnterMustComplete/DosExitMustComplete + * block as well. + * + * <B>Mutex semaphores</B> + * + * The problem with OS/2 mutex semaphores is that they are + * sometimes not automatically released when a thread terminates. + * If there are several mutexes involved and they are released + * in improper order, you can get zombie threads on exit. + * Even worse, if this happens to a PM thread, this will hang + * the system. + * + * As a result, you should protect any section of code which + * requests a semaphore with the exception handlers. + * + * So _whenever_ you request a mutex semaphore, enclose + * the block with TRY/CATCH in case the code crashes. + * Besides, enclose the TRY/CATCH block in a must-complete + * section, like this: + * + + HMTX hmtx = ... + + + + int your_func(int) + + { + + BOOL fSemOwned = FALSE; + + + + TRY_QUIET(excpt1) // or TRY_LOUD + + { + + if (fSemOwned = !DosRequestMutexSem(hmtx, ...)) + + { ... // work on your protected data + + } + + // mutex gets released below + + } + + CATCH(excpt1) { } END_CATCH(); // always needed! + + + + if (fSemOwned) + + // this gets executed always, even if an exception occured + + DosReleaseMutexSem(hmtx); + + } // end of your_func + * + * This way your mutex semaphore gets released in every + * possible condition. + * + * <B>Customizing</B> + * + * As opposed to versions before 0.9.0, this code is now + * completely independent of XWorkplace. This file now + * contains "pure" exception handlers only. + * + * However, you can customize these exception handlers by + * calling excRegisterHooks. This is what XWorkplace does now. + * This should be done upon initialization of your application. + * If excRegisterHooks is not called, the following safe + * defaults are used: + * + * -- the trap log file is TRAP.LOG in the root + * directory of your boot drive. + * + * For details on the provided exception handlers, refer + * to excHandlerLoud and excHandlerQuiet. + * + * More useful debug information can be found in the "OS/2 Debugging + * Handbook", which is now available in INF format on the IBM + * DevCon site ("http://service2.boulder.ibm.com/devcon/"). + * This book shows worked examples of how to unwind a stack dump. + * + * This file incorporates code from the following: + * -- Monte Copeland, IBM Boca Ration, Florida, USA (1993) + * -- Roman Stangl, from the Program Commander/2 sources + * (1997-98) + * -- Marc Fiammante, John Currier, Kim Rasmussen, + * Anthony Cruise (EXCEPT3.ZIP package for a generic + * exception handling DLL, available at Hobbes). + * + * If not explicitly stated otherwise, the code has been written + * by me, Ulrich M�ller. + * + * Note: Version numbering in this file relates to XWorkplace version + * numbering. + * + *@@header "helpers\except.h" + */ + +/* + * This file Copyright (C) 1992-99 Ulrich M�ller, + * Monte Copeland, + * Roman Stangl, + * Kim Rasmussen, + * Marc Fiammante, + * John Currier, + * Anthony Cruise. + * This file is part of the "XWorkplace helpers" source package. + * + * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. + * + */ + +#define OS2EMX_PLAIN_CHAR + // this is needed for "os2emx.h"; if this is defined, + // emx will define PSZ as _signed_ char, otherwise + // as unsigned char + +#define INCL_DOSMODULEMGR +#define INCL_DOSEXCEPTIONS +#define INCL_DOSPROCESS +#define INCL_DOSMISC +#define INCL_DOSERRORS +#include <os2.h> + +// C library headers +#include <stdio.h> // needed for except.h +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <setjmp.h> // needed for except.h +#include <assert.h> // needed for except.h + +#define DONT_REPLACE_MALLOC +#include "helpers\setup.h" // code generation and debugging options + +// headers in /helpers +#include "helpers\dosh.h" // Control Program helper routines +#include "helpers\except.h" // exception handling +#include "helpers\debug.h" // symbol/debug code analysis + +#pragma hdrstop + +/* ****************************************************************** + * + * Global variables + * + ********************************************************************/ + +// hooks to be registered using excRegisterHooks +PFNEXCOPENFILE G_pfnExcOpenFile = 0; +PFNEXCHOOK G_pfnExcHook = 0; +PFNEXCHOOKERROR G_pfnExcHookError = 0; +// beep flag for excHandlerLoud +BOOL G_fBeepOnException = TRUE; + +ULONG G_ulExplainExceptionRunning = 0; + // global flag which is != 0 if some exception handler + // is inside excExplainException, so that XShutdown can + // wait until the trap log is done; + // this is exported thru except.h + // V0.9.13 (2001-06-19) [umoeller] + +/* + *@@category: Helpers\Control program helpers\Exceptions/debugging + * See except.c. + */ + +/* ****************************************************************** + * + * Exception helper routines + * + ********************************************************************/ + +/* + *@@ excDescribePage: + * + */ + +VOID excDescribePage(FILE *file, ULONG ulCheck) +{ + APIRET arc; + ULONG ulCountPages = 1; + ULONG ulFlagsPage = 0; + arc = DosQueryMem((PVOID)ulCheck, &ulCountPages, &ulFlagsPage); + + if (arc == NO_ERROR) + { + fprintf(file, "valid, flags: "); + if (ulFlagsPage & PAG_READ) + fprintf(file, "read "); + if (ulFlagsPage & PAG_WRITE) + fprintf(file, "write "); + if (ulFlagsPage & PAG_EXECUTE) + fprintf(file, "execute "); + if (ulFlagsPage & PAG_GUARD) + fprintf(file, "guard "); + if (ulFlagsPage & PAG_COMMIT) + fprintf(file, "committed "); + if (ulFlagsPage & PAG_SHARED) + fprintf(file, "shared "); + if (ulFlagsPage & PAG_FREE) + fprintf(file, "free "); + if (ulFlagsPage & PAG_BASE) + fprintf(file, "base "); + } + else if (arc == ERROR_INVALID_ADDRESS) + fprintf(file, "invalid"); +} + +/* + *@@ excPrintStackFrame: + * wrapper for dbgPrintStackFrame to format + * output stuff right. + * + *@@added V0.9.2 (2000-03-10) [umoeller] + *@@changed V0.9.12 (2001-05-12) [umoeller]: added seg:ofs to output always + */ + +VOID excPrintStackFrame(FILE *file, // in: output log file + PSZ pszDescription, // in: description for stack frame (should be eight chars) + ULONG ulAddress) // in: address to debug +{ + APIRET arc = NO_ERROR; + HMODULE hmod1 = NULLHANDLE; + CHAR szMod1[2*CCHMAXPATH] = "unknown"; + ULONG ulObject = 0, + ulOffset = 0; + fprintf(file, + " %-8s: %08lX ", + pszDescription, + ulAddress); + arc = DosQueryModFromEIP(&hmod1, + &ulObject, + sizeof(szMod1), szMod1, + &ulOffset, + ulAddress); + + if (arc != NO_ERROR) + { + // error: + fprintf(file, + " %-8s Error: DosQueryModFromEIP returned %lu\n", + szMod1, + arc); + } + else + { + CHAR szFullName[2*CCHMAXPATH]; + + fprintf(file, + " %-8s %02lX:%08lX\n ", + szMod1, + ulObject + 1, // V0.9.12 (2001-05-12) [umoeller] + ulOffset); // V0.9.12 (2001-05-12) [umoeller] + + DosQueryModuleName(hmod1, sizeof(szFullName), szFullName); + dbgPrintStackFrame(file, + szFullName, + ulObject, + ulOffset); + + fprintf(file, "\n"); + + // make a 'tick' sound to let the user know we're still alive + DosBeep(2000, 10); + } +} + +/* + *@@ excDumpStackFrames: + * called from excExplainException to dump the + * thread's stack frames. This calls excPrintStackFrame + * for each stack frame found. + * + *@@added V0.9.4 (2000-06-15) [umoeller] + */ + +VOID excDumpStackFrames(FILE *file, // in: logfile from fopen() + PTIB ptib, + PCONTEXTRECORD pContextRec) // in: excpt info +{ + PULONG pulStackWord = 0; + + fprintf(file, "\n\nStack frames:\n Address Module seg:ofs\n"); + + // first the trapping address itself + excPrintStackFrame(file, + "CS:EIP ", + pContextRec->ctx_RegEip); + + + pulStackWord = (PULONG)pContextRec->ctx_RegEbp; + /* if (pContextRec->ctx_RegEbp < pContextRec->ctx_RegEsp) + pulStackWord = (PULONG)(pContextRec->ctx_RegEbp & 0xFFFFFFF0); + else + pulStackWord = (PULONG)(pContextRec->ctx_RegEsp & 0xFFFFFFF0); */ + + while ( (pulStackWord != 0) + && (pulStackWord < (PULONG)ptib->tib_pstacklimit) + ) + { + CHAR szAddress[20]; + + if (((ULONG)pulStackWord & 0x00000FFF) == 0x00000000) + { + // we're on a page boundary: check access + ULONG ulCountPages = 0x1000; + ULONG ulFlagsPage = 0; + APIRET arc = DosQueryMem((void *)pulStackWord, + &ulCountPages, + &ulFlagsPage); + if ( (arc != NO_ERROR) + || ( (arc == NO_ERROR) + && ( !( ((ulFlagsPage & (PAG_COMMIT|PAG_READ)) + == (PAG_COMMIT|PAG_READ) + ) + ) + ) + ) + ) + { + fprintf(file, "\n %08lX: ", (ULONG)pulStackWord); + fprintf(file, "Page inaccessible"); + pulStackWord += 0x1000; + continue; // for + } + } + + sprintf(szAddress, "%08lX", + (ULONG)pulStackWord); + excPrintStackFrame(file, + szAddress, + *(pulStackWord+1)); + pulStackWord = (PULONG)*(pulStackWord); + + if (pulStackWord == 0) + fprintf(file, "\n pulStackWord == 0"); + else if (pulStackWord >= (PULONG)ptib->tib_pstacklimit) + fprintf(file, "\n pulStackWord >= (PULONG)ptib->tib_pstacklimit"); + } // end while +} + +/* + *@@ excExplainException: + * used by the exception handlers below to write + * LOTS of information about the exception into a logfile. + * + * This calls excPrintStackFrame for each stack frame. + * + *@@changed V0.9.0 [umoeller]: added support for application hook + *@@changed V0.9.0 (99-11-02) [umoeller]: added TID to dump + *@@changed V0.9.2 (2000-03-10) [umoeller]: now using excPrintStackFrame + *@@changed V0.9.3 (2000-05-03) [umoeller]: fixed crashes + *@@changed V0.9.6 (2000-11-06) [umoeller]: added more register dumps + *@@changed V0.9.13 (2001-06-19) [umoeller]: added global flag for whether this is running + *@@changed V0.9.16 (2001-11-02) [pr]: make object display signed + *@@changed V0.9.19 (2002-03-28) [umoeller]: added thread ordinal + */ + +VOID excExplainException(FILE *file, // in: logfile from fopen() + PSZ pszHandlerName, // in: descriptive string + PEXCEPTIONREPORTRECORD pReportRec, // in: excpt info + PCONTEXTRECORD pContextRec) // in: excpt info +{ + ULONG aulBuf[3]; + const char *pcszVersion = "unknown"; + + PTIB ptib = NULL; + PPIB ppib = NULL; + HMODULE hMod1, hMod2; + CHAR szMod1[CCHMAXPATH] = "unknown", + szMod2[CCHMAXPATH] = "unknown"; + ULONG ulObjNum, + ulOffset; + ULONG ul; + + ULONG ulOldPriority = 0x0100; // regular, delta 0 + + // raise global flag for whether this func is running + // V0.9.13 (2001-06-19) [umoeller] + G_ulExplainExceptionRunning++; + + // raise this thread's priority, because this + // might take some time + if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR) + if (ptib) + if (ptib->tib_ptib2) + { + ulOldPriority = ptib->tib_ptib2->tib2_ulpri; + DosSetPriority(PRTYS_THREAD, + PRTYC_REGULAR, + PRTYD_MAXIMUM, + 0); // current thread + } + + // make some noise +#ifndef __NOEXCEPTIONBEEPS__ // V0.9.19 (2002-04-17) [umoeller] + if (G_fBeepOnException) + { + DosBeep( 250, 30); + DosBeep( 500, 30); + DosBeep(1000, 30); + DosBeep(2000, 30); + DosBeep(4000, 30); + DosBeep(2000, 30); + DosBeep(1000, 30); + DosBeep( 500, 30); + DosBeep( 250, 30); + } +#endif + + // generic exception info + DosQuerySysInfo(QSV_VERSION_MAJOR, // 11 + QSV_VERSION_MINOR, // 12 + &aulBuf, sizeof(aulBuf)); + // Warp 3 is reported as 20.30 + // Warp 4 is reported as 20.40 + // Aurora is reported as 20.45 + + if (aulBuf[0] == 20) + { + switch (aulBuf[1]) + { + case 30: pcszVersion = "Warp 3"; break; + case 40: pcszVersion = "Warp 4"; break; + case 45: pcszVersion = "WSeB kernel"; break; + } + } + fprintf(file, + "Running OS/2 version: %u.%u (%s)\n", + aulBuf[0], // major + aulBuf[1], + pcszVersion); + + + // generic exception info + fprintf(file, + "\n%s:\n Exception type: %08lX\n Address: %08lX\n Params: ", + pszHandlerName, + pReportRec->ExceptionNum, + (ULONG)pReportRec->ExceptionAddress); + for (ul = 0; ul < pReportRec->cParameters; ul++) + { + fprintf(file, "%08lX ", + pReportRec->ExceptionInfo[ul]); + } + + // now explain the exception in a bit more detail; + // depending on the exception, pReportRec->ExceptionInfo + // contains some useful data + switch (pReportRec->ExceptionNum) + { + case XCPT_ACCESS_VIOLATION: + fprintf(file, "\nXCPT_ACCESS_VIOLATION: "); + if (pReportRec->ExceptionInfo[0] & XCPT_READ_ACCESS) + fprintf(file, "Invalid read access from 0x%04lX:%08lX.\n", + pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]); + else if (pReportRec->ExceptionInfo[0] & XCPT_WRITE_ACCESS) + fprintf(file, "Invalid write access to 0x%04lX:%08lX.\n", + pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]); + else if (pReportRec->ExceptionInfo[0] & XCPT_SPACE_ACCESS) + fprintf(file, "Invalid space access at 0x%04lX.\n", + pReportRec->ExceptionInfo[1]); + else if (pReportRec->ExceptionInfo[0] & XCPT_LIMIT_ACCESS) + fprintf(file, "Invalid limit access occurred.\n"); + else if (pReportRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS) + fprintf(file, "unknown at 0x%04lX:%08lX\n", + pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]); + fprintf(file, + "Explanation: An attempt was made to access a memory object which does\n" + " not belong to the current process. Most probable causes\n" + " for this are that an invalid pointer was used, there was\n" + " confusion with administering memory or error conditions \n" + " were not properly checked for.\n"); + break; + + case XCPT_INTEGER_DIVIDE_BY_ZERO: + fprintf(file, "\nXCPT_INTEGER_DIVIDE_BY_ZERO.\n"); + fprintf(file, + "Explanation: An attempt was made to divide an integer value by zero,\n" + " which is not defined.\n"); + break; + + case XCPT_ILLEGAL_INSTRUCTION: + fprintf(file, "\nXCPT_ILLEGAL_INSTRUCTION.\n"); + fprintf(file, + "Explanation: An attempt was made to execute an instruction that\n" + " is not defined on this machine's architecture.\n"); + break; + + case XCPT_PRIVILEGED_INSTRUCTION: + fprintf(file, "\nXCPT_PRIVILEGED_INSTRUCTION.\n"); + fprintf(file, + "Explanation: An attempt was made to execute an instruction that\n" + " is not permitted in the current machine mode or that\n" + " the program had no permission to execute.\n"); + break; + + case XCPT_INTEGER_OVERFLOW: + fprintf(file, "\nXCPT_INTEGER_OVERFLOW.\n"); + fprintf(file, + "Explanation: An integer operation generated a carry-out of the most\n" + " significant bit. This is a sign of an attempt to store\n" + " a value which does not fit into an integer variable.\n"); + break; + + default: + fprintf(file, "\nUnknown OS/2 exception number %d.\n", pReportRec->ExceptionNum); + fprintf(file, "Look this up in the OS/2 header files.\n"); + break; + } + + // V0.9.16 (2001-11-02) [pr]: We already got this info. above - this overwrites the + // original values before the priority change, which is rather confusing. + // if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR) + { + /* + * process info: + * + */ + + if ((ptib) && (ppib)) // (99-11-01) [umoeller] + { + if (pContextRec->ContextFlags & CONTEXT_CONTROL) + { + // get the main module + hMod1 = ppib->pib_hmte; + DosQueryModuleName(hMod1, + sizeof(szMod1), + szMod1); + + // get the trapping module + DosQueryModFromEIP(&hMod2, + &ulObjNum, + sizeof(szMod2), + szMod2, + &ulOffset, + pContextRec->ctx_RegEip); + DosQueryModuleName(hMod2, + sizeof(szMod2), + szMod2); + } + + fprintf(file, + "\nProcess information:" + "\n Process ID: 0x%lX" + "\n Process module: 0x%lX (%s)" + "\n Trapping module: 0x%lX (%s)" + "\n Object: %ld\n", // V0.9.16 (2001-11-02) [pr]: make this display signed + ppib->pib_ulpid, + hMod1, szMod1, + hMod2, szMod2, + ulObjNum); + + fprintf(file, + "\nTrapping thread information:" + "\n Thread ID: 0x%lX (%lu)" + "\n Thread slot ID: 0x%lX (%lu)" // added V0.9.19 (2002-03-28) [umoeller] + "\n Priority: 0x%lX\n", + ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ultid, + ptib->tib_ordinal, ptib->tib_ordinal, + ulOldPriority); + } + else + fprintf(file, "\nProcess information was not available."); + + /* + * now call the hook, if one has been defined, + * so that the application can write additional + * information to the traplog (V0.9.0) + */ + + if (G_pfnExcHook) + G_pfnExcHook(file, ptib, ulOldPriority); // V0.9.16 (2001-12-02) [pr] + + // *** registers + + fprintf(file, "\nRegisters:"); + if (pContextRec->ContextFlags & CONTEXT_INTEGER) + { + // DS the following 4 added V0.9.6 (2000-11-06) [umoeller] + fprintf(file, "\n DS = %08lX ", pContextRec->ctx_SegDs); + excDescribePage(file, pContextRec->ctx_SegDs); + // ES + fprintf(file, "\n ES = %08lX ", pContextRec->ctx_SegEs); + excDescribePage(file, pContextRec->ctx_SegEs); + // FS + fprintf(file, "\n FS = %08lX ", pContextRec->ctx_SegFs); + excDescribePage(file, pContextRec->ctx_SegFs); + // GS + fprintf(file, "\n GS = %08lX ", pContextRec->ctx_SegGs); + excDescribePage(file, pContextRec->ctx_SegGs); + + // EAX + fprintf(file, "\n EAX = %08lX ", pContextRec->ctx_RegEax); + excDescribePage(file, pContextRec->ctx_RegEax); + // EBX + fprintf(file, "\n EBX = %08lX ", pContextRec->ctx_RegEbx); + excDescribePage(file, pContextRec->ctx_RegEbx); + // ECX + fprintf(file, "\n ECX = %08lX ", pContextRec->ctx_RegEcx); + excDescribePage(file, pContextRec->ctx_RegEcx); + // EDX + fprintf(file, "\n EDX = %08lX ", pContextRec->ctx_RegEdx); + excDescribePage(file, pContextRec->ctx_RegEdx); + // ESI + fprintf(file, "\n ESI = %08lX ", pContextRec->ctx_RegEsi); + excDescribePage(file, pContextRec->ctx_RegEsi); + // EDI + fprintf(file, "\n EDI = %08lX ", pContextRec->ctx_RegEdi); + excDescribePage(file, pContextRec->ctx_RegEdi); + fprintf(file, "\n"); + } + else + fprintf(file, " not available\n"); + + if (pContextRec->ContextFlags & CONTEXT_CONTROL) + { + + // *** instruction + + fprintf(file, "Instruction pointer (where exception occured):\n CS:EIP = %04lX:%08lX ", + pContextRec->ctx_SegCs, + pContextRec->ctx_RegEip); + excDescribePage(file, pContextRec->ctx_RegEip); + + // *** CPU flags + + fprintf(file, "\n EFLAGS = %08lX", pContextRec->ctx_EFlags); + + /* + * stack: + * + */ + + fprintf(file, "\nStack:\n Base: %08lX\n Limit: %08lX", + (ULONG)(ptib ? ptib->tib_pstack : 0), + (ULONG)(ptib ? ptib->tib_pstacklimit : 0)); + fprintf(file, "\n SS:ESP = %04lX:%08lX ", + pContextRec->ctx_SegSs, + pContextRec->ctx_RegEsp); + excDescribePage(file, pContextRec->ctx_RegEsp); + + fprintf(file, "\n EBP = %08lX ", pContextRec->ctx_RegEbp); + excDescribePage(file, pContextRec->ctx_RegEbp); + + /* + * stack dump: + */ + + if (ptib != 0) + { + excDumpStackFrames(file, ptib, pContextRec); + } + } + } + fprintf(file, "\n"); + + // reset old priority + DosSetPriority(PRTYS_THREAD, + (ulOldPriority & 0x0F00) >> 8, + (UCHAR)ulOldPriority, + 0); // current thread + + // lower global flag again V0.9.13 (2001-06-19) [umoeller] + G_ulExplainExceptionRunning--; +} + +/* ****************************************************************** + * + * Exported routines + * + ********************************************************************/ + +/* + *@@ excRegisterHooks: + * this registers hooks which get called for + * exception handlers. You can set any of the + * hooks to NULL for safe defaults (see top of + * except.c for details). You can set none, + * one, or both of the hooks, and you can call + * this function several times. + * + * Both hooks get called whenever an exception + * occurs, so there better be no bugs in these + * routines. ;-) They only get called from + * within excHandlerLoud (because excHandlerQuiet + * writes no trap logs). + * + * The hooks are as follows: + * + * -- pfnExcOpenFileNew gets called to open + * the trap log file. This must return a FILE* + * pointer from fopen(). If this is not defined, + * ?:\TRAP.LOG is used. Use this to specify a + * different file and have some notes written + * into it before the actual exception info. + * + * -- pfnExcHookNew gets called while the trap log + * is being written. At this point, + * the following info has been written into + * the trap log already: + * -- exception type/address block + * -- exception explanation + * -- process information + * + * _After_ the hook, the exception handler + * continues with the "Registers" information + * and stack dump/analysis. + * + * Use this hook to write additional application + * info into the trap log, such as the state + * of your own threads and mutexes. + * + * -- pfnExcHookError gets called when the TRY_* macros + * fail to install an exception handler (when + * DosSetExceptionHandler fails). I've never seen + * this happen. + * + *@@added V0.9.0 [umoeller] + *@@changed V0.9.2 (2000-03-10) [umoeller]: pfnExcHookError added + */ + +VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew, + PFNEXCHOOK pfnExcHookNew, + PFNEXCHOOKERROR pfnExcHookError, + BOOL fBeepOnExceptionNew) +{ + // adjust the global variables + G_pfnExcOpenFile = pfnExcOpenFileNew; + G_pfnExcHook = pfnExcHookNew; + G_pfnExcHookError = pfnExcHookError; + G_fBeepOnException = fBeepOnExceptionNew; +} + +/* + *@@ excHandlerLoud: + * this is the "sophisticated" exception handler; + * which gives forth a loud sequence of beeps thru the + * speaker, writes a trap log and then returns back + * to the thread to continue execution, i.e. the + * default OS/2 exception handler will never get + * called. + * + * This requires a setjmp() call on + * EXCEPTIONREGISTRATIONRECORD2.jmpThread before + * being installed. The TRY_LOUD macro will take + * care of this for you (see except.c). + * + * This intercepts the following exceptions (see + * the OS/2 Control Program Reference for details): + * + * -- XCPT_ACCESS_VIOLATION (traps 0x0d, 0x0e) + * -- XCPT_INTEGER_DIVIDE_BY_ZERO (trap 0) + * -- XCPT_ILLEGAL_INSTRUCTION (trap 6) + * -- XCPT_PRIVILEGED_INSTRUCTION + * -- XCPT_INTEGER_OVERFLOW (trap 4) + * + * For these exceptions, we call the functions in debug.c + * to try to find debug code or SYM file information about + * what source code corresponds to the error. + * + * See excRegisterHooks for the default setup of this. + * + * Note that to get meaningful debugging information + * in this handler's traplog, you need the following: + * + * a) have a MAP file created at link time (/MAP) + * + * b) convert the MAP to a SYM file using MAPSYM + * + * c) put the SYM file in the same directory of + * the module (EXE or DLL). This must have the + * same filestem as the module. + * + * All other exceptions are passed to the next handler + * in the exception handler chain. This might be the + * C/C++ compiler handler or the default OS/2 handler, + * which will probably terminate the process. + * + *@@changed V0.9.0 [umoeller]: added support for thread termination + *@@changed V0.9.2 (2000-03-10) [umoeller]: switched date format to ISO + *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that + */ + +ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec, + PEXCEPTIONREGISTRATIONRECORD2 pRegRec2, + PCONTEXTRECORD pContextRec, + PVOID pv) +{ + /* From the VAC++3 docs: + * "The first thing an exception handler should do is check the + * exception flags. If EH_EXIT_UNWIND is set, meaning + * the thread is ending, the handler tells the operating system + * to pass the exception to the next exception handler. It does the + * same if the EH_UNWINDING flag is set, the flag that indicates + * this exception handler is being removed. + * The EH_NESTED_CALL flag indicates whether the exception + * occurred within an exception handler. If the handler does + * not check this flag, recursive exceptions could occur until + * there is no stack remaining." + * So for all these conditions, we exit immediately. + */ + + if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND) + return (XCPT_CONTINUE_SEARCH); + if (pReportRec->fHandlerFlags & EH_UNWINDING) + return (XCPT_CONTINUE_SEARCH); + if (pReportRec->fHandlerFlags & EH_NESTED_CALL) + return (XCPT_CONTINUE_SEARCH); + + switch (pReportRec->ExceptionNum) + { + case XCPT_ACCESS_VIOLATION: + case XCPT_INTEGER_DIVIDE_BY_ZERO: + case XCPT_ILLEGAL_INSTRUCTION: + case XCPT_PRIVILEGED_INSTRUCTION: + case XCPT_INVALID_LOCK_SEQUENCE: + case XCPT_INTEGER_OVERFLOW: + { + // "real" exceptions: + FILE *file; + + // open traplog file; + if (G_pfnExcOpenFile) + // hook defined for this: call it + file = (*G_pfnExcOpenFile)(); + else + { + CHAR szFileName[100]; + // no hook defined: open some + // default traplog file in root directory of + // boot drive + sprintf(szFileName, "%c:\\trap.log", doshQueryBootDrive()); + file = fopen(szFileName, "a"); + + if (file) + { + DATETIME DT; + DosGetDateTime(&DT); + fprintf(file, + "\nTrap message -- Date: %04d-%02d-%02d, Time: %02d:%02d:%02d\n", + DT.year, DT.month, DT.day, + DT.hours, DT.minutes, DT.seconds); + fprintf(file, "------------------------------------------------\n"); + + } + } + + // write error log + excExplainException(file, + "excHandlerLoud", + pReportRec, + pContextRec); + fclose(file); + + // copy report rec to user buffer + // V0.9.19 (2002-05-07) [umoeller] + memcpy(&pRegRec2->err, + pReportRec, + sizeof(EXCEPTIONREPORTRECORD)); + + // jump back to failing routine + longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum); + break; } + } + + // not handled + return (XCPT_CONTINUE_SEARCH); +} + +/* + *@@ excHandlerQuiet: + * "quiet" xcpt handler, which simply suppresses exceptions; + * this is useful for certain error-prone functions, where + * exceptions are likely to appear, for example used by + * wpshCheckObject to implement a fail-safe SOM object check. + * + * This does _not_ write an error log and makes _no_ sound. + * This simply jumps back to the trapping thread or + * calls EXCEPTIONREGISTRATIONRECORD2.pfnOnKill. + * + * Other than that, this behaves like excHandlerLoud. + * + * This is best registered thru the TRY_QUIET macro + * (new with V0.84, described in except.c), which + * does the necessary setup. + * + *@@changed V0.9.0 [umoeller]: added support for thread termination + *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that + */ + +ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec, + PEXCEPTIONREGISTRATIONRECORD2 pRegRec2, + PCONTEXTRECORD pContextRec, + PVOID pv) +{ + if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND) + return (XCPT_CONTINUE_SEARCH); + if (pReportRec->fHandlerFlags & EH_UNWINDING) + return (XCPT_CONTINUE_SEARCH); + if (pReportRec->fHandlerFlags & EH_NESTED_CALL) + return (XCPT_CONTINUE_SEARCH); + + switch (pReportRec->ExceptionNum) + { + case XCPT_ACCESS_VIOLATION: + case XCPT_INTEGER_DIVIDE_BY_ZERO: + case XCPT_ILLEGAL_INSTRUCTION: + case XCPT_PRIVILEGED_INSTRUCTION: + case XCPT_INVALID_LOCK_SEQUENCE: + case XCPT_INTEGER_OVERFLOW: + // write excpt explanation only if the + // resp. debugging #define is set (setup.h) + #ifdef DEBUG_WRITEQUIETEXCPT + { + FILE *file = excOpenTraplogFile(); + excExplainException(file, + "excHandlerQuiet", + pReportRec, + pContextRec); + fclose(file); + } + #endif + + // copy report rec to user buffer + // V0.9.19 (2002-05-07) [umoeller] + memcpy(&pRegRec2->err, + pReportRec, + sizeof(EXCEPTIONREPORTRECORD)); + + // jump back to failing routine + longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum); + break; + + default: + break; + } + + return (XCPT_CONTINUE_SEARCH); +} + + diff --git a/sal/osl/os2/file.cxx b/sal/osl/os2/file.cxx new file mode 100644 index 000000000000..e89ce6450bee --- /dev/null +++ b/sal/osl/os2/file.cxx @@ -0,0 +1,3132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +/************************************************************************ + * ToDo + * + * Fix osl_getCanonicalName + * + * - Fix: check for corresponding struct sizes in exported functions + * - check size/use of oslDirectory + * - check size/use of oslDirectoryItem + * - check size/use of oslFileStatus + * - check size/use of oslVolumeDeviceHandle + * - check size/use of oslVolumeInfo + * - check size/use of oslFileHandle + ***********************************************************************/ + +#define INCL_DOSDEVIOCTL // OS2 device definitions + +#include "system.h" +#include <rtl/alloc.h> + +#include "osl/file.hxx" + + +#include <sal/types.h> +#include <osl/thread.h> +#include <osl/diagnose.h> +#include "file_error_transl.h" +#include <osl/time.h> + +#ifndef _FILE_URL_H_ +#include "file_url.h" +#endif + +#include "file_path_helper.hxx" +#include "uunxapi.hxx" + +#ifndef _STRING_H_ +#include <string.h> +#endif + +#ifndef _CTYPE_H_ +#include <ctype.h> +#endif + +#ifndef _WCHAR_H_ +#include <wchar.h> +#endif + +#if OSL_DEBUG_LEVEL > 1 + extern void debug_ustring(rtl_uString*); +#endif + + +#ifdef DEBUG_OSL_FILE +# define PERROR( a, b ) perror( a ); fprintf( stderr, b ) +#else +# define PERROR( a, b ) +#endif + +extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ); + + struct errentry errtable[] = { + { NO_ERROR, osl_File_E_None }, /* 0 */ + { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */ + { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */ + { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */ + { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */ + { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */ + { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */ + { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */ + { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */ + { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */ + { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */ + { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */ + { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */ + { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */ + { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */ + { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */ + { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */ + { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */ + { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */ + { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */ + { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */ + { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */ + { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */ + { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */ + { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */ + { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */ + { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */ + { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */ + { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */ + { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */ + { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */ + { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */ + { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */ + { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */ + { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */ + { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */ + { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */ + { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */ + { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */ + { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */ + { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */ + { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */ + { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */ + { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */ + { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */ + { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */ + { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */ + //{ ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM } /* 1816 */ + }; + + #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) + + //##################################################### + oslFileError MapError(APIRET dwError) + { + for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i ) + { + if (dwError == errtable[i].oscode) + return static_cast<oslFileError>(errtable[i].errnocode); + } + return osl_File_E_INVAL; + } + +/****************************************************************************** + * + * static members + * + *****************************************************************************/ + +static const char * pFileLockEnvVar = (char *) -1; + + +/****************************************************************************** + * + * C-String Function Declarations + * + *****************************************************************************/ + +static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask); +static oslFileError osl_psz_removeFile(const sal_Char* pszPath); +static oslFileError osl_psz_createDirectory(const sal_Char* pszPath); +static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath); +static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath); +static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); +static oslFileError osl_psz_setFileTime(const sal_Char* strFilePath, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime); + + +/****************************************************************************** + * + * Static Module Utility Function Declarations + * + *****************************************************************************/ + +static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists); +static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID); +static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName); +static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode); +static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); +rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr); + +/****************************************************************************** + * + * Non-Static Utility Function Declarations + * + *****************************************************************************/ + +extern "C" int UnicodeToText( char *, size_t, const sal_Unicode *, sal_Int32 ); +extern "C" int TextToUnicode( + const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size); + +/****************************************************************************** + * + * 'removeable device' aka floppy functions + * + *****************************************************************************/ + +static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath); +static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy); +static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy); + +#ifdef DEBUG_OSL_FILE +static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy); +#endif + +/********************************************** + * _osl_openLocalRoot + * enumerate available drives + *********************************************/ +static oslFileError _osl_openLocalRoot( rtl_uString *strDirectoryPath, oslDirectory *pDirectory) +{ + rtl_uString *ustrSystemPath = NULL; + oslFileError error; + + if ( !pDirectory ) + return osl_File_E_INVAL; + + *pDirectory = NULL; + + error = osl_getSystemPathFromFileURL_Ex( strDirectoryPath, &ustrSystemPath, sal_False ); + + if ( osl_File_E_None == error ) + { + /* create and initialize impl structure */ + DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); + if( pDirImpl ) + { + ULONG ulDriveNum; + APIRET rc; + pDirImpl->uType = DIRECTORYTYPE_LOCALROOT; + pDirImpl->ustrPath = ustrSystemPath; + rc = DosQueryCurrentDisk (&ulDriveNum, &pDirImpl->ulDriveMap); + pDirImpl->pDirStruct = 0; + pDirImpl->ulNextDrive = 1; + pDirImpl->ulNextDriveMask = 1; + + // determine number of floppy-drives + BYTE nFloppies; + rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); + if (nFloppies == 0) { + // if no floppies, start with 3rd drive (C:) + pDirImpl->ulNextDrive = 3; + pDirImpl->ulNextDriveMask <<= 2; + } else if (nFloppies == 1) { + // mask drive B (second bit) in this case + pDirImpl->ulDriveMap &= ~0x02; + } + *pDirectory = (oslDirectory) pDirImpl; + return osl_File_E_None; + } + else + { + errno = osl_File_E_NOMEM; + } + + } + + rtl_uString_release( ustrSystemPath ); + return error; +} + +/********************************************** + * _osl_getNextDrive + *********************************************/ +static oslFileError SAL_CALL _osl_getNextDrive( + oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint ) +{ + DirectoryImpl *pDirImpl = (DirectoryImpl *)Directory; + DirectoryItem_Impl *pItemImpl = NULL; + rtl_uString * ustrDrive = NULL; + BOOL fSuccess; + char buffer[3]; + + uHint = uHint; /* avoid warnings */ + + if ( !pItem ) + return osl_File_E_INVAL; + + *pItem = NULL; + + if ( !pDirImpl ) + return osl_File_E_INVAL; + + while( pDirImpl->ulNextDrive <= 26) + { + // exit if bit==1 -> drive found + if (pDirImpl->ulDriveMap & pDirImpl->ulNextDriveMask) { + + /* convert file name to unicode */ + buffer[0] = '@' + pDirImpl->ulNextDrive; + buffer[1] = ':'; + buffer[2] = 0; + + pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); + if ( !pItemImpl ) + return osl_File_E_NOMEM; + + memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); + pItemImpl->uType = DIRECTORYITEM_DRIVE; + pItemImpl->nRefCount = 1; + + rtl_string2UString( &pItemImpl->ustrDrive, buffer, 3, + osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(pItemImpl->ustrDrive != 0); + + /* use drive as directory item */ + *pItem = (oslDirectoryItem) pItemImpl; + } + // scan next bit position + pDirImpl->ulNextDrive++; + pDirImpl->ulNextDriveMask <<= 1; + + if (*pItem) // item assigned, return now. + return osl_File_E_None; + } + + // no more items + return osl_File_E_NOENT; +} + +/********************************************** + * _osl_readdir_impl_ + * + * readdir wrapper, filters out "." and ".." + * on request + *********************************************/ + +static struct dirent* _osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir) +{ + struct dirent* pdirent; + + while ((pdirent = readdir(pdir)) != NULL) + { + if (bFilterLocalAndParentDir && + ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, "..")))) + continue; + else + break; + } + + return pdirent; +} + +/******************************************************************* + * osl_openDirectory + ******************************************************************/ + +oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory) +{ + rtl_uString* ustrSystemPath = NULL; + oslFileError eRet; + + char path[PATH_MAX]; + + OSL_ASSERT(ustrDirectoryURL && (ustrDirectoryURL->length > 0)); + OSL_ASSERT(pDirectory); + + if (0 == ustrDirectoryURL->length ) + return osl_File_E_INVAL; + + if ( 0 == rtl_ustr_compareIgnoreAsciiCase( ustrDirectoryURL->buffer, (const sal_Unicode*)L"file:///" ) ) + return _osl_openLocalRoot( ustrDirectoryURL, pDirectory ); + + /* convert file URL to system path */ + eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False); + + if( osl_File_E_None != eRet ) + return eRet; + + osl_systemPathRemoveSeparator(ustrSystemPath); + + /* convert unicode path to text */ + if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) ) + { + // if only the drive is specified (x:), add a \ (x:\) otherwise current + // directory is browsed instead of root. + if (strlen( path) == 2 && path[1] == ':') + strcat( path, "\\"); + /* open directory */ + DIR *pdir = opendir( path ); + + if( pdir ) + { + /* create and initialize impl structure */ + DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); + + if( pDirImpl ) + { + pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM; + pDirImpl->pDirStruct = pdir; + pDirImpl->ustrPath = ustrSystemPath; + + *pDirectory = (oslDirectory) pDirImpl; + return osl_File_E_None; + } + else + { + errno = ENOMEM; + closedir( pdir ); + } + } + else + /* should be removed by optimizer in product version */ + PERROR( "osl_openDirectory", path ); + } + + rtl_uString_release( ustrSystemPath ); + + return oslTranslateFileError(OSL_FET_ERROR, errno); +} + + +/**************************************************************************** + * osl_getNextDirectoryItem + ***************************************************************************/ + +oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 uHint) +{ + DirectoryImpl* pDirImpl = (DirectoryImpl*)Directory; + DirectoryItem_Impl *pItemImpl = NULL; + rtl_uString* ustrFileName = NULL; + rtl_uString* ustrFilePath = NULL; + struct dirent* pEntry; + + OSL_ASSERT(Directory); + OSL_ASSERT(pItem); + + if ((NULL == Directory) || (NULL == pItem)) + return osl_File_E_INVAL; + + if ( pDirImpl->uType == DIRECTORYTYPE_LOCALROOT) + return _osl_getNextDrive( Directory, pItem, uHint ); + + pEntry = _osl_readdir_impl_(pDirImpl->pDirStruct, sal_True); + + if (NULL == pEntry) + return osl_File_E_NOENT; + + pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); + if ( !pItemImpl ) + return osl_File_E_NOMEM; + + memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); + pItemImpl->uType = DIRECTORYITEM_FILE; + pItemImpl->nRefCount = 1; + pItemImpl->d_attr = pEntry->d_attr; + + /* convert file name to unicode */ + rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ), + osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(ustrFileName != 0); + + osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &pItemImpl->ustrFilePath); + rtl_uString_release( ustrFileName ); + + *pItem = (oslDirectoryItem)pItemImpl; + return osl_File_E_None; +} + +/****************************************************************************/ +/* osl_closeDirectory */ +/****************************************************************************/ + +oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory ) +{ + DirectoryImpl* pDirImpl = (DirectoryImpl*) Directory; + oslFileError err = osl_File_E_None; + + OSL_ASSERT( Directory ); + + if( NULL == pDirImpl ) + return osl_File_E_INVAL; + + switch ( pDirImpl->uType ) + { + case DIRECTORYTYPE_FILESYSTEM: + if( closedir( pDirImpl->pDirStruct ) ) + err = oslTranslateFileError(OSL_FET_ERROR, errno); + break; + case DIRECTORYTYPE_LOCALROOT: + err = osl_File_E_None; + break; +#if 0 + case DIRECTORYTYPE_NETROOT: + { + DWORD err = WNetCloseEnum(pDirImpl->hDirectory); + eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err); + } + break; +#endif + default: + OSL_ENSURE( 0, "Invalid directory type" ); + break; + } + + /* cleanup members */ + rtl_uString_release( pDirImpl->ustrPath ); + + rtl_freeMemory( pDirImpl ); + + return err; +} + +/****************************************************************************/ +/* osl_getDirectoryItem */ +/****************************************************************************/ + +oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem ) +{ + rtl_uString* strSysFilePath = NULL; + oslFileError error = osl_File_E_INVAL; + ULONG dwPathType; + PATHTYPE type = PATHTYPE_FILE; + + OSL_ASSERT(ustrFileURL); + OSL_ASSERT(pItem); + + /* Assume failure */ + if ( !pItem ) + return osl_File_E_INVAL; + *pItem = NULL; + + if (0 == ustrFileURL->length || NULL == pItem) + return osl_File_E_INVAL; + + error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &strSysFilePath, sal_False); + + if (osl_File_E_None != error) + return error; + + dwPathType = IsValidFilePath( strSysFilePath->buffer, NULL, VALIDATEPATH_NORMAL ); + + if ( dwPathType & PATHTYPE_IS_VOLUME ) + type = PATHTYPE_VOLUME; + else if ( dwPathType & PATHTYPE_IS_SERVER ) + type = PATHTYPE_NETSERVER; + else + type = PATHTYPE_FILE; + + switch ( type ) + { + case PATHTYPE_NETSERVER: + { + DirectoryItem_Impl* pItemImpl = + reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); + + if ( !pItemImpl ) + error = osl_File_E_NOMEM; + + if ( osl_File_E_None == error ) + { + memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); + pItemImpl->uType = DIRECTORYITEM_SERVER; + pItemImpl->nRefCount = 1; + rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); + + *pItem = pItemImpl; + } + } + break; + case PATHTYPE_VOLUME: + { + DirectoryItem_Impl* pItemImpl = + reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); + + if ( !pItemImpl ) + error = osl_File_E_NOMEM; + + if ( osl_File_E_None == error ) + { + memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); + pItemImpl->uType = DIRECTORYITEM_DRIVE; + pItemImpl->nRefCount = 1; + rtl_uString_assign( &pItemImpl->ustrDrive, strSysFilePath ); + + if ( pItemImpl->ustrDrive->buffer[pItemImpl->ustrDrive->length-1] != sal_Unicode('\\') ) + rtl_uString_newConcat( &pItemImpl->ustrDrive, + pItemImpl->ustrDrive, rtl::OUString::createFromAscii( "\\" ).pData); + + *pItem = pItemImpl; + } + } + break; + default: + case PATHTYPE_FILE: + { + if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' ) + rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 ); + + if (0 == access_u(strSysFilePath, F_OK)) + { + DirectoryItem_Impl *pItemImpl = + reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); + + memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); + pItemImpl->uType = DIRECTORYITEM_FILE; + pItemImpl->nRefCount = 1; + rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); + + *pItem = pItemImpl; + } + else + error = oslTranslateFileError(OSL_FET_ERROR, errno); + } + break; + } + + if ( strSysFilePath ) + rtl_uString_release( strSysFilePath ); + + return error; +} + +/****************************************************************************/ +/* osl_acquireDirectoryItem */ +/****************************************************************************/ + +oslFileError osl_acquireDirectoryItem( oslDirectoryItem Item ) +{ + OSL_ASSERT( Item ); + DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; + + if ( !pItemImpl ) + return osl_File_E_INVAL; + + pItemImpl->nRefCount++; + return osl_File_E_None; +} + +/****************************************************************************/ +/* osl_releaseDirectoryItem */ +/****************************************************************************/ + +oslFileError osl_releaseDirectoryItem( oslDirectoryItem Item ) +{ + OSL_ASSERT( Item ); + DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; + + if ( !pItemImpl ) + return osl_File_E_INVAL; + + if ( ! --pItemImpl->nRefCount ) + { + if (pItemImpl->ustrFilePath) + rtl_uString_release( pItemImpl->ustrFilePath ); + if (pItemImpl->ustrDrive) + rtl_uString_release( pItemImpl->ustrDrive ); + rtl_freeMemory( pItemImpl ); + } + return osl_File_E_None; +} + +/**************************************************************************** + * osl_createFileHandleFromFD + ***************************************************************************/ + +oslFileHandle osl_createFileHandleFromFD( int fd ) +{ + oslFileHandleImpl* pHandleImpl = NULL; + + if ( fd >= 0 ) + { + pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) ); + + if( pHandleImpl ) + { + pHandleImpl->ustrFilePath = NULL; + rtl_uString_new( &pHandleImpl->ustrFilePath ); + pHandleImpl->fd = fd; + + /* FIXME: should detect whether the file has been locked */ + pHandleImpl->bLocked = sal_True; + } + } + + return (oslFileHandle)pHandleImpl; +} + +/**************************************************************************** + * osl_openFile + ***************************************************************************/ + +oslFileError osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags ) +{ + oslFileHandleImpl* pHandleImpl = NULL; + oslFileError eRet; + rtl_uString* ustrFilePath = NULL; + + char buffer[PATH_MAX]; + int fd; + int mode = S_IRUSR | S_IRGRP | S_IROTH; + int flags = O_RDONLY; + + struct flock aflock; + + /* locking the complete file */ + aflock.l_type = 0; + aflock.l_whence = SEEK_SET; + aflock.l_start = 0; + aflock.l_len = 0; + + OSL_ASSERT( ustrFileURL ); + OSL_ASSERT( pHandle ); + + if( ( 0 == ustrFileURL->length ) ) + return osl_File_E_INVAL; + + /* convert file URL to system path */ + eRet = osl_getSystemPathFromFileURL( ustrFileURL, &ustrFilePath ); + + if( osl_File_E_None != eRet ) + return eRet; + + osl_systemPathRemoveSeparator(ustrFilePath); + + /* convert unicode path to text */ + if( UnicodeToText( buffer, PATH_MAX, ustrFilePath->buffer, ustrFilePath->length ) ) + { + /* we do not open devices or such here */ + if( !( uFlags & osl_File_OpenFlag_Create ) ) + { + struct stat aFileStat; + + if( 0 > stat( buffer, &aFileStat ) ) + { + PERROR( "osl_openFile", buffer ); + eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); + } + + else if( !S_ISREG( aFileStat.st_mode ) ) + { + eRet = osl_File_E_INVAL; + } + } + + if( osl_File_E_None == eRet ) + { + /* + * set flags and mode + */ + + if ( uFlags & osl_File_OpenFlag_Write ) + { + mode |= S_IWUSR | S_IWGRP | S_IWOTH; + flags = O_RDWR; + aflock.l_type = F_WRLCK; + } + + if ( uFlags & osl_File_OpenFlag_Create ) + { + mode |= S_IWUSR | S_IWGRP | S_IWOTH; + flags = O_CREAT | O_EXCL | O_RDWR; + } + + /* open the file */ + fd = open( buffer, flags | O_BINARY, mode); + if ( fd >= 0 ) + { + sal_Bool bNeedsLock = ( ( uFlags & osl_File_OpenFlag_NoLock ) == 0 ); + sal_Bool bLocked = sal_False; + if( bNeedsLock ) + { + /* check if file lock is enabled and clear l_type member of flock otherwise */ + if( (char *) -1 == pFileLockEnvVar ) + { + /* FIXME: this is not MT safe */ + pFileLockEnvVar = getenv("SAL_ENABLE_FILE_LOCKING"); + + if( NULL == pFileLockEnvVar) + pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING"); + } + + if( NULL == pFileLockEnvVar ) + aflock.l_type = 0; + + /* lock the file if flock.l_type is set */ + bLocked = ( F_WRLCK != aflock.l_type || -1 != fcntl( fd, F_SETLK, &aflock ) ); + } + + if ( !bNeedsLock || bLocked ) + { + /* allocate memory for impl structure */ + pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) ); + if( pHandleImpl ) + { + pHandleImpl->ustrFilePath = ustrFilePath; + pHandleImpl->fd = fd; + pHandleImpl->bLocked = bLocked; + + *pHandle = (oslFileHandle) pHandleImpl; + + return osl_File_E_None; + } + else + { + errno = ENOMEM; + } + } + + close( fd ); + } + + PERROR( "osl_openFile", buffer ); + eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); + } + } + else + eRet = osl_File_E_INVAL; + + rtl_uString_release( ustrFilePath ); + return eRet; +} + +/****************************************************************************/ +/* osl_closeFile */ +/****************************************************************************/ + +oslFileError osl_closeFile( oslFileHandle Handle ) +{ + oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle; + oslFileError eRet = osl_File_E_INVAL; + + OSL_ASSERT( Handle ); + + if( pHandleImpl ) + { + rtl_uString_release( pHandleImpl->ustrFilePath ); + + /* release file lock if locking is enabled */ + if( pFileLockEnvVar ) + { + struct flock aflock; + + aflock.l_type = F_UNLCK; + aflock.l_whence = SEEK_SET; + aflock.l_start = 0; + aflock.l_len = 0; + + if ( pHandleImpl->bLocked ) + { + /* FIXME: check if file is really locked ? */ + + /* release the file share lock on this file */ + if( -1 == fcntl( pHandleImpl->fd, F_SETLK, &aflock ) ) + PERROR( "osl_closeFile", "unlock failed" ); + } + } + + if( 0 > close( pHandleImpl->fd ) ) + { + eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); + } + else + eRet = osl_File_E_None; + + rtl_freeMemory( pHandleImpl ); + } + + return eRet; +} + +/****************************************************************************/ +/* osl_isEndOfFile */ +/****************************************************************************/ + +oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ) +{ + oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle; + oslFileError eRet = osl_File_E_INVAL; + + if ( pHandleImpl) + { + long curPos = lseek( pHandleImpl->fd, 0, SEEK_CUR ); + + if ( curPos >= 0 ) + { + long endPos = lseek( pHandleImpl->fd, 0, SEEK_END ); + + if ( endPos >= 0 ) + { + *pIsEOF = ( curPos == endPos ); + curPos = lseek( pHandleImpl->fd, curPos, SEEK_SET ); + + if ( curPos >= 0 ) + eRet = osl_File_E_None; + else + eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); + } + else + eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); + } + else + eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); + } + + return eRet; +} + + +/****************************************************************************/ +/* osl_moveFile */ +/****************************************************************************/ + +oslFileError osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) +{ + char srcPath[PATH_MAX]; + char destPath[PATH_MAX]; + oslFileError eRet; + APIRET rc; + + OSL_ASSERT( ustrFileURL ); + OSL_ASSERT( ustrDestURL ); + + /* convert source url to system path */ + eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); + if( eRet != osl_File_E_None ) + return eRet; + + /* convert destination url to system path */ + eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); + if( eRet != osl_File_E_None ) + return eRet; + + //YD 01/05/06 rename() can overwrite existing files. + rc = DosDelete( (PCSZ)destPath); + rc = DosMove( (PCSZ)srcPath, (PCSZ)destPath); + if (!rc) + eRet = osl_File_E_None; + else + eRet = MapError( rc); + + return eRet; +} + +/****************************************************************************/ +/* osl_copyFile */ +/****************************************************************************/ + +#define TMP_DEST_FILE_EXTENSION ".osl-tmp" + +static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists) +{ + int nRet=0; + sal_Char pszTmpDestFile[PATH_MAX]; + size_t size_tmp_dest_buff = sizeof(pszTmpDestFile); + + /* Quick fix for #106048, the whole copy file function seems + to be erroneous anyway and needs to be rewritten. + Besides osl_copyFile is currently not used from OO/SO code. + */ + memset(pszTmpDestFile, 0, size_tmp_dest_buff); + + if ( DestFileExists ) + { + strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1); + + if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff) + return osl_File_E_NAMETOOLONG; + + strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION)); + + /* FIXME: what if pszTmpDestFile already exists? */ + /* with getcanonical??? */ + nRet=rename(pszDestFileName,pszTmpDestFile); + } + + /* mfe: should be S_ISREG */ + if ( !S_ISLNK(nMode) ) + { + /* copy SourceFile to DestFile */ + nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode); + } + /* mfe: OK redundant at the moment */ + else if ( S_ISLNK(nMode) ) + { + nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName); + } + else + { + /* mfe: what to do here? */ + nRet=ENOSYS; + } + + if ( nRet > 0 && DestFileExists == 1 ) + { + unlink(pszDestFileName); + rename(pszTmpDestFile,pszDestFileName); + } + + if ( nRet > 0 ) + { + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + if ( DestFileExists == 1 ) + { + unlink(pszTmpDestFile); + } + + return osl_File_E_None; +} + +/***************************************** + * oslChangeFileModes + ****************************************/ + +static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID) +{ + int nRet=0; + struct utimbuf aTimeBuffer; + + nRet = chmod(pszFileName,nMode); + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + aTimeBuffer.actime=nAcTime; + aTimeBuffer.modtime=nModTime; + nRet=utime(pszFileName,&aTimeBuffer); + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + if ( nUID != getuid() ) + { + nUID=getuid(); + } + + nRet=chown(pszFileName,nUID,nGID); + if ( nRet < 0 ) + { + nRet=errno; + + /* mfe: do not return an error here! */ + /* return oslTranslateFileError(nRet);*/ + } + + return osl_File_E_None; +} + +/***************************************** + * oslDoCopyLink + ****************************************/ + +static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName) +{ + int nRet=0; + + /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */ + /* mfe: if source is a link copy the link and not the file it points to (hro says so) */ + sal_Char pszLinkContent[PATH_MAX]; + + pszLinkContent[0] = '\0'; + + nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX); + + if ( nRet < 0 ) + { + nRet=errno; + return nRet; + } + else + pszLinkContent[ nRet ] = 0; + + nRet = symlink(pszLinkContent,pszDestFileName); + + if ( nRet < 0 ) + { + nRet=errno; + return nRet; + } + + return 0; +} + +/***************************************** + * oslDoCopyFile + ****************************************/ + +static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode) +{ + int SourceFileFD=0; + int DestFileFD=0; + int nRet=0; + void* pSourceFile=0; + char buffer[ 4096]; + + SourceFileFD=open(pszSourceFileName,O_RDONLY | O_BINARY); + if ( SourceFileFD < 0 ) + { + nRet=errno; + return nRet; + } + + DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT | O_BINARY, mode); + if ( DestFileFD < 0 ) + { + nRet=errno; + close(SourceFileFD); + return nRet; + } + + /* HACK: because memory mapping fails on various + platforms if the size of the source file is 0 byte */ + if (0 == nSourceSize) + { + close(SourceFileFD); + close(DestFileFD); + return 0; + } + + while( (nRet = read(SourceFileFD, buffer, sizeof(buffer))) !=0 ) + { + nRet = write( DestFileFD, buffer, nRet); + } + + close(SourceFileFD); + close(DestFileFD); + + return nRet; +} + +static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) +{ + time_t nAcTime=0; + time_t nModTime=0; + uid_t nUID=0; + gid_t nGID=0; + int nRet=0; + mode_t nMode=0; + struct stat aFileStat; + oslFileError tErr=osl_File_E_invalidError; + size_t nSourceSize=0; + int DestFileExists=1; + + /* mfe: does the source file really exists? */ + nRet = lstat(pszPath,&aFileStat); + + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + /* mfe: we do only copy files here! */ + if ( S_ISDIR(aFileStat.st_mode) ) + { + return osl_File_E_ISDIR; + } + + nSourceSize=(size_t)aFileStat.st_size; + nMode=aFileStat.st_mode; + nAcTime=aFileStat.st_atime; + nModTime=aFileStat.st_mtime; + nUID=aFileStat.st_uid; + nGID=aFileStat.st_gid; + + nRet = stat(pszDestPath,&aFileStat); + if ( nRet < 0 ) + { + nRet=errno; + + if ( nRet == ENOENT ) + { + DestFileExists=0; + } +/* return oslTranslateFileError(nRet);*/ + } + + /* mfe: the destination file must not be a directory! */ + if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) + { + return osl_File_E_ISDIR; + } + else + { + /* mfe: file does not exists or is no dir */ + } + + tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); + + if ( tErr != osl_File_E_None ) + { + return tErr; + } + + /* + * mfe: ignore return code + * since only the success of the copy is + * important + */ + oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); + + return tErr; +} + +oslFileError osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) +{ + char srcPath[PATH_MAX]; + char destPath[PATH_MAX]; + oslFileError eRet; + APIRET rc; + + OSL_ASSERT( ustrFileURL ); + OSL_ASSERT( ustrDestURL ); + + /* convert source url to system path */ + eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); + if( eRet != osl_File_E_None ) + return eRet; + + /* convert destination url to system path */ + eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); + if( eRet != osl_File_E_None ) + return eRet; + + return osl_psz_copyFile( srcPath, destPath ); +} + +/****************************************************************************/ +/* osl_removeFile */ +/****************************************************************************/ + +oslFileError osl_removeFile( rtl_uString* ustrFileURL ) +{ + char path[PATH_MAX]; + oslFileError eRet; + APIRET rc; + + OSL_ASSERT( ustrFileURL ); + + /* convert file url to system path */ + eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); + if( eRet != osl_File_E_None ) + return eRet; + + rc = DosDelete( (PCSZ)path); + if (!rc) + eRet = osl_File_E_None; + else + eRet = MapError( rc); + + return eRet; +} + +/****************************************************************************/ +/* osl_getVolumeInformation */ +/****************************************************************************/ + +#define TXFSDC_BLOCKR 0x00 // block device removable +#define TXFSDC_GETBPB 0x00 // get device bpb info +#define TXFSBPB_REMOVABLE 0x08 // BPB attribute for removable + +typedef struct drivecmd +{ + BYTE cmd; // 0=unlock 1=lock 2=eject + BYTE drv; // 0=A, 1=B 2=C ... +} DRIVECMD; // end of struct "drivecmd" + +#pragma pack(push, 1) // byte packing +typedef struct txfs_ebpb // ext. boot parameter block +{ // at offset 0x0b in bootsector + USHORT SectSize; // 0B bytes per sector + BYTE ClustSize; // 0D sectors per cluster + USHORT FatOffset; // 0E sectors to 1st FAT + BYTE NrOfFats; // 10 nr of FATS (FAT only) + USHORT RootEntries; // 11 Max entries \ (FAT only) + USHORT Sectors; // 13 nr of sectors if < 64K + BYTE MediaType; // 15 mediatype (F8 for HD) + USHORT FatSectors; // 16 sectors/FAT (FAT only) + USHORT LogGeoSect; // 18 sectors/Track + USHORT LogGeoHead; // 1a nr of heads + ULONG HiddenSectors; // 1c sector-offset from MBR/EBR + ULONG BigSectors; // 20 nr of sectors if >= 64K +} TXFS_EBPB; // last byte is at offset 0x23 + +typedef struct drivebpb +{ + TXFS_EBPB ebpb; // extended BPB + BYTE reserved[6]; + USHORT cyls; + BYTE type; + USHORT attributes; // device attributes + BYTE fill[6]; // documented for IOCtl +} DRIVEBPB; // end of struct "drivebpb" + +struct CDInfo { + USHORT usCount; + USHORT usFirst; +}; + +#pragma pack(pop) + +/*****************************************************************************/ +// Get number of cdrom readers +/*****************************************************************************/ +BOOL GetCDInfo( CDInfo * pCDInfo ) +{ + HFILE hFileCD; + ULONG ulAction; + + if( NO_ERROR == DosOpen( (PCSZ)"\\DEV\\CD-ROM2$", + &hFileCD, &ulAction, 0, FILE_NORMAL, + OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL )) { + ULONG ulDataSize = sizeof(CDInfo); + APIRET rc = DosDevIOCtl( hFileCD, 0x82, 0x60, NULL, 0, + NULL, (PVOID)pCDInfo, ulDataSize, &ulDataSize); + DosClose( hFileCD); + if(rc == NO_ERROR) + return TRUE; + } + // failed + pCDInfo->usFirst = 0; + pCDInfo->usCount = 0; + return FALSE; +} + +/*****************************************************************************/ +// Determine if unit is a cdrom or not +/*****************************************************************************/ +BOOL DriveIsCDROM(UINT uiDrive, CDInfo *pCDInfo) +{ + return (uiDrive >= pCDInfo->usFirst) + && (uiDrive < (pCDInfo->usFirst + pCDInfo->usCount)); +} + +/*****************************************************************************/ +// Determine attached fstype, e.g. HPFS for specified drive +/*****************************************************************************/ +BOOL TxFsType // RET FS type resolved +( + char *drive, // IN Drive specification + char *fstype, // OUT Attached FS type + char *details // OUT details (UNC) or NULL +) +{ + BOOL rc = FALSE; + FSQBUFFER2 *fsinfo; // Attached FS info + ULONG fsdlen = 2048; // Fs info data length + + strcpy(fstype, "none"); + if (details) + { + strcpy(details, ""); + } + if ((fsinfo = (FSQBUFFER2*)calloc(1, fsdlen)) != NULL) + { + if (DosQFSAttach((PCSZ)drive, 0, 1, fsinfo, &fsdlen) == NO_ERROR) + { + strcpy(fstype, (char*) fsinfo->szName + fsinfo->cbName +1); + if (details && (fsinfo->cbFSAData != 0)) + { + strcpy( details, (char*) fsinfo->szName + fsinfo->cbName + + fsinfo->cbFSDName +2); + } + rc = TRUE; + } + free(fsinfo); + } + return (rc); +} // end 'TxFsType' +/*---------------------------------------------------------------------------*/ + + +/*****************************************************************************/ +// Determine if a driveletter represents a removable medium/device +/*****************************************************************************/ +BOOL TxFsIsRemovable // RET drive is removable +( + char *drive // IN Driveletter to test +) +{ + BOOL rc = FALSE; + DRIVECMD IOCtl; + DRIVEBPB RemAt; + ULONG DataLen; + ULONG ParmLen; + BYTE NoRem; + + DosError( FERR_DISABLEHARDERR); // avoid 'not ready' popups + + ParmLen = sizeof(IOCtl); + IOCtl.cmd = TXFSDC_BLOCKR; + IOCtl.drv = toupper(drive[0]) - 'A'; + DataLen = sizeof(NoRem); + + if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, + DSK_BLOCKREMOVABLE, + &IOCtl, ParmLen, &ParmLen, + &NoRem, DataLen, &DataLen) == NO_ERROR) + { + if (NoRem) // non-removable sofar, check + { // BPB as well (USB devices) + ParmLen = sizeof(IOCtl); + IOCtl.cmd = TXFSDC_GETBPB; + IOCtl.drv = toupper(drive[0]) - 'A'; + DataLen = sizeof(RemAt); + + if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, + DSK_GETDEVICEPARAMS, + &IOCtl, ParmLen, &ParmLen, + &RemAt, DataLen, &DataLen) == NO_ERROR) + + { + if (RemAt.attributes & TXFSBPB_REMOVABLE) + { + rc = TRUE; // removable, probably USB + } + } + } + else + { + rc = TRUE; // removable block device + } + } + DosError( FERR_ENABLEHARDERR); // enable criterror handler + return (rc); +} // end 'TxFsIsRemovable' +/*---------------------------------------------------------------------------*/ + +static oslFileError get_drive_type(const char* path, oslVolumeInfo* pInfo) +{ + char Drive_Letter = toupper( *path); + char fstype[ 64]; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + + // check for floppy A/B + BYTE nFloppies; + APIRET rc; + rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); + if ((Drive_Letter - 'A') < nFloppies) { + pInfo->uAttributes |= osl_Volume_Attribute_Removeable; + pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk; + return osl_File_E_None; + } + + // query system for CD drives + CDInfo cdInfo; + GetCDInfo(&cdInfo); + + // query if drive is a CDROM + if (DriveIsCDROM( Drive_Letter - 'A', &cdInfo)) + pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; + + if (TxFsIsRemovable( (char*)path)) + pInfo->uAttributes |= osl_Volume_Attribute_Removeable; + + if (TxFsType( (char*)path, fstype, NULL) == FALSE) { + // query failed, assume fixed disk + pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; + return osl_File_E_None; + } + + //- Note, connected Win-NT drives use the REAL FS-name like NTFS! + if ((strncasecmp( fstype, "LAN", 3) == 0) //- OS/2 LAN drives + || (strncasecmp( fstype, "NDFS", 4) == 0) //- NetDrive + || (strncasecmp( fstype, "REMOTE", 5) == 0) ) //- NT disconnected + pInfo->uAttributes |= osl_Volume_Attribute_Remote; + else if (strncasecmp( fstype, "RAMFS", 5) == 0) + pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk; + else if ((strncasecmp( fstype, "CD", 2) == 0) // OS2:CDFS, DOS/WIN:CDROM + || (strncasecmp( fstype, "UDF", 3) == 0) ) // OS2:UDF DVD's + pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; + else + pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; + + return osl_File_E_None; +} + +//############################################# +inline bool is_volume_space_info_request(sal_uInt32 field_mask) +{ + return (field_mask & + (osl_VolumeInfo_Mask_TotalSpace | + osl_VolumeInfo_Mask_UsedSpace | + osl_VolumeInfo_Mask_FreeSpace)); +} + +//############################################# +static void get_volume_space_information(const char* path, oslVolumeInfo *pInfo) +{ + FSALLOCATE aFSInfoBuf; + ULONG nDriveNumber = toupper( *path) - 'A' + 1; + + // disable error popups + DosError(FERR_DISABLEHARDERR); + APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC, + &aFSInfoBuf, sizeof(aFSInfoBuf) ); + // enable error popups + DosError(FERR_ENABLEHARDERR); + if (!rc) + { + uint64_t aBytesPerCluster( uint64_t(aFSInfoBuf.cbSector) * + uint64_t(aFSInfoBuf.cSectorUnit) ); + pInfo->uFreeSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnitAvail); + pInfo->uTotalSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnit); + pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; + pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace | + osl_VolumeInfo_Mask_UsedSpace | + osl_VolumeInfo_Mask_FreeSpace; + } +} + +//############################################# +inline bool is_filesystem_attributes_request(sal_uInt32 field_mask) +{ + return (field_mask & + (osl_VolumeInfo_Mask_MaxNameLength | + osl_VolumeInfo_Mask_MaxPathLength | + osl_VolumeInfo_Mask_FileSystemName | + osl_VolumeInfo_Mask_FileSystemCaseHandling)); +} + +//############################################# +inline bool is_drivetype_request(sal_uInt32 field_mask) +{ + return (field_mask & osl_VolumeInfo_Mask_Attributes); +} + +typedef struct _FSQBUFFER_ +{ + FSQBUFFER2 aBuf; + UCHAR sBuf[64]; +} FSQBUFFER_; + +//############################################# +static oslFileError get_filesystem_attributes(const char* path, sal_uInt32 field_mask, oslVolumeInfo* pInfo) +{ + pInfo->uAttributes = 0; + + oslFileError osl_error = osl_File_E_None; + + // osl_get_drive_type must be called first because + // this function resets osl_VolumeInfo_Mask_Attributes + // on failure + if (is_drivetype_request(field_mask)) + osl_error = get_drive_type(path, pInfo); + + if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask)) + { + FSQBUFFER_ aBuf; + ULONG nBufLen; + APIRET nRet; + + nBufLen = sizeof( aBuf ); + // disable error popups + DosError(FERR_DISABLEHARDERR); + nRet = DosQueryFSAttach( (PCSZ)path, 0, FSAIL_QUERYNAME, (_FSQBUFFER2*) &aBuf, &nBufLen ); + if ( !nRet ) + { + char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1); + pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; + pInfo->uMaxNameLength = _MAX_FNAME; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; + pInfo->uMaxPathLength = _MAX_PATH; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; + rtl_uString_newFromAscii(&pInfo->ustrFileSystemName, pType); + + // case is preserved always except for FAT + if (strcmp( pType, "FAT" )) + pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + } + // enable error popups + DosError(FERR_ENABLEHARDERR); + } + return osl_error; +} + +oslFileError SAL_CALL osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask ) +{ + char volume_root[PATH_MAX]; + oslFileError error; + + OSL_ASSERT( ustrDirectoryURL ); + OSL_ASSERT( pInfo ); + + /* convert directory url to system path */ + error = FileURLToPath( volume_root, PATH_MAX, ustrDirectoryURL ); + if( error != osl_File_E_None ) + return error; + + if (!pInfo) + return osl_File_E_INVAL; + + pInfo->uValidFields = 0; + + if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None) + return error; + + if (is_volume_space_info_request(uFieldMask)) + get_volume_space_information(volume_root, pInfo); + + if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle) + { + pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle; + rtl_uString* uVolumeRoot; + rtl_uString_newFromAscii( &uVolumeRoot, volume_root); + osl_getFileURLFromSystemPath( uVolumeRoot, (rtl_uString**)&pInfo->pDeviceHandle); + rtl_uString_release( uVolumeRoot); + } + + return osl_File_E_None; +} + +/****************************************************************************/ +/* osl_getFileStatus */ +/****************************************************************************/ +static oslFileError _osl_getDriveInfo( + oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask) +{ + DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; + sal_Unicode cDrive[3]; + sal_Unicode cRoot[4]; + + if ( !pItemImpl ) + return osl_File_E_INVAL; + + pStatus->uValidFields = 0; + + cDrive[0] = pItemImpl->ustrDrive->buffer[0]; + cDrive[1] = (sal_Unicode)':'; + cDrive[2] = 0; + cRoot[0] = pItemImpl->ustrDrive->buffer[0]; + cRoot[1] = (sal_Unicode)':'; + cRoot[2] = 0; + + if ( uFieldMask & osl_FileStatus_Mask_FileName ) + { + if ( pItemImpl->ustrDrive->buffer[0] == '\\' && + pItemImpl->ustrDrive->buffer[1] == '\\' ) + { + LPCWSTR lpFirstBkSlash = wcschr( (const wchar_t*)&pItemImpl->ustrDrive->buffer[2], '\\' ); + + if ( lpFirstBkSlash && lpFirstBkSlash[1] ) + { + LPCWSTR lpLastBkSlash = wcschr( (const wchar_t*)&lpFirstBkSlash[1], '\\' ); + + if ( lpLastBkSlash ) + rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1], lpLastBkSlash - lpFirstBkSlash - 1 ); + else + rtl_uString_newFromStr( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1] ); + pStatus->uValidFields |= osl_FileStatus_Mask_FileName; + } + } + else + { + FSINFO aFSInfoBuf; + ULONG ulFSInfoLevel = FSIL_VOLSER; + ULONG nDriveNumber; + char szFileName[ _MAX_PATH]; + + nDriveNumber = toupper(*cDrive) - 'A' + 1; + memset( &aFSInfoBuf, 0, sizeof(FSINFO) ); + // disable error popups + DosError(FERR_DISABLEHARDERR); + APIRET rc = DosQueryFSInfo( nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) ); + // enable error popups + DosError(FERR_ENABLEHARDERR); + memset( szFileName, 0, sizeof( szFileName)); + *szFileName = toupper(*cDrive); + strcat( szFileName, ": ["); + if ( !rc || aFSInfoBuf.vol.cch) + strncat( szFileName, aFSInfoBuf.vol.szVolLabel, aFSInfoBuf.vol.cch); + strcat( szFileName, "]"); + rtl_uString_newFromAscii( &pStatus->ustrFileName, szFileName ); + + pStatus->uValidFields |= osl_FileStatus_Mask_FileName; + } + } + + pStatus->eType = osl_File_Type_Volume; + pStatus->uValidFields |= osl_FileStatus_Mask_Type; + + if ( uFieldMask & osl_FileStatus_Mask_FileURL ) + { + rtl_uString *ustrSystemPath = NULL; + + rtl_uString_newFromStr( &ustrSystemPath, pItemImpl->ustrDrive->buffer ); + osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL ); + rtl_uString_release( ustrSystemPath ); + pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; + } + + return osl_File_E_None; +} + +oslFileError SAL_CALL osl_getFileStatus( + oslDirectoryItem Item, + oslFileStatus *pStatus, + sal_uInt32 uFieldMask ) +{ + DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; + struct stat file_stat; + + if ( !pItemImpl ) + return osl_File_E_INVAL; + + if ( pItemImpl->uType == DIRECTORYITEM_DRIVE) + return _osl_getDriveInfo( Item, pStatus, uFieldMask ); + + osl::lstat(pItemImpl->ustrFilePath, file_stat); + if ( uFieldMask & osl_FileStatus_Mask_Validate ) + { + uFieldMask &= ~ osl_FileStatus_Mask_Validate; + } + + /* If no fields to retrieve left ignore pStatus */ + if ( !uFieldMask ) + return osl_File_E_None; + + /* Otherwise, this must be a valid pointer */ + if ( !pStatus ) + return osl_File_E_INVAL; + + if ( pStatus->uStructSize != sizeof(oslFileStatus) ) + return osl_File_E_INVAL; + + pStatus->uValidFields = 0; + + /* File time stamps */ + + if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime)) + { + pStatus->aModifyTime.Seconds = file_stat.st_mtime; + pStatus->aModifyTime.Nanosec = 0; + pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime; + } + + if ( (uFieldMask & osl_FileStatus_Mask_AccessTime)) + { + pStatus->aAccessTime.Seconds = file_stat.st_atime; + pStatus->aAccessTime.Nanosec = 0; + pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime; + } + + if ( (uFieldMask & osl_FileStatus_Mask_CreationTime)) + { + pStatus->aAccessTime.Seconds = file_stat.st_birthtime; + pStatus->aAccessTime.Nanosec = 0; + pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime; + } + + /* Most of the fields are already set, regardless of requiered fields */ + + osl_systemPathGetFileNameOrLastDirectoryPart(pItemImpl->ustrFilePath, &pStatus->ustrFileName); + pStatus->uValidFields |= osl_FileStatus_Mask_FileName; + + if (S_ISLNK(file_stat.st_mode)) + pStatus->eType = osl_File_Type_Link; + else if (S_ISDIR(file_stat.st_mode)) + pStatus->eType = osl_File_Type_Directory; + else if (S_ISREG(file_stat.st_mode)) + pStatus->eType = osl_File_Type_Regular; + else if (S_ISFIFO(file_stat.st_mode)) + pStatus->eType = osl_File_Type_Fifo; + else if (S_ISSOCK(file_stat.st_mode)) + pStatus->eType = osl_File_Type_Socket; + else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode)) + pStatus->eType = osl_File_Type_Special; + else + pStatus->eType = osl_File_Type_Unknown; + + pStatus->uValidFields |= osl_FileStatus_Mask_Type; + + pStatus->uAttributes = pItemImpl->d_attr; + pStatus->uValidFields |= osl_FileStatus_Mask_Attributes; + + pStatus->uFileSize = file_stat.st_size; + pStatus->uValidFields |= osl_FileStatus_Mask_FileSize; + + if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL ) + { + rtl_uString *ustrFullPath = NULL; + + rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); + osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL ); + rtl_uString_release( ustrFullPath ); + + pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL; + } + + if ( uFieldMask & osl_FileStatus_Mask_FileURL ) + { + rtl_uString *ustrFullPath = NULL; + + rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); + osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL ); + rtl_uString_release( ustrFullPath ); + pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; + } + + return osl_File_E_None; +} + +/****************************************************************************/ +/* osl_createDirectory */ +/****************************************************************************/ + +oslFileError osl_createDirectory( rtl_uString* ustrDirectoryURL ) +{ + char path[PATH_MAX]; + oslFileError eRet; + APIRET rc; + + OSL_ASSERT( ustrDirectoryURL ); + + /* convert directory url to system path */ + eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); + if( eRet != osl_File_E_None ) + return eRet; + + rc = DosCreateDir( (PCSZ)path, NULL); + if (rc == ERROR_ACCESS_DENIED) + rc=ERROR_FILE_EXISTS; + + if (!rc) + eRet = osl_File_E_None; + else + eRet = MapError( rc); + + return eRet; +} + +/****************************************************************************/ +/* osl_removeDirectory */ +/****************************************************************************/ + +oslFileError osl_removeDirectory( rtl_uString* ustrDirectoryURL ) +{ + char path[PATH_MAX]; + oslFileError eRet; + APIRET rc; + + OSL_ASSERT( ustrDirectoryURL ); + + /* convert directory url to system path */ + eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); + if( eRet != osl_File_E_None ) + return eRet; + + rc = DosDeleteDir( (PCSZ)path); + if (!rc) + eRet = osl_File_E_None; + else + eRet = MapError( rc); + + return eRet; +} + +//############################################# +int path_make_parent(sal_Unicode* path) +{ + int i = rtl_ustr_lastIndexOfChar(path, '/'); + + if (i > 0) + { + *(path + i) = 0; + return i; + } + else + return 0; +} + +//############################################# +int create_dir_with_callback( + sal_Unicode* directory_path, + oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, + void* pData) +{ + int mode = S_IRWXU | S_IRWXG | S_IRWXO; + + if (osl::mkdir(directory_path, mode) == 0) + { + if (aDirectoryCreationCallbackFunc) + { + rtl::OUString url; + osl::FileBase::getFileURLFromSystemPath(directory_path, url); + aDirectoryCreationCallbackFunc(pData, url.pData); + } + return 0; + } + return errno; +} + +//############################################# +oslFileError create_dir_recursively_( + sal_Unicode* dir_path, + oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, + void* pData) +{ + OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \ + "Path must not end with a slash"); + + int native_err = create_dir_with_callback( + dir_path, aDirectoryCreationCallbackFunc, pData); + + if (native_err == 0) + return osl_File_E_None; + + if (native_err != ENOENT) + return oslTranslateFileError(OSL_FET_ERROR, native_err); + + // we step back until '/a_dir' at maximum because + // we should get an error unequal ENOENT when + // we try to create 'a_dir' at '/' and would so + // return before + int pos = path_make_parent(dir_path); + + oslFileError osl_error = create_dir_recursively_( + dir_path, aDirectoryCreationCallbackFunc, pData); + + if (osl_File_E_None != osl_error) + return osl_error; + + dir_path[pos] = '/'; + + return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData); +} + +//####################################### +oslFileError SAL_CALL osl_createDirectoryPath( + rtl_uString* aDirectoryUrl, + oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, + void* pData) +{ + if (aDirectoryUrl == NULL) + return osl_File_E_INVAL; + + rtl::OUString sys_path; + oslFileError osl_error = osl_getSystemPathFromFileURL_Ex( + aDirectoryUrl, &sys_path.pData, sal_False); + + if (osl_error != osl_File_E_None) + return osl_error; + + osl::systemPathRemoveSeparator(sys_path); + + // const_cast because sys_path is a local copy which we want to modify inplace instead of + // coyp it into another buffer on the heap again + return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); +} + +/****************************************************************************/ +/* osl_getCanonicalName */ +/****************************************************************************/ + +oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL ) +{ + OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented"); + + rtl_uString_newFromString(pustrValidURL, ustrFileURL); + return osl_File_E_None; +} + + +/****************************************************************************/ +/* osl_setFileAttributes */ +/****************************************************************************/ + +oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes ) +{ + char path[PATH_MAX]; + oslFileError eRet; + FILESTATUS3 fsts3ConfigInfo; + ULONG ulBufSize = sizeof(FILESTATUS3); + APIRET rc = NO_ERROR; + + OSL_ASSERT( ustrFileURL ); + + /* convert file url to system path */ + eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); + if( eRet != osl_File_E_None ) + return eRet; + + /* query current attributes */ + rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize); + if (rc != NO_ERROR) + return MapError( rc); + + /* set/reset readonly/hidden (see w32\file.cxx) */ + fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN); + if ( uAttributes & osl_File_Attribute_ReadOnly ) + fsts3ConfigInfo.attrFile |= FILE_READONLY; + if ( uAttributes & osl_File_Attribute_Hidden ) + fsts3ConfigInfo.attrFile |= FILE_HIDDEN; + + /* write new attributes */ + rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0); + if (rc != NO_ERROR) + return MapError( rc); + + /* everything ok */ + return osl_File_E_None; +} + +/****************************************************************************/ +/* osl_setFileTime */ +/****************************************************************************/ + +oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime, + const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime ) +{ + char path[PATH_MAX]; + oslFileError eRet; + + OSL_ASSERT( ustrFileURL ); + + /* convert file url to system path */ + eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); + if( eRet != osl_File_E_None ) + return eRet; + + return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime ); +} + +/****************************************************************************** + * + * Exported Module Functions + * (independent of C or Unicode Strings) + * + *****************************************************************************/ + + +/******************************************* + osl_readFile +********************************************/ + +oslFileError osl_readFile(oslFileHandle Handle, void* pBuffer, sal_uInt64 uBytesRequested, sal_uInt64* pBytesRead) +{ + ssize_t nBytes = 0; + oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle; + + if ((0 == pHandleImpl) || (pHandleImpl->fd < 0) || (0 == pBuffer) || (0 == pBytesRead)) + return osl_File_E_INVAL; + + nBytes = read(pHandleImpl->fd, pBuffer, uBytesRequested); + + if (-1 == nBytes) + return oslTranslateFileError(OSL_FET_ERROR, errno); + + *pBytesRead = nBytes; + return osl_File_E_None; +} + +/******************************************* + osl_writeFile +********************************************/ + +oslFileError osl_writeFile(oslFileHandle Handle, const void* pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64* pBytesWritten) +{ + ssize_t nBytes = 0; + oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle; + + OSL_ASSERT(pHandleImpl); + OSL_ASSERT(pBuffer); + OSL_ASSERT(pBytesWritten); + + if ((0 == pHandleImpl) || (0 == pBuffer) || (0 == pBytesWritten)) + return osl_File_E_INVAL; + + OSL_ASSERT(pHandleImpl->fd >= 0); + + if (pHandleImpl->fd < 0) + return osl_File_E_INVAL; + + nBytes = write(pHandleImpl->fd, pBuffer, uBytesToWrite); + + if (-1 == nBytes) + return oslTranslateFileError(OSL_FET_ERROR, errno); + + *pBytesWritten = nBytes; + return osl_File_E_None; +} + +/******************************************* + osl_writeFile +********************************************/ + +oslFileError osl_setFilePos( oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uPos ) +{ + oslFileHandleImpl* pHandleImpl=0; + int nRet=0; + off_t nOffset=0; + + pHandleImpl = (oslFileHandleImpl*) Handle; + if ( pHandleImpl == 0 ) + { + return osl_File_E_INVAL; + } + + if ( pHandleImpl->fd < 0 ) + { + return osl_File_E_INVAL; + } + + /* FIXME mfe: setFilePos: Do we have any runtime function to determine LONG_MAX? */ + if ( uPos > LONG_MAX ) + { + return osl_File_E_OVERFLOW; + } + + nOffset=(off_t)uPos; + + switch(uHow) + { + case osl_Pos_Absolut: + nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_SET); + break; + + case osl_Pos_Current: + nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_CUR); + break; + + case osl_Pos_End: + nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_END); + break; + + default: + return osl_File_E_INVAL; + } + + if ( nOffset < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + return osl_File_E_None; +} + +/************************************************ + * osl_getFilePos + ***********************************************/ + +oslFileError osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos ) +{ + oslFileHandleImpl* pHandleImpl=0; + off_t nOffset=0; + int nRet=0; + + pHandleImpl = (oslFileHandleImpl*) Handle; + if ( pHandleImpl == 0 || pPos == 0) + { + return osl_File_E_INVAL; + } + + if ( pHandleImpl->fd < 0 ) + { + return osl_File_E_INVAL; + } + + nOffset = lseek(pHandleImpl->fd,0,SEEK_CUR); + + if (nOffset < 0) + { + nRet =errno; + + /* *pPos =0; */ + + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + *pPos=nOffset; + + return osl_File_E_None; +} + +/**************************************************************************** + * osl_getFileSize + ****************************************************************************/ + +oslFileError osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize ) +{ + oslFileHandleImpl* pHandleImpl=(oslFileHandleImpl*) Handle; + if (pHandleImpl == 0) + return osl_File_E_INVAL; + + struct stat file_stat; + if (fstat(pHandleImpl->fd, &file_stat) == -1) + return oslTranslateFileError(OSL_FET_ERROR, errno); + + *pSize = file_stat.st_size; + return osl_File_E_None; +} + +/************************************************ + * osl_setFileSize + ***********************************************/ + +oslFileError osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize ) +{ + oslFileHandleImpl* pHandleImpl=0; + off_t nOffset=0; + + pHandleImpl = (oslFileHandleImpl*) Handle; + if ( pHandleImpl == 0 ) + { + return osl_File_E_INVAL; + } + + if ( pHandleImpl->fd < 0 ) + { + return osl_File_E_INVAL; + } + + /* FIXME: mfe: setFileSize: Do we have any runtime function to determine LONG_MAX? */ + if ( uSize > LONG_MAX ) + { + return osl_File_E_OVERFLOW; + } + + nOffset = (off_t)uSize; + if (ftruncate (pHandleImpl->fd, nOffset) < 0) + { + /* Failure. Try fallback algorithm */ + oslFileError result; + struct stat aStat; + off_t nCurPos; + + /* Save original result */ + result = oslTranslateFileError (OSL_FET_ERROR, errno); + PERROR("ftruncate", "Try osl_setFileSize [fallback]\n"); + + /* Check against current size. Fail upon 'shrink' */ + if (fstat (pHandleImpl->fd, &aStat) < 0) + { + PERROR("ftruncate: fstat", "Out osl_setFileSize [error]\n"); + return (result); + } + if ((0 <= nOffset) && (nOffset <= aStat.st_size)) + { + /* Failure upon 'shrink'. Return original result */ + return (result); + } + + /* Save current position */ + nCurPos = (off_t)lseek (pHandleImpl->fd, (off_t)0, SEEK_CUR); + if (nCurPos == (off_t)(-1)) + { + PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n"); + return (result); + } + + /* Try 'expand' via 'lseek()' and 'write()' */ + if (lseek (pHandleImpl->fd, (off_t)(nOffset - 1), SEEK_SET) < 0) + { + PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n"); + return (result); + } + if (write (pHandleImpl->fd, (char*)"", (size_t)1) < 0) + { + /* Failure. Restore saved position */ + PERROR("ftruncate: write", "Out osl_setFileSize [error]\n"); + if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0) + { +#ifdef DEBUG_OSL_FILE + perror("ftruncate: lseek"); +#endif /* DEBUG_OSL_FILE */ + } + return (result); + } + + /* Success. Restore saved position */ + if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0) + { + PERROR("ftruncate: lseek", "Out osl_setFileSize [error]"); + return (result); + } + } + + return (osl_File_E_None); +} + +/*###############################################*/ +oslFileError SAL_CALL osl_syncFile(oslFileHandle Handle) +{ + oslFileHandleImpl* handle_impl = (oslFileHandleImpl*)Handle; + + if (handle_impl == 0) + return osl_File_E_INVAL; + + if (fsync(handle_impl->fd) == -1) + return oslTranslateFileError(OSL_FET_ERROR, errno); + + return osl_File_E_None; +} + +/****************************************************************************** + * + * C-String Versions of Exported Module Functions + * + *****************************************************************************/ + +#ifdef HAVE_STATFS_H + +#if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX) +# define __OSL_STATFS_STRUCT struct statfs +# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs)) +# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize)) +# define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename) +# define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0) + +/* always return true if queried for the properties of + the file system. If you think this is wrong under any + of the target platforms fix it!!!! */ +# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1) +# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1) +#endif /* FREEBSD || NETBSD */ + +#if defined(LINUX) +# define __OSL_NFS_SUPER_MAGIC 0x6969 +# define __OSL_SMB_SUPER_MAGIC 0x517B +# define __OSL_MSDOS_SUPER_MAGIC 0x4d44 +# define __OSL_NTFS_SUPER_MAGIC 0x5346544e +# define __OSL_STATFS_STRUCT struct statfs +# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs)) +# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize)) +# define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type) +# define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type) +# define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a))) +# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type)) +# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type)) +#endif /* LINUX */ + +#if defined(SOLARIS) || defined(IRIX) +# 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 || IRIX*/ + +# define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT))) + +#else /* no statfs available */ + +# define __OSL_STATFS_STRUCT struct dummy {int i;} +# define __OSL_STATFS_INIT(a) ((void)0) +# define __OSL_STATFS(dir, sfs) (1) +# define __OSL_STATFS_ISREMOTE(sfs) (0) +# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1) +# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1) +#endif /* HAVE_STATFS_H */ + + +static oslFileError osl_psz_getVolumeInformation ( + const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask) +{ + __OSL_STATFS_STRUCT sfs; + + if (!pInfo) + return osl_File_E_INVAL; + + __OSL_STATFS_INIT(sfs); + + pInfo->uValidFields = 0; + pInfo->uAttributes = 0; + + if ((__OSL_STATFS(pszDirectory, &sfs)) < 0) + { + oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno); + return (result); + } + + /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */ + if (uFieldMask & osl_VolumeInfo_Mask_Attributes) + { + if (__OSL_STATFS_ISREMOTE(sfs)) + pInfo->uAttributes |= osl_Volume_Attribute_Remote; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + } + + if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling) + { + if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs)) + pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive; + + if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs)) + pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + } + + pInfo->uTotalSpace = 0; + pInfo->uFreeSpace = 0; + pInfo->uUsedSpace = 0; + +#if defined(__OSL_STATFS_BLKSIZ) + + if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) || + (uFieldMask & osl_VolumeInfo_Mask_UsedSpace)) + { + pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs); + pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks); + pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace; + } + + if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) || + (uFieldMask & osl_VolumeInfo_Mask_UsedSpace)) + { + pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs); + + if (getuid() == 0) + pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree); + else + pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail); + + pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace; + } + +#endif /* __OSL_STATFS_BLKSIZ */ + + if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) && + (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace )) + { + pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; + pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace; + } + + pInfo->uMaxNameLength = 0; + if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength) + { + long nLen = pathconf(pszDirectory, _PC_NAME_MAX); + if (nLen > 0) + { + pInfo->uMaxNameLength = (sal_uInt32)nLen; + pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; + } + } + + pInfo->uMaxPathLength = 0; + if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength) + { + long nLen = pathconf (pszDirectory, _PC_PATH_MAX); + if (nLen > 0) + { + pInfo->uMaxPathLength = (sal_uInt32)nLen; + pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; + } + } + +#if defined(__OSL_STATFS_TYPENAME) + + if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName) + { + rtl_string2UString( + &(pInfo->ustrFileSystemName), + __OSL_STATFS_TYPENAME(sfs), + rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS); + OSL_ASSERT(pInfo->ustrFileSystemName != 0); + + pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; + } + +#endif /* __OSL_STATFS_TYPENAME */ + + if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle) + { + /* FIXME: check also entries in mntent for the device + and fill it with correct values */ + + *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory); + + if (*pInfo->pDeviceHandle) + { + pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle; + pInfo->uAttributes |= osl_Volume_Attribute_Removeable; + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + } + } + return osl_File_E_None; +} + +/****************************************** + * osl_psz_setFileTime + *****************************************/ + +static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath, + const TimeValue* /*pCreationTime*/, + const TimeValue* pLastAccessTime, + const TimeValue* pLastWriteTime ) +{ + int nRet=0; + struct utimbuf aTimeBuffer; + struct stat aFileStat; +#ifdef DEBUG_OSL_FILE + struct tm* pTM=0; +#endif + + nRet = lstat(pszFilePath,&aFileStat); + + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + +#ifdef DEBUG_OSL_FILE + fprintf(stderr,"File Times are (in localtime):\n"); + pTM=localtime(&aFileStat.st_ctime); + fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM)); + pTM=localtime(&aFileStat.st_atime); + fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM)); + pTM=localtime(&aFileStat.st_mtime); + fprintf(stderr,"Modification is '%s'\n",asctime(pTM)); + + fprintf(stderr,"File Times are (in UTC):\n"); + fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime)); + fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime)); + fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime)); +#endif + + if ( pLastAccessTime != 0 ) + { + aTimeBuffer.actime=pLastAccessTime->Seconds; + } + else + { + aTimeBuffer.actime=aFileStat.st_atime; + } + + if ( pLastWriteTime != 0 ) + { + aTimeBuffer.modtime=pLastWriteTime->Seconds; + } + else + { + aTimeBuffer.modtime=aFileStat.st_mtime; + } + + /* mfe: Creation time not used here! */ + +#ifdef DEBUG_OSL_FILE + fprintf(stderr,"File Times are (in localtime):\n"); + pTM=localtime(&aFileStat.st_ctime); + fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM)); + pTM=localtime(&aTimeBuffer.actime); + fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM)); + pTM=localtime(&aTimeBuffer.modtime); + fprintf(stderr,"Modification now '%s'\n",asctime(pTM)); + + fprintf(stderr,"File Times are (in UTC):\n"); + fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime)); + fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime)); + fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime)); +#endif + + nRet=utime(pszFilePath,&aTimeBuffer); + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + return osl_File_E_None; +} + + +/***************************************** + * osl_psz_removeFile + ****************************************/ +#if 0 +static oslFileError osl_psz_removeFile( const sal_Char* pszPath ) +{ + int nRet=0; + struct stat aStat; + + nRet = stat(pszPath,&aStat); + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + if ( S_ISDIR(aStat.st_mode) ) + { + return osl_File_E_ISDIR; + } + + nRet = unlink(pszPath); + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + return osl_File_E_None; +} +#endif + +/***************************************** + * osl_psz_createDirectory + ****************************************/ +#if 0 +static oslFileError osl_psz_createDirectory( const sal_Char* pszPath ) +{ + int nRet=0; + int mode = S_IRWXU | S_IRWXG | S_IRWXO; + + nRet = mkdir(pszPath,mode); + + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + return osl_File_E_None; +} +#endif +/***************************************** + * osl_psz_removeDirectory + ****************************************/ +#if 0 +static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath ) +{ + int nRet=0; + + nRet = rmdir(pszPath); + + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + return osl_File_E_None; +} +#endif +/***************************************** + * oslDoMoveFile + ****************************************/ +#if 0 +static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath) +{ + oslFileError tErr=osl_File_E_invalidError; + + tErr = osl_psz_moveFile(pszPath,pszDestPath); + if ( tErr == osl_File_E_None ) + { + return tErr; + } + + if ( tErr != osl_File_E_XDEV ) + { + return tErr; + } + + tErr=osl_psz_copyFile(pszPath,pszDestPath); + + if ( tErr != osl_File_E_None ) + { + oslFileError tErrRemove; + tErrRemove=osl_psz_removeFile(pszDestPath); + return tErr; + } + + tErr=osl_psz_removeFile(pszPath); + + return tErr; +} +#endif +/***************************************** + * osl_psz_moveFile + ****************************************/ +#if 0 +static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath) +{ + + int nRet = 0; + + nRet = rename(pszPath,pszDestPath); + + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + return osl_File_E_None; +} +#endif +/***************************************** + * osl_psz_copyFile + ****************************************/ +#if 0 +static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) +{ + time_t nAcTime=0; + time_t nModTime=0; + uid_t nUID=0; + gid_t nGID=0; + int nRet=0; + mode_t nMode=0; + struct stat aFileStat; + oslFileError tErr=osl_File_E_invalidError; + size_t nSourceSize=0; + int DestFileExists=1; + + /* mfe: does the source file really exists? */ + nRet = lstat(pszPath,&aFileStat); + + if ( nRet < 0 ) + { + nRet=errno; + return oslTranslateFileError(OSL_FET_ERROR, nRet); + } + + /* mfe: we do only copy files here! */ + if ( S_ISDIR(aFileStat.st_mode) ) + { + return osl_File_E_ISDIR; + } + + nSourceSize=(size_t)aFileStat.st_size; + nMode=aFileStat.st_mode; + nAcTime=aFileStat.st_atime; + nModTime=aFileStat.st_mtime; + nUID=aFileStat.st_uid; + nGID=aFileStat.st_gid; + + nRet = stat(pszDestPath,&aFileStat); + if ( nRet < 0 ) + { + nRet=errno; + + if ( nRet == ENOENT ) + { + DestFileExists=0; + } +/* return oslTranslateFileError(nRet);*/ + } + + /* mfe: the destination file must not be a directory! */ + if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) + { + return osl_File_E_ISDIR; + } + else + { + /* mfe: file does not exists or is no dir */ + } + + tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); + + if ( tErr != osl_File_E_None ) + { + return tErr; + } + + /* + * mfe: ignore return code + * since only the success of the copy is + * important + */ + oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); + + return tErr; +} +#endif + +/****************************************************************************** + * + * Utility Functions + * + *****************************************************************************/ + + +/***************************************** + * oslMakeUStrFromPsz + ****************************************/ + +rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid) +{ + rtl_string2UString( + ustrValid, + pszStr, + rtl_str_getLength( pszStr ), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*ustrValid != 0); + + return *ustrValid; +} + +/***************************************************************************** + * UnicodeToText + * converting unicode to text manually saves us the penalty of a temporary + * rtl_String object. + ****************************************************************************/ + +int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen ) +{ + rtl_UnicodeToTextConverter hConverter; + sal_uInt32 nInfo; + sal_Size nSrcChars, nDestBytes; + + /* stolen from rtl/string.c */ + hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() ); + + nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen, + buffer, bufLen, + OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, + &nInfo, &nSrcChars ); + + rtl_destroyUnicodeToTextConverter( hConverter ); + + if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL ) + { + errno = EOVERFLOW; + return 0; + } + + /* ensure trailing '\0' */ + buffer[nDestBytes] = '\0'; + + return nDestBytes; +} + +/***************************************************************************** + TextToUnicode + + @param text + The text to convert. + + @param text_buffer_size + The number of characters. + + @param unic_text + The unicode buffer. + + @param unic_text_buffer_size + The size in characters of the unicode buffer. + + ****************************************************************************/ + +int TextToUnicode( + const char* text, + size_t text_buffer_size, + sal_Unicode* unic_text, + sal_Int32 unic_text_buffer_size) +{ + rtl_TextToUnicodeConverter hConverter; + sal_uInt32 nInfo; + sal_Size nSrcChars; + sal_Size nDestBytes; + + /* stolen from rtl/string.c */ + hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding()); + + nDestBytes = rtl_convertTextToUnicode(hConverter, + 0, + text, text_buffer_size, + unic_text, unic_text_buffer_size, + OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, + &nInfo, &nSrcChars); + + rtl_destroyTextToUnicodeConverter(hConverter); + + if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL) + { + errno = EOVERFLOW; + return 0; + } + + /* ensure trailing '\0' */ + unic_text[nDestBytes] = '\0'; + + return nDestBytes; +} + +/****************************************************************************** + * + * GENERIC FLOPPY FUNCTIONS + * + *****************************************************************************/ + + +/***************************************** + * osl_unmountVolumeDevice + ****************************************/ + +oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle ) +{ + oslFileError tErr = osl_File_E_NOSYS; + + tErr = osl_unmountFloppy(Handle); + + /* Perhaps current working directory is set to mount point */ + + if ( tErr ) + { + sal_Char *pszHomeDir = getenv("HOME"); + + if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) ) + { + /* try again */ + + tErr = osl_unmountFloppy(Handle); + + OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" ); + } + } + + return tErr; +} + +/***************************************** + * osl_automountVolumeDevice + ****************************************/ + +oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle ) +{ + oslFileError tErr = osl_File_E_NOSYS; + + tErr = osl_mountFloppy(Handle); + + return tErr; +} + +/***************************************** + * osl_getVolumeDeviceMountPath + ****************************************/ + +oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath ) +{ + oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle; + sal_Char Buffer[PATH_MAX]; + + Buffer[0] = '\0'; + + if ( pItem == 0 || pstrPath == 0 ) + { + return osl_File_E_INVAL; + } + + if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) + { + return osl_File_E_INVAL; + } + +#ifdef DEBUG_OSL_FILE + fprintf(stderr,"Handle is:\n"); + osl_printFloppyHandle(pItem); +#endif + + snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint); + +#ifdef DEBUG_OSL_FILE + fprintf(stderr,"Mount Point is: '%s'\n",Buffer); +#endif + + oslMakeUStrFromPsz(Buffer, pstrPath); + + return osl_File_E_None; +} + +/***************************************** + * osl_acquireVolumeDeviceHandle + ****************************************/ + +oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) +{ + oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle; + + if ( pItem == 0 ) + { + return osl_File_E_INVAL; + } + + if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) + { + return osl_File_E_INVAL; + } + + ++pItem->RefCount; + + return osl_File_E_None; +} + +/***************************************** + * osl_releaseVolumeDeviceHandle + ****************************************/ + +oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) +{ + oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle; + + if ( pItem == 0 ) + { + return osl_File_E_INVAL; + } + + if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) + { + return osl_File_E_INVAL; + } + + --pItem->RefCount; + + if ( pItem->RefCount == 0 ) + { + rtl_freeMemory(pItem); + } + + return osl_File_E_None; +} + +/***************************************** + * osl_newVolumeDeviceHandleImpl + ****************************************/ + +static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl() +{ + oslVolumeDeviceHandleImpl* pHandle; + const size_t nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl); + + pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle); + if (pHandle != NULL) + { + pHandle->ident[0] = 'O'; + pHandle->ident[1] = 'V'; + pHandle->ident[2] = 'D'; + pHandle->ident[3] = 'H'; + pHandle->pszMountPoint[0] = '\0'; + pHandle->pszFilePath[0] = '\0'; + pHandle->pszDevice[0] = '\0'; + pHandle->RefCount = 1; + } + return pHandle; +} + +/***************************************** + * osl_freeVolumeDeviceHandleImpl + ****************************************/ + +static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle) +{ + if (pHandle != NULL) + rtl_freeMemory (pHandle); +} + + +/****************************************************************************** + * + * OS/2 FLOPPY FUNCTIONS + * + *****************************************************************************/ + +#if defined(OS2) +static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath) +{ + return NULL; +} + +static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy) +{ + return osl_File_E_BUSY; +} + +static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy) +{ + return osl_File_E_BUSY; +} + +static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem) +{ + return sal_False; +} + +static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice) +{ + return sal_False; +} + + +#ifdef DEBUG_OSL_FILE +static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem) +{ + if (pItem == 0 ) + { + fprintf(stderr,"NULL Handle\n"); + return; + } + if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) + { +#ifdef TRACE_OSL_FILE + fprintf(stderr,"Invalid Handle]\n"); +#endif + return; + } + + + fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint); + fprintf(stderr,"FilePath : '%s'\n",pItem->pszFilePath); + fprintf(stderr,"Device : '%s'\n",pItem->pszDevice); + + return; +} +#endif + +#endif /* OS2 */ diff --git a/sal/osl/os2/file_error_transl.cxx b/sal/osl/os2/file_error_transl.cxx new file mode 100644 index 000000000000..53867a32fcf9 --- /dev/null +++ b/sal/osl/os2/file_error_transl.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_error_transl.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + #ifndef _ERRNO_H + #include <errno.h> + #endif + + #ifndef _FILE_ERROR_TRANSL_H_ + #include "file_error_transl.h" + #endif + + #ifndef _OSL_DIAGNOSE_H_ + #include <osl/diagnose.h> + #endif + + +/******************************************** + * oslTranslateFileError + *******************************************/ + +oslFileError oslTranslateFileError(sal_Bool bIsError, int Errno) +{ + oslFileError osl_error = osl_File_E_invalidError; + + OSL_ENSURE((bIsError && (0 != Errno)) || (!bIsError && (0 == Errno)), "oslTranslateFileError strange input combination!"); + + /* Have a look at file_error_transl.h for + the reason that we do this here */ + if (bIsError && (0 == Errno)) + return osl_error; + + switch(Errno) + { + case 0: + osl_error = osl_File_E_None; + break; + + case EPERM: + osl_error = osl_File_E_PERM; + break; + + case ENOENT: + osl_error = osl_File_E_NOENT; + break; + + case ESRCH: + osl_error = osl_File_E_SRCH; + break; + + case EINTR: + osl_error = osl_File_E_INTR; + break; + + case EIO: + osl_error = osl_File_E_IO; + break; + + case ENXIO: + osl_error = osl_File_E_IO; + break; + + case E2BIG: + osl_error = osl_File_E_2BIG; + break; + + case ENOEXEC: + osl_error = osl_File_E_NOEXEC; + break; + + case EBADF: + osl_error = osl_File_E_BADF; + break; + + case ECHILD: + osl_error = osl_File_E_CHILD; + break; + + case EAGAIN: + osl_error = osl_File_E_AGAIN; + break; + + case ENOMEM: + osl_error = osl_File_E_NOMEM; + break; + + case EACCES: + osl_error = osl_File_E_ACCES; + break; + + case EFAULT: + osl_error = osl_File_E_FAULT; + break; + + case EBUSY: + osl_error = osl_File_E_BUSY; + break; + + case EEXIST: + osl_error = osl_File_E_EXIST; + break; + + case EXDEV: + osl_error = osl_File_E_XDEV; + break; + + case ENODEV: + osl_error = osl_File_E_NODEV; + break; + + case ENOTDIR: + osl_error = osl_File_E_NOTDIR; + break; + + case EISDIR: + osl_error = osl_File_E_ISDIR; + break; + + case EINVAL: + osl_error = osl_File_E_INVAL; + break; + + case ENFILE: + osl_error = osl_File_E_NFILE; + break; + + case EMFILE: + osl_error = osl_File_E_MFILE; + break; + + case ENOTTY: + osl_error = osl_File_E_NOTTY; + break; + + case EFBIG: + osl_error = osl_File_E_FBIG; + break; + + case ENOSPC: + osl_error = osl_File_E_NOSPC; + break; + + case ESPIPE: + osl_error = osl_File_E_SPIPE; + break; + + case EROFS: + osl_error = osl_File_E_ROFS; + break; + + case EMLINK: + osl_error = osl_File_E_MLINK; + break; + + case EPIPE: + osl_error = osl_File_E_PIPE; + break; + + case EDOM: + osl_error = osl_File_E_DOM; + break; + + case ERANGE: + osl_error = osl_File_E_RANGE; + break; + + case EDEADLK: + osl_error = osl_File_E_DEADLK; + break; + + case ENAMETOOLONG: + osl_error = osl_File_E_NAMETOOLONG; + break; + + case ENOLCK: + osl_error = osl_File_E_NOLCK; + break; + + case ENOSYS: + osl_error = osl_File_E_NOSYS; + break; + + case ENOTEMPTY: + osl_error = osl_File_E_NOTEMPTY; + break; + + case ELOOP: + osl_error = osl_File_E_LOOP; + break; + +#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD)) + case EILSEQ: + osl_error = osl_File_E_ILSEQ; + break; +#endif /* MACOSX */ + +#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)) + case ENOLINK: + osl_error = osl_File_E_NOLINK; + break; +#endif /* MACOSX */ + +#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2)) + case EMULTIHOP: + osl_error = osl_File_E_MULTIHOP; + break; +#endif /* MACOSX */ + + case EUSERS: + osl_error = osl_File_E_USERS; + break; + + case EOVERFLOW: + osl_error = osl_File_E_OVERFLOW; + break; + + case ETIMEDOUT: + osl_error = osl_File_E_TIMEDOUT; + break; + + default: + /* FIXME translateFileError: is this alright? Or add a new one: osl_File_E_Unknown? */ + osl_error = osl_File_E_invalidError; + break; + } + + return osl_error; +} + diff --git a/sal/osl/os2/file_error_transl.h b/sal/osl/os2/file_error_transl.h new file mode 100644 index 000000000000..6e461f4019bd --- /dev/null +++ b/sal/osl/os2/file_error_transl.h @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_error_transl.h,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILE_ERROR_TRANSL_H_ +#define _FILE_ERROR_TRANSL_H_ + +#include <osl/file.h> +#include <sal/types.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************************* + oslTranslateFileError + Translate errno's to osl file errors + + @param bIsError [in] specifies if nErrno + should be interpreted as error, + some libc functions signaling an error + but errno is nevertheless 0 in this + case the function should at least + return osl_File_E_Unknown but in no + case osl_File_E_None! + + @param nErrno [in] the errno if errno is 0 + and bIsError is true the function + returns osl_File_E_Unknown + + @returns the osl error code appropriate to + the errno + + *********************************************/ + +#define OSL_FET_SUCCESS sal_False +#define OSL_FET_ERROR sal_True + +oslFileError oslTranslateFileError(sal_Bool bIsError, int Errno); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sal/osl/os2/file_path_helper.cxx b/sal/osl/os2/file_path_helper.cxx new file mode 100644 index 000000000000..872239043981 --- /dev/null +++ b/sal/osl/os2/file_path_helper.cxx @@ -0,0 +1,380 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_path_helper.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + /******************************************* + Includes + ******************************************/ + + #ifndef _OSL_THREAD_H_ + #include "osl/thread.h" + #endif + + #ifndef _OSL_FILE_PATH_HELPER_H_ + #include "file_path_helper.h" + #endif + + #ifndef _OSL_FILE_PATH_HELPER_HXX_ + #include "file_path_helper.hxx" + #endif + + #ifndef _OSL_UUNXAPI_HXX_ + #include "uunxapi.hxx" + #endif + + #ifndef _OSL_DIAGNOSE_H_ + #include <osl/diagnose.h> + #endif + + #ifndef _RTL_USTRING_HXX_ + #include <rtl/ustring.hxx> + #endif + + /******************************************* + Constants + ******************************************/ + + const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'\\'; + const sal_Unicode FPH_CHAR_DOT = (sal_Unicode)'.'; + const sal_Unicode FPH_CHAR_COLON = (sal_Unicode)':'; + + inline const rtl::OUString FPH_PATH_SEPARATOR() + { return rtl::OUString::createFromAscii("\\"); } + inline const rtl::OUString FPH_LOCAL_DIR_ENTRY() + { return rtl::OUString::createFromAscii("."); } + inline const rtl::OUString FPH_PARENT_DIR_ENTRY() + { return rtl::OUString::createFromAscii(".."); } + + /******************************************* + * osl_systemPathRemoveSeparator + ******************************************/ + + void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath) + { + OSL_PRECOND(pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter"); + + // maybe there are more than one separator at end + // so we run in a loop + while ((pustrPath->length > 1) && (FPH_CHAR_PATH_SEPARATOR == pustrPath->buffer[pustrPath->length - 1])) + { + pustrPath->length--; + pustrPath->buffer[pustrPath->length] = (sal_Unicode)'\0'; + } + + OSL_POSTCOND((0 == pustrPath->length) || (1 == pustrPath->length) || \ + (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR), \ + "osl_systemPathRemoveSeparator: Post condition failed"); + } + + /******************************************* + osl_systemPathEnsureSeparator + ******************************************/ + + void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath) + { + OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \ + "osl_systemPathEnsureSeparator: Invalid parameter"); + + rtl::OUString path(*ppustrPath); + sal_Int32 lp = path.getLength(); + sal_Int32 i = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR); + + if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0)) + { + path += FPH_PATH_SEPARATOR(); + rtl_uString_assign(ppustrPath, path.pData); + } + + OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \ + "osl_systemPathEnsureSeparator: Post condition failed"); + } + + /******************************************* + * osl_systemPathIsRelativePath + ******************************************/ + + sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath) + { + OSL_PRECOND(pustrPath, "osl_systemPathIsRelativePath: Invalid parameter"); + return (!osl_systemPathIsAbsolutePath(pustrPath)); + } + + /****************************************** + * osl_systemPathIsAbsolutePath + *****************************************/ + + sal_Bool SAL_CALL osl_systemPathIsAbsolutePath(const rtl_uString* pustrPath) + { + OSL_PRECOND(pustrPath, "osl_systemPathIsAbsolutePath: Invalid parameter"); + if (pustrPath->length == 0) + return sal_False; + if (pustrPath->buffer[0] == FPH_CHAR_PATH_SEPARATOR) + return sal_True; + if (pustrPath->buffer[1] == FPH_CHAR_COLON + && pustrPath->buffer[2] == FPH_CHAR_PATH_SEPARATOR) + return sal_True; + return sal_False; + } + + /****************************************** + osl_systemPathMakeAbsolutePath + *****************************************/ + + void SAL_CALL osl_systemPathMakeAbsolutePath( + const rtl_uString* pustrBasePath, + const rtl_uString* pustrRelPath, + rtl_uString** ppustrAbsolutePath) +{ + rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath))); + rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath)); + + if (base.getLength() > 0) + osl_systemPathEnsureSeparator(&base.pData); + + base += rel; + + rtl_uString_acquire(base.pData); + *ppustrAbsolutePath = base.pData; +} + + + /***************************************** + osl_systemPathGetParent + ****************************************/ + + sal_Int32 SAL_CALL osl_systemPathGetParent(rtl_uString* pustrPath) + { + return 0; + } + + /******************************************* + osl_systemPathGetFileOrLastDirectoryPart + ******************************************/ + + void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart( + const rtl_uString* pustrPath, + rtl_uString** ppustrFileNameOrLastDirPart) +{ + OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \ + "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter"); + + rtl::OUString path(const_cast<rtl_uString*>(pustrPath)); + + osl_systemPathRemoveSeparator(path.pData); + + rtl::OUString last_part; + + if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR)) + { + sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR); + idx_ps++; // always right to increment by one even if idx_ps == -1! + last_part = rtl::OUString(path.getStr() + idx_ps); + } + rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData); +} + + + /******************************************** + osl_systemPathIsHiddenFileOrDirectoryEntry + *********************************************/ + + sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry( + const rtl_uString* pustrPath) +{ + OSL_PRECOND(pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter"); + + sal_Bool is_hidden = sal_False; + + if (pustrPath->length > 0) + { + rtl::OUString fdp; + + osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData); + + is_hidden = ((fdp.pData->length > 0) && (fdp.pData->buffer[0] == FPH_CHAR_DOT) && + !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData)); + } + + return is_hidden; +} + + + /************************************************ + osl_systemPathIsLocalOrParentDirectoryEntry + ************************************************/ + +sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry( + const rtl_uString* pustrPath) +{ + OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter"); + + rtl::OUString dirent; + + osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData); + + return ( + (dirent == FPH_LOCAL_DIR_ENTRY()) || + (dirent == FPH_PARENT_DIR_ENTRY()) + ); +} + +/*********************************************** + Simple iterator for a path list separated by + the specified character + **********************************************/ + +class path_list_iterator +{ +public: + + /****************************************** + constructor + + after construction get_current_item + returns the first path in list, no need + to call reset first + *****************************************/ + path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) : + m_path_list(path_list), + m_end(m_path_list.getStr() + m_path_list.getLength() + 1), + m_separator(list_separator) + { + reset(); + } + + /****************************************** + reset the iterator + *****************************************/ + void reset() + { + m_path_segment_begin = m_path_segment_end = m_path_list.getStr(); + advance(); + } + + /****************************************** + move the iterator to the next position + *****************************************/ + void next() + { + OSL_PRECOND(!done(), "path_list_iterator: Already done!"); + + m_path_segment_begin = ++m_path_segment_end; + advance(); + } + + /****************************************** + check if done + *****************************************/ + bool done() const + { + return (m_path_segment_end >= m_end); + } + + /****************************************** + return the current item + *****************************************/ + rtl::OUString get_current_item() const + { + return rtl::OUString( + m_path_segment_begin, + (m_path_segment_end - m_path_segment_begin)); + } + +private: + + /****************************************** + move m_path_end to the next separator or + to the edn of the string + *****************************************/ + void advance() + { + while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator)) + ++m_path_segment_end; + + OSL_ASSERT(m_path_segment_end <= m_end); + } + +private: + rtl::OUString m_path_list; + const sal_Unicode* m_end; + const sal_Unicode m_separator; + const sal_Unicode* m_path_segment_begin; + const sal_Unicode* m_path_segment_end; + +// prevent copy and assignment +private: + /****************************************** + copy constructor + remember: do not simply copy m_path_begin + and m_path_end because they point to + the memory of other.m_path_list! + *****************************************/ + path_list_iterator(const path_list_iterator& other); + + /****************************************** + assignment operator + remember: do not simply copy m_path_begin + and m_path_end because they point to + the memory of other.m_path_list! + *****************************************/ + path_list_iterator& operator=(const path_list_iterator& other); +}; + + /************************************************ + osl_searchPath + ***********************************************/ + +sal_Bool SAL_CALL osl_searchPath( + const rtl_uString* pustrFilePath, + const rtl_uString* pustrSearchPathList, + rtl_uString** ppustrPathFound) +{ + OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter"); + + bool bfound = false; + rtl::OUString fp(const_cast<rtl_uString*>(pustrFilePath)); + rtl::OUString pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList)); + path_list_iterator pli(pl); + + while (!pli.done()) + { + rtl::OUString p = pli.get_current_item(); + osl::systemPathEnsureSeparator(p); + p += fp; + + if (osl::access(p, F_OK) > -1) + { + bfound = true; + rtl_uString_assign(ppustrPathFound, p.pData); + break; + } + pli.next(); + } + return bfound; +} diff --git a/sal/osl/os2/file_path_helper.h b/sal/osl/os2/file_path_helper.h new file mode 100644 index 000000000000..8e6deee5760c --- /dev/null +++ b/sal/osl/os2/file_path_helper.h @@ -0,0 +1,295 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_path_helper.h,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + #ifndef _OSL_FILE_PATH_HELPER_H_ + #define _OSL_FILE_PATH_HELPER_H_ + + + #ifndef _SAL_TYPES_H_ + #include <sal/types.h> + #endif + + #ifndef _RTL_USTRING_H_ + #include <rtl/ustring.h> + #endif + + + #ifdef __cplusplus + extern "C" + { + #endif + + + /******************************************* + osl_systemPathRemoveSeparator + Removes the last separator from the + given system path if any and if the path + is not the root path '/' + + @param ppustrPath [inout] a system path + if the path is not the root path + and the last character is a + path separator it will be cut off + ppustrPath must not be NULL and + must point to a valid rtl_uString + + @returns nothing + + ******************************************/ + + void SAL_CALL osl_systemPathRemoveSeparator( + /*inout*/ rtl_uString* pustrPath); + + /******************************************* + osl_systemPathEnsureSeparator + Adds a trailing path separator to the + given system path if not already there + and if the path is not the root path '/' + + @param pustrPath [inout] a system path + if the path is not the root path + '/' and has no trailing separator + a separator will be added + ppustrPath must not be NULL and + must point to a valid rtl_uString + + @returns nothing + + ******************************************/ + + void SAL_CALL osl_systemPathEnsureSeparator( + /*inout*/ rtl_uString** ppustrPath); + + /******************************************* + osl_systemPathIsRelativePath + Returns true if the given path is a + relative path and so starts not with '/' + + @param pustrPath [in] a system path + pustrPath must not be NULL + + @returns sal_True if the given path + doesn't start with a separator + else sal_False will be returned + + ******************************************/ + + sal_Bool SAL_CALL osl_systemPathIsRelativePath( + const rtl_uString* pustrPath); + + /****************************************** + osl_systemPathIsAbsolutePath + Returns true if the given path is an + absolute path and so starts with a '/' + + @param pustrPath [in] a system path + pustrPath must not be NULL + + @returns sal_True if the given path + start's with a separator else + sal_False will be returned + + *****************************************/ + + sal_Bool SAL_CALL osl_systemPathIsAbsolutePath( + const rtl_uString* pustrPath); + + /****************************************** + osl_systemPathMakeAbsolutePath + Append a relative path to a base path + + @param pustrBasePath [in] a system + path that will be considered as + base path + pustrBasePath must not be NULL + + @param pustrRelPath [in] a system path + that will be considered as + relative path + pustrBasePath must not be NULL + + @param ppustrAbsolutePath [out] the + resulting path which is a + concatination of the base and + the relative path + if base path is empty the + resulting absolute path is the + relative path + if relative path is empty the + resulting absolute path is the + base path + if base and relative path are + empty the resulting absolute + path is also empty + ppustrAbsolutePath must not be + NULL and *ppustrAbsolutePath + must be 0 or point to a valid + rtl_uString + + *****************************************/ + + void SAL_CALL osl_systemPathMakeAbsolutePath( + const rtl_uString* pustrBasePath, + const rtl_uString* pustrRelPath, + rtl_uString** ppustrAbsolutePath); + + /***************************************** + osl_systemPathGetParent + Replaces the last occurrance of a path + separator with '\0' and returns the + position where the '/' was replaced + + @param pustrPath [inout] a system + path, the last separator of + this path will be replaced by + a '\0' + if the path is the root path + '/' or the path is considered + as to have no parent, e.g. + '/NoParent' or 'NoParent' or + the path is empty no + replacement will be made + pustrPath must not be NULL + + @returns the position of the last path + separator that was replaced + or 0 if no replacement took + place + + ****************************************/ + + sal_Int32 SAL_CALL osl_systemPathGetParent( + /*inout*/ rtl_uString* pustrPath); + + /***************************************** + osl_systemPathGetFileOrLastDirectoryPart + Returns the file or the directory part + of the given path + + @param pustrPath [in] a system path, + must not be NULL + + @param ppustrFileOrDirPart [out] on + return receives the last part + of the given directory or the + file name + if pustrPath is the root path + '/' an empty string will be + returned + if pustrPath has a trailing + '/' the last part before the + '/' will be returned else + the part after the last '/' + will be returned + + @returns nothing + + ****************************************/ + void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart( + const rtl_uString* pustrPath, + rtl_uString** ppustrFileNameOrLastDirPart); + + + /******************************************** + osl_systemPathIsHiddenFileOrDirectoryEntry + Returns sal_True if the last part of + given system path is not '.' or '..' + alone and starts with a '.' + + @param pustrPath [in] a system path, + must not be NULL + + @returns sal_True if the last part of + the given system path starts + with '.' or sal_False the last + part is '.' or '..' alone or + doesn't start with a dot + + *********************************************/ + + sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry( + const rtl_uString* pustrPath); + + + /************************************************ + osl_systemPathIsLocalOrParentDirectoryEntry + Returns sal_True if the last part of the given + system path is the local directory entry '.' + or the parent directory entry '..' + + @param pustrPath [in] a system path, + must not be NULL + + @returns sal_True if the last part of the + given system path is '.' or '..' + else sal_False + + ************************************************/ + + sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry( + const rtl_uString* pustrPath); + + + /************************************************ + osl_searchPath + Searches for a file name or path name in all + directories specified by a given path list. + Symbolic links in the resulting path will not be + resolved, it's up to the caller to do this. + + @param pustrFilePath [in] a file name or + directory name to search for, the name must + be provided as system path not as a file URL + + @param pustrSearchPathList [in] a ':' + separated list of paths in which to search for + the file or directory name + + @ppustrPathFound [out] on success receives the + complete path of the file or directory found + as a system path + + @returns sal_True if the specified file or + directory was found else sal_False + ***********************************************/ + + sal_Bool SAL_CALL osl_searchPath( + const rtl_uString* pustrFilePath, + const rtl_uString* pustrSearchPathList, + rtl_uString** ppustrPathFound); + + + #ifdef __cplusplus + } + #endif + + + #endif /* #ifndef _OSL_PATH_HELPER_H_ */ + diff --git a/sal/osl/os2/file_path_helper.hxx b/sal/osl/os2/file_path_helper.hxx new file mode 100644 index 000000000000..4eda01c9f402 --- /dev/null +++ b/sal/osl/os2/file_path_helper.hxx @@ -0,0 +1,299 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_path_helper.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _OSL_FILE_PATH_HELPER_HXX_ +#define _OSL_FILE_PATH_HELPER_HXX_ + + +#ifndef _OSL_FILE_PATH_HELPER_H_ +#include "file_path_helper.h" +#endif + +#include <rtl/ustring.hxx> + + +namespace osl +{ + + /******************************************* + systemPathRemoveSeparator + Removes the last separator from the + given system path if any and if the path + is not the root path '/' + + @param ppustrPath [inout] a system path + if the path is not the root path + and the last character is a + path separator it will be cut off + ppustrPath must not be NULL and + must point to a valid rtl_uString + + @returns nothing + + ******************************************/ + + inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path) + { + osl_systemPathRemoveSeparator(Path.pData); + } + + /******************************************* + systemPathEnsureSeparator + Adds a trailing path separator to the + given system path if not already there + and if the path is not the root path '/' + + @param pustrPath [inout] a system path + if the path is not the root path + '/' and has no trailing separator + a separator will be added + ppustrPath must not be NULL and + must point to a valid rtl_uString + + @returns nothing + + ******************************************/ + + inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path) + { + osl_systemPathEnsureSeparator(&Path.pData); + } + + /******************************************* + systemPathIsRelativePath + Returns true if the given path is a + relative path and so starts not with '/' + + @param pustrPath [in] a system path + pustrPath must not be NULL + + @returns sal_True if the given path + doesn't start with a separator + else sal_False will be returned + + ******************************************/ + + inline bool systemPathIsRelativePath(const rtl::OUString& Path) + { + return osl_systemPathIsRelativePath(Path.pData); + } + + /****************************************** + systemPathIsAbsolutePath + Returns true if the given path is an + absolute path and so starts with a '/' + + @param pustrPath [in] a system path + pustrPath must not be NULL + + @returns sal_True if the given path + start's with a separator else + sal_False will be returned + + *****************************************/ + + inline bool systemPathIsAbsolutePath(const rtl::OUString& Path) + { + return osl_systemPathIsAbsolutePath(Path.pData); + } + + /****************************************** + systemPathMakeAbsolutePath + Append a relative path to a base path + + @param pustrBasePath [in] a system + path that will be considered as + base path + pustrBasePath must not be NULL + + @param pustrRelPath [in] a system path + that will be considered as + relative path + pustrBasePath must not be NULL + + @param ppustrAbsolutePath [out] the + resulting path which is a + concatination of the base and + the relative path + if base path is empty the + resulting absolute path is the + relative path + if relative path is empty the + resulting absolute path is the + base path + if base and relative path are + empty the resulting absolute + path is also empty + ppustrAbsolutePath must not be + NULL and *ppustrAbsolutePath + must be 0 or point to a valid + rtl_uString + + *****************************************/ + + inline void systemPathMakeAbsolutePath( + const rtl::OUString& BasePath, + const rtl::OUString& RelPath, + rtl::OUString& AbsolutePath) + { + osl_systemPathMakeAbsolutePath( + BasePath.pData, RelPath.pData, &AbsolutePath.pData); + } + + /***************************************** + systemPathGetParent + Replaces the last occurrance of a path + separator with '\0' and returns the + position where the '/' was replaced + + @param pustrPath [inout] a system + path, the last separator of + this path will be replaced by + a '\0' + if the path is the root path + '/' or the path is considered + as to have no parent, e.g. + '/NoParent' or 'NoParent' or + the path is empty no + replacement will be made + pustrPath must not be NULL + + @returns the position of the last path + separator that was replaced + or 0 if no replacement took + place + + ****************************************/ + + inline sal_Int32 systemPathGetParent(/*inout*/ rtl::OUString& Path) + { + return osl_systemPathGetParent(Path.pData); + } + + /***************************************** + systemPathGetFileOrLastDirectoryPart + Returns the file or the directory part + of the given path + + @param pustrPath [in] a system path, + must not be NULL + + @param ppustrFileOrDirPart [out] on + return receives the last part + of the given directory or the + file name + if pustrPath is the root path + '/' an empty string will be + returned + if pustrPath has a trailing + '/' the last part before the + '/' will be returned else + the part after the last '/' + will be returned + + @returns nothing + + ****************************************/ + + inline void systemPathGetFileNameOrLastDirectoryPart( + const rtl::OUString& Path, + rtl::OUString& FileNameOrLastDirPart) + { + osl_systemPathGetFileNameOrLastDirectoryPart( + Path.pData, &FileNameOrLastDirPart.pData); + } + + + /******************************************** + systemPathIsHiddenFileOrDirectoryEntry + Returns sal_True if the last part of + given system path is not '.' or '..' + alone and starts with a '.' + + @param pustrPath [in] a system path, + must not be NULL + + @returns sal_True if the last part of + the given system path starts + with '.' or sal_False the last + part is '.' or '..' alone or + doesn't start with a dot + + *********************************************/ + + inline bool systemPathIsHiddenFileOrDirectoryEntry( + const rtl::OUString& Path) + { + return osl_systemPathIsHiddenFileOrDirectoryEntry(Path.pData); + } + + + /************************************************ + systemPathIsLocalOrParentDirectoryEntry + Returns sal_True if the last part of the given + system path is the local directory entry '.' + or the parent directory entry '..' + + @param pustrPath [in] a system path, + must not be NULL + + @returns sal_True if the last part of the + given system path is '.' or '..' + else sal_False + + ************************************************/ + + inline bool systemPathIsLocalOrParentDirectoryEntry( + const rtl::OUString& Path) + { + return osl_systemPathIsLocalOrParentDirectoryEntry(Path.pData); + } + + /************************************************ + searchPath + ***********************************************/ + + inline bool searchPath( + const rtl::OUString& ustrFilePath, + const rtl::OUString& ustrSearchPathList, + rtl::OUString& ustrPathFound) + { + return osl_searchPath( + ustrFilePath.pData, + ustrSearchPathList.pData, + &ustrPathFound.pData); + } + + + } // namespace osl + + + #endif /* #ifndef _OSL_PATH_HELPER_HXX_ */ + diff --git a/sal/osl/os2/file_url.cxx b/sal/osl/os2/file_url.cxx new file mode 100644 index 000000000000..fbec9daaca1d --- /dev/null +++ b/sal/osl/os2/file_url.cxx @@ -0,0 +1,1629 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_url.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <ctype.h> +#include "system.h" + +#ifndef _LIMITS_H +#include <limits.h> +#endif + +#ifndef _ERRNO_H +#include <errno.h> +#endif + +#ifndef _STDLIB_H_ +#include <stdlib.h> +#endif + +#ifndef _STRINGS_H +#include <strings.h> +#endif + +#ifndef _UNISTD_H +#include <unistd.h> +#endif +#include <osl/file.h> +#include <osl/security.h> +#include <rtl/uri.h> +#include <osl/diagnose.h> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.h> + +#ifndef _OSL_TREAD_H_ +#include <osl/thread.h> +#endif +#include <osl/file.hxx> +#include <osl/mutex.h> +#include <osl/process.h> +#include "file_error_transl.h" + +#ifndef _FILE_URL_H_ +#include "file_url.h" +#endif +#include "file_path_helper.hxx" + +#ifndef _OSL_UUNXAPI_HXX_ +#include "uunxapi.hxx" +#endif + +#include <wchar.h> +#include <wctype.h> + +/*************************************************** + + General note + + This file contains the part that handles File URLs. + + File URLs as scheme specific notion of URIs + (RFC2396) may be handled platform independend, but + will not in osl which is considered wrong. + Future version of osl should handle File URLs this + way. In rtl/uri there is already an URI parser etc. + so this code should be consolidated. + + **************************************************/ + +oslMutex g_CurrentDirectoryMutex; + + +/*************************************************** + * forward + **************************************************/ + +void _osl_warnFile(const char*, rtl_uString*); +rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr); + +extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32); +extern "C" int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size); + +/*************************************************** + * namespace directives + **************************************************/ + +using namespace osl; + +/****************************************************************************** + * + * Exported Module Functions + * + *****************************************************************************/ + +/* a slightly modified version of Pchar in rtl/source/uri.c */ +const sal_Bool uriCharClass[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */ +}; + + +/* check for top wrong usage strings */ +/* +static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len ) +{ + rtl_uString *pTmp = NULL; + sal_Bool bRet; + + rtl_uString_newFromStr_WithLength( &pTmp, path, len ); + + rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length ); + + bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) || + ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) || + ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) || + ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) || + ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) ); + + rtl_uString_release( pTmp ); + return bRet; +} +*/ + + +/****************************************************************************/ +/* osl_getFileURLFromSystemPath */ +/****************************************************************************/ + +BOOL WINAPI IsValidFilePathComponent( + LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags) +{ + LPCTSTR lpComponentEnd = NULL; + LPCTSTR lpCurrent = lpComponent; + BOOL fValid = TRUE; /* Assume success */ + TCHAR cLast = 0; + + /* Path component length must not exceed MAX_PATH */ + + while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < _MAX_PATH ) + { + switch ( *lpCurrent ) + { + /* Both backslash and slash determine the end of a path component */ + case '\0': + case '/': + case '\\': + switch ( cLast ) + { + /* Component must not end with '.' or blank and can't be empty */ + + case '.': + if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE ) + { + if ( 1 == lpCurrent - lpComponent ) + { + /* Current directory is O.K. */ + lpComponentEnd = lpCurrent; + break; + } + else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent ) + { + /* Parent directory is O.K. */ + lpComponentEnd = lpCurrent; + break; + } + } + case 0: + case ' ': + lpComponentEnd = lpCurrent - 1; + fValid = FALSE; + break; + default: + lpComponentEnd = lpCurrent; + break; + } + break; + /* '?' and '*' are valid wildcards but not valid file name characters */ + case '?': + case '*': + if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS ) + break; + /* The following characters are reserved */ + case '<': + case '>': + case '\"': + case '|': + case ':': + lpComponentEnd = lpCurrent; + fValid = FALSE; + break; + default: + /* Characters below ASCII 32 are not allowed */ + if ( *lpCurrent < ' ' ) + { + lpComponentEnd = lpCurrent; + fValid = FALSE; + } + break; + } + cLast = *lpCurrent++; + } + + /* If we don't reached the end of the component the length of the component was to long + ( See condition of while loop ) */ + if ( !lpComponentEnd ) + { + fValid = FALSE; + lpComponentEnd = lpCurrent; + } + + /* Test wether the component specifies a device name what is not allowed */ + + // MT: PERFORMANCE: + // This is very expensive. A lot of calls to _tcsicmp. + // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp! + // Possible optimizations + // - Array should be const static + // - Sorted array, use binary search + // - More intelligent check for com1-9, lpt1-9 + // Maybe make szComponent upper case, don't search case intensitive + // Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway. + /* + if ( fValid ) + { + LPCTSTR alpDeviceNames[] = + { + TEXT("CON"), + TEXT("PRN"), + TEXT("AUX"), + TEXT("CLOCK$"), + TEXT("NUL"), + TEXT("LPT1"), + TEXT("LPT2"), + TEXT("LPT3"), + TEXT("LPT4"), + TEXT("LPT5"), + TEXT("LPT6"), + TEXT("LPT7"), + TEXT("LPT8"), + TEXT("LPT9"), + TEXT("COM1"), + TEXT("COM2"), + TEXT("COM3"), + TEXT("COM4"), + TEXT("COM5"), + TEXT("COM6"), + TEXT("COM7"), + TEXT("COM8"), + TEXT("COM9") + }; + + TCHAR szComponent[MAX_PATH]; + int nComponentLength; + LPCTSTR lpDot; + int i; + + // A device name with an extension is also invalid + lpDot = _tcschr( lpComponent, '.' ); + + if ( !lpDot || lpDot > lpComponentEnd ) + nComponentLength = lpComponentEnd - lpComponent; + else + nComponentLength = lpDot - lpComponent; + + _tcsncpy( szComponent, lpComponent, nComponentLength ); + szComponent[nComponentLength] = 0; + + for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ ) + { + if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) ) + { + lpComponentEnd = lpComponent; + fValid = FALSE; + break; + } + } + } + */ + + if ( fValid ) + { + // Empty components are not allowed + if ( lpComponentEnd - lpComponent < 1 ) + fValid = FALSE; + + // If we reached the end of the string NULL is returned + else if ( !*lpComponentEnd ) + lpComponentEnd = NULL; + + } + + if ( lppComponentEnd ) + *lppComponentEnd = lpComponentEnd; + + return fValid; +} + +//##################################################### +DWORD WINAPI IsValidFilePath(LPCTSTR lpszPath, LPCTSTR *lppError, DWORD dwFlags) +{ + LPCTSTR lpComponent; + BOOL fValid = TRUE; + DWORD dwPathType = PATHTYPE_ERROR; + + if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE ) + dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE; + + if ( !lpszPath ) + { + fValid = FALSE; + lpComponent = lpszPath; + } + + /* Test for UNC path notation */ + if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) ) + { + /* Place the pointer behind the leading to backslashes */ + + lpComponent = lpszPath + 2; + + fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE ); + + /* So far we have a valid servername. Now let's see if we also have a network resource */ + + dwPathType = PATHTYPE_ABSOLUTE_UNC; + + if ( fValid ) + { + if ( lpComponent && !*++lpComponent ) + lpComponent = NULL; + + if ( !lpComponent ) + { +#if 0 + /* We only have a Server specification what is invalid */ + + lpComponent = lpszPath; + fValid = FALSE; +#else + dwPathType |= PATHTYPE_IS_SERVER; +#endif + } + else + { + /* Now test the network resource */ + + fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 ); + + /* If we now reached the end of the path, everything is O.K. */ + + + if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) ) + { + lpComponent = NULL; + dwPathType |= PATHTYPE_IS_VOLUME; + } + } + } + } + + /* Local path verification. Must start with <drive>: */ + else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] ) + { + /* Place pointer behind correct drive specification */ + + lpComponent = lpszPath + 2; + + if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) ) + lpComponent++; + else if ( *lpComponent ) + fValid = FALSE; + + dwPathType = PATHTYPE_ABSOLUTE_LOCAL; + + /* Now we are behind the backslash or it was a simple drive without backslash */ + + if ( fValid && !*lpComponent ) + { + lpComponent = NULL; + dwPathType |= PATHTYPE_IS_VOLUME; + } + } + + /* Can be a relative path */ + else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE ) + { + lpComponent = lpszPath; + + /* Relative path can start with a backslash */ + + if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) ) + { + lpComponent++; + if ( !*lpComponent ) + lpComponent = NULL; + } + + dwPathType = PATHTYPE_RELATIVE; + } + + /* Anything else is an error */ + else + { + fValid = FALSE; + lpComponent = lpszPath; + } + + /* Now validate each component of the path */ + while ( fValid && lpComponent ) + { + fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags ); + + if ( fValid && lpComponent ) + { + lpComponent++; + + /* If the string behind the backslash is empty, we've done */ + + if ( !*lpComponent ) + lpComponent = NULL; + } + } + + if ( fValid && _tcslen( lpszPath ) >= _MAX_PATH ) + { + fValid = FALSE; + lpComponent = lpszPath + _MAX_PATH; + } + + if ( lppError ) + *lppError = lpComponent; + + return fValid ? dwPathType : PATHTYPE_ERROR; +} + +sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL ) +{ + sal_Char *pBuffer; + const sal_Char *pSrcEnd; + const sal_Char *pSrc; + sal_Char *pDest; + sal_Int32 nSrcLen; + sal_Bool bValidEncoded = sal_True; /* Assume success */ + + /* The resulting decoded string length is shorter or equal to the source length */ + + nSrcLen = rtl_string_getLength(strUTF8); + pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1)); + + pDest = pBuffer; + pSrc = rtl_string_getStr(strUTF8); + pSrcEnd = pSrc + nSrcLen; + + /* Now decode the URL what should result in an UTF8 string */ + while ( bValidEncoded && pSrc < pSrcEnd ) + { + switch ( *pSrc ) + { + case '%': + { + sal_Char aToken[3]; + sal_Char aChar; + + pSrc++; + aToken[0] = *pSrc++; + aToken[1] = *pSrc++; + aToken[2] = 0; + + aChar = (sal_Char)strtoul( aToken, NULL, 16 ); + + /* The chars are path delimiters and must not be encoded */ + + if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar ) + bValidEncoded = sal_False; + else + *pDest++ = aChar; + } + break; + default: + *pDest++ = *pSrc++; + break; + } + } + + *pDest++ = 0; + + if ( bValidEncoded ) { + rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*pstrDecodedURL != 0); + } + + rtl_freeMemory( pBuffer ); + + return bValidEncoded; +} + +//############################################# +void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL ) +{ + /* Encode non ascii characters within the URL */ + + rtl_String *strUTF8 = NULL; + sal_Char *pszEncodedURL; + const sal_Char *pURLScan; + sal_Char *pURLDest; + sal_Int32 nURLScanLen; + sal_Int32 nURLScanCount; + + rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); + + pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) ); + + pURLDest = pszEncodedURL; + pURLScan = rtl_string_getStr( strUTF8 ); + nURLScanLen = rtl_string_getLength( strUTF8 ); + nURLScanCount = 0; + + while ( nURLScanCount < nURLScanLen ) + { + sal_Char cCurrent = *pURLScan; + + switch ( cCurrent ) + { + default: + if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) ) + { + sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent ); + pURLDest += 3; + break; + } + case '!': + case '\'': + case '(': + case ')': + case '*': + case '-': + case '.': + case '_': + case '~': + case '$': + case '&': + case '+': + case ',': + case '=': + case '@': + case ':': + case '/': + case '\\': + case '|': + *pURLDest++ = cCurrent; + break; + case 0: + break; + } + + pURLScan++; + nURLScanCount++; + } + + + *pURLDest = 0; + + rtl_string_release( strUTF8 ); + rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL ); + rtl_freeMemory( pszEncodedURL ); +} + +//############################################# +oslFileError SAL_CALL _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL ) +{ + oslFileError nError = osl_File_E_INVAL; /* Assume failure */ + rtl_uString *strTempURL = NULL; + DWORD dwPathType = PATHTYPE_ERROR; + + if (strPath) + dwPathType = IsValidFilePath(strPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE); + + if (dwPathType) + { + rtl_uString *strTempPath = NULL; + + /* Replace backslashes */ + + rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' ); + + switch ( dwPathType & PATHTYPE_MASK_TYPE ) + { + case PATHTYPE_RELATIVE: + rtl_uString_assign( &strTempURL, strTempPath ); + nError = osl_File_E_None; + break; + case PATHTYPE_ABSOLUTE_UNC: + rtl_uString_newFromAscii( &strTempURL, "file:" ); + rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath ); + nError = osl_File_E_None; + break; + case PATHTYPE_ABSOLUTE_LOCAL: + rtl_uString_newFromAscii( &strTempURL, "file:///" ); + rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath ); + nError = osl_File_E_None; + break; + default: + break; + } + + /* Release temp path */ + + rtl_uString_release( strTempPath ); + } + + if ( osl_File_E_None == nError ) + { + rtl_String *strEncodedURL = NULL; + + /* Encode the URL */ + + _osl_encodeURL( strTempURL, &strEncodedURL ); + + /* Provide URL via unicode string */ + + rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*pstrURL != 0); + rtl_string_release( strEncodedURL ); + } + + /* Release temp URL */ + + if ( strTempURL ) + rtl_uString_release( strTempURL ); + + /* + OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath ); + */ + + return nError; +} + +oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL ) +{ + return _osl_getFileURLFromSystemPath( ustrSystemPath, pustrFileURL ); +#if 0 + static const sal_Unicode pDoubleSlash[2] = { '/', '/' }; + + rtl_uString *pTmp = NULL; + sal_Int32 nIndex; + + if( 0 == ustrSystemPath->length ) + return osl_File_E_INVAL; + + /* YD convert '\' to '/' */ + rtl_ustr_replaceChar( ustrSystemPath->buffer, '\\', '/' ); + + /* temporary hack: if already file url, return ustrSystemPath */ + if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) ) + { + /* + if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) ) + { + OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" ); + rtl_uString_assign( pustrFileURL, ustrSystemPath ); + } + else + { + rtl_uString *pTmp2 = NULL; + + OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" ); + rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 ); + rtl_uString_newFromAscii( &pTmp2, "file://" ); + rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 ); + rtl_uString_release( pTmp2 ); + } + return osl_File_E_None; + */ + return osl_File_E_INVAL; + } + + + /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ + if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] ) + { + /* check if another user is specified */ + if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) ) + { + /* osl_getHomeDir returns file URL */ + osl_getHomeDir( osl_getCurrentSecurity(), &pTmp ); + + /* remove "file://" prefix */ + rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 ); + + /* replace '~' in original string */ + rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp ); + } + + else + { + /* FIXME: replace ~user with users home directory */ + return osl_File_E_INVAL; + } + } + + /* check if initial string contains double instances of '/' */ + nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 ); + if( -1 != nIndex ) + { + sal_Int32 nSrcIndex; + sal_Int32 nDeleted = 0; + + /* if pTmp is not already allocated, copy ustrSystemPath for modification */ + if( NULL == pTmp ) + rtl_uString_newFromString( &pTmp, ustrSystemPath ); + + /* adapt index to pTmp */ + nIndex += pTmp->length - ustrSystemPath->length; + + /* remove all occurances of '//' */ + for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ ) + { + if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) ) + nDeleted++; + else + pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex]; + } + + /* adjust length member */ + pTmp->length -= nDeleted; + } + + if( NULL == pTmp ) + rtl_uString_assign( &pTmp, ustrSystemPath ); + + /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */ + /* + OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) ); + */ + + /* file URLs must be URI encoded */ + rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL ); + + rtl_uString_release( pTmp ); + + /* absolute urls should start with 'file://' */ + if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] ) + { + rtl_uString *pProtocol = NULL; + + rtl_uString_newFromAscii( &pProtocol, "file://" ); + rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL ); + rtl_uString_release( pProtocol ); + } + + return osl_File_E_None; +#endif +} + +//############################################# +oslFileError SAL_CALL _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative ) +{ + rtl_String *strUTF8 = NULL; + rtl_uString *strDecodedURL = NULL; + rtl_uString *strTempPath = NULL; + const sal_Unicode *pDecodedURL; + sal_uInt32 nDecodedLen; + sal_Bool bValidEncoded; + oslFileError nError = osl_File_E_INVAL; /* Assume failure */ + + /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from + having a mixed encoded URL later */ + + rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); + + /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */ + + OSL_ENSURE_FILE( + strUTF8->length == strURL->length || + 0 != rtl_ustr_ascii_shortenedCompare_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 ) + ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL ); + + bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL ); + + /* Release the encoded UTF8 string */ + + rtl_string_release( strUTF8 ); + + + if ( bValidEncoded ) + { + /* Replace backslashes and pipes */ + + rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' ); + rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' ); + + pDecodedURL = rtl_uString_getStr( strDecodedURL ); + nDecodedLen = rtl_uString_getLength( strDecodedURL ); + + /* Must start with "file://" */ + + if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) ) + { + sal_uInt32 nSkip; + + if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) ) + nSkip = 8; + else if ( + 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) || + 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 ) + ) + nSkip = 17; + else + nSkip = 5; + + /* Indicates local root */ + if ( nDecodedLen == nSkip ) + rtl_uString_newFromStr_WithLength( &strTempPath, (const sal_Unicode*)WSTR_SYSTEM_ROOT_PATH, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 ); + else + rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip ); + + if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_ELLIPSE ) ) + nError = osl_File_E_None; + } + else if ( bAllowRelative ) /* This maybe a relative file URL */ + { + rtl_uString_assign( &strTempPath, strDecodedURL ); + + if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE ) ) + nError = osl_File_E_None; + } + /* + else + OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL ); + */ + + } + + if ( strDecodedURL ) + rtl_uString_release( strDecodedURL ); + + if ( osl_File_E_None == nError ) + rtl_uString_assign( pustrPath, strTempPath ); + + if ( strTempPath ) + rtl_uString_release( strTempPath ); + + /* + OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL ); + */ + + return nError; +} + +/****************************************************************************/ +/* osl_getSystemPathFromFileURL */ +/****************************************************************************/ + +oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath ) +{ + return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, sal_True ); +#if 0 + sal_Int32 nIndex = 0; + rtl_uString * pTmp = NULL; + + sal_Unicode encodedSlash[3] = { '%', '2', 'F' }; + + /* temporary hack: if already system path, return ustrFileURL */ + /* + if( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) + { + OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" ); + rtl_uString_assign( pustrSystemPath, ustrFileURL ); + return osl_File_E_None; + } + */ + + /* a valid file url may not start with '/' */ + if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) ) + { + return osl_File_E_INVAL; + } + + /* search for encoded slashes (%2F) and decode every single token if we find one */ + if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) ) + { + rtl_uString * ustrPathToken = NULL; + sal_Int32 nOffset = 7; + + do + { + nOffset += nIndex; + + /* break url down in '/' devided tokens tokens */ + nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' ); + + /* copy token to new string */ + rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset, + -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ ); + + /* decode token */ + rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); + + /* the result should not contain any '/' */ + if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) ) + { + rtl_uString_release( pTmp ); + rtl_uString_release( ustrPathToken ); + + return osl_File_E_INVAL; + } + + } while( -1 != nIndex ); + + /* release temporary string and restore index variable */ + rtl_uString_release( ustrPathToken ); + nIndex = 0; + } + + /* protocol and server should not be encoded, so decode the whole string */ + rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); + + /* check if file protocol specified */ + /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ + if( 7 <= pTmp->length ) + { + rtl_uString * pProtocol = NULL; + rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 ); + + /* protocol is case insensitive */ + rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length ); + + if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) ) + nIndex = 7; + + rtl_uString_release( pProtocol ); + } + + /* skip "localhost" or "127.0.0.1" if "file://" is specified */ + /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ + if( nIndex && ( 10 <= pTmp->length - nIndex ) ) + { + rtl_uString * pServer = NULL; + rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 ); + + /* server is case insensitive */ + rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length ); + + if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) || + ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) ) + { + /* don't exclude the '/' */ + nIndex += 9; + } + + rtl_uString_release( pServer ); + } + + if( nIndex ) + rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex ); + + /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ + if( (sal_Unicode) '~' == pTmp->buffer[0] ) + { + /* check if another user is specified */ + if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) ) + { + rtl_uString *pTmp2 = NULL; + + /* osl_getHomeDir returns file URL */ + osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 ); + + /* remove "file://" prefix */ + rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 ); + + /* replace '~' in original string */ + rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 ); + rtl_uString_release( pTmp2 ); + } + + else + { + /* FIXME: replace ~user with users home directory */ + return osl_File_E_INVAL; + } + } + + /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */ + /* + OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) ); + */ + + *pustrSystemPath = pTmp; + return osl_File_E_None; +#endif // 0 +} + + +/**************************************************************************** + * osl_getSystemPathFromFileURL_Ex - helper function + * clients may specify if they want to accept relative + * URLs or not + ****************************************************************************/ + +oslFileError osl_getSystemPathFromFileURL_Ex( + rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative) +{ + return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, bAllowRelative); +#if 0 + rtl_uString* temp = 0; + oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp); + + if (osl_File_E_None == osl_error) + { + if (bAllowRelative + || (UNICHAR_SLASH == temp->buffer[0]) + || (UNICHAR_COLON == temp->buffer[1] && UNICHAR_SLASH == temp->buffer[2])) + { + *pustrSystemPath = temp; + } + else + { + rtl_uString_release(temp); + osl_error = osl_File_E_INVAL; + } + } + + return osl_error; +#endif +} + +namespace /* private */ +{ + +#if 0 // YD + + /****************************************************** + * Helper function, return a pinter to the final '\0' + * of a string + ******************************************************/ + + sal_Unicode* ustrtoend(sal_Unicode* pStr) + { + return (pStr + rtl_ustr_getLength(pStr)); + } + + /********************************************* + + ********************************************/ + sal_Unicode* ustrcpy(const sal_Unicode* s, sal_Unicode* d) + { + const sal_Unicode* sc = s; + sal_Unicode* dc = d; + + while ((*dc++ = *sc++)) + /**/; + + return d; + } + + /********************************************* + + ********************************************/ + + sal_Unicode* ustrncpy(const sal_Unicode* s, sal_Unicode* d, unsigned int n) + { + const sal_Unicode* sc = s; + sal_Unicode* dc = d; + unsigned int i = n; + + while (i--) + *dc++ = *sc++; + + if (n) + *dc = 0; + + return d; + } + + /********************************************* + + ********************************************/ + + sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d) + { + sal_Unicode* p = ustrtoend(d); + *p++ = chr; + *p = 0; + return d; + } + + /********************************************* + + ********************************************/ + + sal_Unicode* ustrcat(const sal_Unicode* s, sal_Unicode* d) + { + sal_Unicode* dc = ustrtoend(d); + ustrcpy(s, dc); + return d; + } + + /****************************************************** + * + ******************************************************/ + + bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr) + { + sal_Unicode* p = ustrtoend(pStr); + if (p > pStr) + p--; + return (*p == Chr); + } + + /****************************************************** + * Ensure that the given string has the specified last + * character if necessary append it + ******************************************************/ + + sal_Unicode* _strensurelast(sal_Unicode* pStr, sal_Unicode Chr) + { + if (!_islastchr(pStr, Chr)) + ustrchrcat(Chr, pStr); + return pStr; + } + + /****************************************************** + * Remove the last part of a path, a path that has + * only a '/' or no '/' at all will be returned + * unmodified + ******************************************************/ + + sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath) + { + /* we always may skip -2 because we + may at least stand on a '/' but + either there is no other character + before this '/' or it's another + character than the '/' + */ + sal_Unicode* p = ustrtoend(aPath) - 2; + + // move back to the next path separator + // or to the start of the string + while ((p > aPath) && (*p != UNICHAR_SLASH)) + p--; + + if (p >= aPath) + { + if (UNICHAR_SLASH == *p) + { + p++; + *p = '\0'; + } + else + { + *p = '\0'; + } + } + + return aPath; + } + + /****************************************************** + * + ******************************************************/ + + oslFileError _osl_resolvepath( + /*inout*/ sal_Unicode* path, + /*inout*/ sal_Unicode* current_pos, + /*in */ sal_Unicode* sentinel, + /*inout*/ bool* failed) + { + oslFileError ferr = osl_File_E_None; + + if (!*failed) + { + char unresolved_path[PATH_MAX]; + if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path))) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + char resolved_path[PATH_MAX]; + if (realpath(unresolved_path, resolved_path)) + { + if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX)) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + current_pos = ustrtoend(path) - 1; + } + else + { + if (EACCES == errno || ENOTDIR == errno || ENOENT == errno) + *failed = true; + else + ferr = oslTranslateFileError(OSL_FET_ERROR, errno); + } + } + + return ferr; + } + + /****************************************************** + * Works even with non existing paths. The resulting + * path must not exceed PATH_MAX else + * osl_File_E_NAMETOOLONG is the result + ******************************************************/ + + oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path) + { + // the given unresolved path must not exceed PATH_MAX + if (unresolved_path.getLength() >= (PATH_MAX - 2)) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + sal_Unicode path_resolved_so_far[PATH_MAX]; + const sal_Unicode* punresolved = unresolved_path.getStr(); + sal_Unicode* presolvedsf = path_resolved_so_far; + + // reserve space for leading '/' and trailing '\0' + // do not exceed this limit + sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2; + + // if realpath fails with error ENOTDIR, EACCES or ENOENT + // we will not call it again, because _osl_realpath should also + // work with non existing directories etc. + bool realpath_failed = false; + oslFileError ferr; + + path_resolved_so_far[0] = '\0'; + + while (*punresolved != '\0') + { + // ignore '/.' , skip one part back when '/..' + + if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf)) + { + if ('\0' == *(punresolved + 1)) + { + punresolved++; + continue; + } + else if (UNICHAR_SLASH == *(punresolved + 1)) + { + punresolved += 2; + continue; + } + else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2)))) + { + _rmlastpathtoken(path_resolved_so_far); + + presolvedsf = ustrtoend(path_resolved_so_far) - 1; + + if (UNICHAR_SLASH == *(punresolved + 2)) + punresolved += 3; + else + punresolved += 2; + + continue; + } + else // a file or directory name may start with '.' + { + if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + ustrchrcat(*punresolved++, path_resolved_so_far); + + if ('\0' == *punresolved && !realpath_failed) + { + ferr = _osl_resolvepath( + path_resolved_so_far, + presolvedsf, + sentinel, + &realpath_failed); + + if (osl_File_E_None != ferr) + return ferr; + } + } + } + else if (UNICHAR_SLASH == *punresolved) + { + if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + ustrchrcat(*punresolved++, path_resolved_so_far); + + if (!realpath_failed) + { + ferr = _osl_resolvepath( + path_resolved_so_far, + presolvedsf, + sentinel, + &realpath_failed); + + if (osl_File_E_None != ferr) + return ferr; + + if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH)) + { + if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + ustrchrcat(UNICHAR_SLASH, path_resolved_so_far); + } + } + } + else // any other character + { + if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) + return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); + + ustrchrcat(*punresolved++, path_resolved_so_far); + + if ('\0' == *punresolved && !realpath_failed) + { + ferr = _osl_resolvepath( + path_resolved_so_far, + presolvedsf, + sentinel, + &realpath_failed); + + if (osl_File_E_None != ferr) + return ferr; + } + } + } + + sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far); + + OSL_ASSERT(len < PATH_MAX); + + resolved_path = rtl::OUString(path_resolved_so_far, len); + + return osl_File_E_None; + } + +#endif // 0 // YD + +} // end namespace private + +#if OSL_DEBUG_LEVEL > 0 + + //##################################################### + void _osl_warnFile( const char *message, rtl_uString *ustrFile ) + { + char szBuffer[2048]; + + if (ustrFile) + { + rtl_String *strFile = NULL; + + rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer ); + rtl_string_release( strFile ); + + message = szBuffer; + } + OSL_ENSURE( 0, message ); + } + +#endif // OSL_DEBUG_LEVEL > 0 + +/****************************************************** + * osl_getAbsoluteFileURL + ******************************************************/ + +//oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL) +oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL ) +{ + oslFileError eError; + rtl_uString *ustrRelSysPath = NULL; + rtl_uString *ustrBaseSysPath = NULL; + + if ( ustrBaseURL && ustrBaseURL->length ) + { + eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False ); + OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" ); + + eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True ); + } + else + { + eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False ); + OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" ); + } + + if ( !eError ) + { + CHAR szBuffer[_MAX_PATH]; + CHAR szRelSysPath[_MAX_PATH]; + CHAR szCurrentDir[_MAX_PATH]; + int result; + char* cwd; + int rc; + +/*@@@ToDo + Bad, bad hack, this only works if the base path + really exists which is not necessary according + to RFC2396 + The whole FileURL implementation should be merged + with the rtl/uri class. +*/ + if ( ustrBaseSysPath ) + { + CHAR szBaseSysPath[_MAX_PATH]; + + if (!g_CurrentDirectoryMutex) + g_CurrentDirectoryMutex = osl_createMutex(); + + osl_acquireMutex( g_CurrentDirectoryMutex ); + + cwd = getcwd( szCurrentDir, sizeof(szCurrentDir) ); + UnicodeToText( szBaseSysPath, sizeof(szBaseSysPath), ustrBaseSysPath->buffer, ustrBaseSysPath->length); + rc = chdir( szBaseSysPath); + } + + UnicodeToText( szRelSysPath, sizeof(szRelSysPath), ustrRelSysPath->buffer, ustrRelSysPath->length); + result = !_abspath( szBuffer, szRelSysPath, sizeof(szBuffer)); + + if ( ustrBaseSysPath ) + { + rc = chdir( szCurrentDir ); + + osl_releaseMutex( g_CurrentDirectoryMutex ); + } + + if ( result ) + { + rtl_uString *ustrAbsSysPath = NULL; + + oslMakeUStrFromPsz( szBuffer, &ustrAbsSysPath); + + eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL ); + + if ( ustrAbsSysPath ) + rtl_uString_release( ustrAbsSysPath ); + } + else + eError = osl_File_E_INVAL; + } + + if ( ustrBaseSysPath ) + rtl_uString_release( ustrBaseSysPath ); + + if ( ustrRelSysPath ) + rtl_uString_release( ustrRelSysPath ); + + return eError; +#if 0 + FileBase::RC rc; + rtl::OUString unresolved_path; + + rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path); + + if(FileBase::E_None != rc) + return oslFileError(rc); + + if (systemPathIsRelativePath(unresolved_path)) + { + rtl::OUString base_path; + rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False); + + if (FileBase::E_None != rc) + return oslFileError(rc); + + rtl::OUString abs_path; + systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path); + + unresolved_path = abs_path; + } + + rtl::OUString resolved_path; + rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path); + + if (FileBase::E_None == rc) + { + rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL); + OSL_ASSERT(FileBase::E_None == rc); + } + + return oslFileError(rc); +#endif // 0 +} + + +namespace /* private */ +{ + + /********************************************* + No separate error code if unicode to text + conversion or getenv fails because for the + caller there is no difference why a file + could not be found in $PATH + ********************************************/ + + bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result) + { + bool bfound = false; + rtl::OUString path = rtl::OUString::createFromAscii("PATH"); + rtl::OUString env_path; + + if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData)) + bfound = osl::searchPath(file_path, env_path, result); + + return bfound; + } + + /********************************************* + No separate error code if unicode to text + conversion or getcwd fails because for the + caller there is no difference why a file + could not be found in CDW + ********************************************/ + + bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result) + { + bool bfound = false; + rtl::OUString cwd_url; + + if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData)) + { + rtl::OUString cwd; + FileBase::getSystemPathFromFileURL(cwd_url, cwd); + bfound = osl::searchPath(file_path, cwd, result); + } + return bfound; + } + + /********************************************* + + ********************************************/ + + bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result) + { + return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result)); + } + +} // end namespace private + + +/**************************************************************************** + * osl_searchFileURL + ***************************************************************************/ + +oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL) +{ + OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter"); + + FileBase::RC rc; + rtl::OUString file_path; + + // try to interpret search path as file url else assume it's a system path list + rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path); + if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc)) + file_path = ustrFilePath; + else if (FileBase::E_None != rc) + return oslFileError(rc); + + bool bfound = false; + rtl::OUString result; + + if (find_in_searchPath(file_path, ustrSearchPath, result) || + find_in_PATH(file_path, result) || + find_in_CWD(file_path, result)) + { + rtl::OUString resolved; + + if (osl::realpath(result, resolved)) + { +#if OSL_DEBUG_LEVEL > 0 + oslFileError osl_error = +#endif + osl_getFileURLFromSystemPath(resolved.pData, pustrURL); + OSL_ASSERT(osl_File_E_None == osl_error); + bfound = true; + } + } + return bfound ? osl_File_E_None : osl_File_E_NOENT; +} + + +/**************************************************************************** + * FileURLToPath + ***************************************************************************/ + +oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL) +{ + rtl_uString* ustrSystemPath = NULL; + oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath); + + if(osl_File_E_None != osl_error) + return osl_error; + + osl_systemPathRemoveSeparator(ustrSystemPath); + + /* convert unicode path to text */ + if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length)) + osl_error = oslTranslateFileError(OSL_FET_ERROR, errno); + + rtl_uString_release(ustrSystemPath); + + return osl_error; +} diff --git a/sal/osl/os2/file_url.h b/sal/osl/os2/file_url.h new file mode 100644 index 000000000000..8884932c5a8a --- /dev/null +++ b/sal/osl/os2/file_url.h @@ -0,0 +1,186 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: file_url.h,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + /*************************************************** + * Internal header file, declares all functions + * that are not part of the offical API and are + * not defined in the osl header files + **************************************************/ + + #ifndef _FILE_URL_H_ + #define _FILE_URL_H_ + + #ifndef _FILE_H_ + #include <osl/file.h> + #endif + + +/*************************************************** + * constants + **************************************************/ + +#define _tcslen(a) wcslen((const wchar_t *) a) +#define _tcsspn(a,b) wcsspn((const wchar_t *) a, (const wchar_t *) b) +#define _istalpha(a) iswalpha((wint_t) a) + +const sal_Unicode UNICHAR_SLASH = ((sal_Unicode)'/'); +const sal_Unicode UNICHAR_COLON = ((sal_Unicode)':'); +const sal_Unicode UNICHAR_DOT = ((sal_Unicode)'.'); + +#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) + +#if OSL_DEBUG_LEVEL > 0 +#define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) ) +#else +#define OSL_ENSURE_FILE( cond, msg, file ) ((void)0) +#endif + +typedef sal_Unicode TCHAR; +typedef sal_Unicode *LPTSTR; +typedef const sal_Unicode *LPCTSTR; +typedef wchar_t *LPWSTR; +typedef const wchar_t *LPCWSTR; +typedef sal_Unicode DWORD; +#define WINAPI + +#define CHARSET_SEPARATOR L"\\/" +#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\" + + +/****************************************************************************** + * + * Data Type Definition + * + ******************************************************************************/ + +#define PATHTYPE_ERROR 0 +#define PATHTYPE_RELATIVE 1 +#define PATHTYPE_ABSOLUTE_UNC 2 +#define PATHTYPE_ABSOLUTE_LOCAL 3 +#define PATHTYPE_MASK_TYPE 0xFF +#define PATHTYPE_IS_VOLUME 0x0100 +#define PATHTYPE_IS_SERVER 0x0200 + +#define VALIDATEPATH_NORMAL 0x0000 +#define VALIDATEPATH_ALLOW_WILDCARDS 0x0001 +#define VALIDATEPATH_ALLOW_ELLIPSE 0x0002 +#define VALIDATEPATH_ALLOW_RELATIVE 0x0004 +#define VALIDATEPATH_ALLOW_UNC 0x0008 + +typedef struct { + UINT uType; + rtl_uString* ustrDrive; + rtl_uString* ustrFilePath; /* holds native directory path */ + int d_attr; /* OS/2 file attributes */ + int nRefCount; +}DirectoryItem_Impl; + +#define DIRECTORYTYPE_LOCALROOT 0 +#define DIRECTORYTYPE_NETROOT 1 +#define DIRECTORYTYPE_NETRESORCE 2 +#define DIRECTORYTYPE_FILESYSTEM 3 + +#define DIRECTORYITEM_DRIVE 0 +#define DIRECTORYITEM_FILE 1 +#define DIRECTORYITEM_SERVER 2 + +typedef struct +{ + UINT uType; + rtl_uString* ustrPath; /* holds native directory path */ + DIR* pDirStruct; + ULONG ulDriveMap; + ULONG ulNextDrive; + ULONG ulNextDriveMask; +} DirectoryImpl; + +/* Different types of paths */ +typedef enum _PATHTYPE +{ + PATHTYPE_SYNTAXERROR = 0, + PATHTYPE_NETROOT, + PATHTYPE_NETSERVER, + PATHTYPE_VOLUME, + PATHTYPE_FILE +} PATHTYPE; + +DWORD WINAPI IsValidFilePath(LPCTSTR, LPCTSTR*, DWORD); + +typedef struct +{ + rtl_uString* ustrFilePath; /* holds native file path */ + int fd; + sal_Bool bLocked; +} oslFileHandleImpl; + + +typedef struct _oslVolumeDeviceHandleImpl +{ + sal_Char pszMountPoint[PATH_MAX]; + sal_Char pszFilePath[PATH_MAX]; + sal_Char pszDevice[PATH_MAX]; + sal_Char ident[4]; + sal_uInt32 RefCount; +} oslVolumeDeviceHandleImpl; + +/* OS error to errno values mapping table */ +struct errentry { + unsigned long oscode; /* OS return value */ + int errnocode; /* System V error code */ +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************************************** +* _osl_getSystemPathFromFileURL +*************************************************/ + +#define FURL_ALLOW_RELATIVE sal_True +#define FURL_DENY_RELATIVE sal_False + +oslFileError osl_getSystemPathFromFileURL_Ex(rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative); + +/************************************************** +* FileURLToPath +*************************************************/ + +oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL); + + +#ifdef __cplusplus +} +#endif + + +#endif /* #define _FILE_URL_H_ */ + diff --git a/sal/osl/os2/helpers/debug.h b/sal/osl/os2/helpers/debug.h new file mode 100644 index 000000000000..b03508b70379 --- /dev/null +++ b/sal/osl/os2/helpers/debug.h @@ -0,0 +1,1782 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile:$ + * $Revision:$ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + *@@sourcefile debug.h: + * header file for debug.c (exception handling and debugging). + * See remarks there. + * + * Note: Version numbering in this file relates to XWorkplace version + * numbering. + * + *@@changed V0.9.0: included contents of newexe.h + * + *@@include #define INCL_BASE + *@@include #include <os2.h> + *@@include #include <stdio.h> + *@@include #include "helpers\debug.h" + */ + +/* + * This file incorporates code from the following: + * -- Marc Fiammante, John Currier, Kim Rasmussen, + * Anthony Cruise (EXCEPT3.ZIP package for a generic + * exception handling DLL, available at Hobbes). + * + * This file Copyright (C) 1992-99 Ulrich M�ller, + * Kim Rasmussen, + * Marc Fiammante, + * John Currier, + * Anthony Cruise. + * + * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. + * + */ + +#ifndef DEBUG_HEADER_INCLUDED + #define DEBUG_HEADER_INCLUDED + + /******************************************************************** + * + * SYM file declarations + * + ********************************************************************/ + + // Pointer means offset from beginning of file or beginning of struct + #pragma pack(1) + + typedef struct + { + unsigned short int ppNextMap; // paragraph pointer to next map + unsigned char bFlags; // symbol types + unsigned char bReserved1; // reserved + unsigned short int pSegEntry; // segment entry point value + unsigned short int cConsts; // count of constants in map + unsigned short int pConstDef; // pointer to constant chain + unsigned short int cSegs; // count of segments in map + unsigned short int ppSegDef; // paragraph pointer to first segment + unsigned char cbMaxSym; // maximum symbol-name length + unsigned char cbModName; // length of module name + char achModName[1]; // cbModName Bytes of module-name member + } MAPDEF; + + typedef struct + { + unsigned short int ppNextMap; // always zero + unsigned char release; // release number (minor version number) + unsigned char version; // major version number + } LAST_MAPDEF; + + typedef struct + { + unsigned short int ppNextSeg; // paragraph pointer to next segment + unsigned short int cSymbols; // count of symbols in list + unsigned short int pSymDef; // offset of symbol chain + unsigned short int wReserved1; // reserved + unsigned short int wReserved2; // reserved + unsigned short int wReserved3; // reserved + unsigned short int wReserved4; // reserved + unsigned char bFlags; // symbol types; bit 0 signals 32-bit (*UM) + unsigned char bReserved1; // reserved + unsigned short int ppLineDef; // offset of line number record + unsigned char bReserved2; // reserved + unsigned char bReserved3; // reserved + unsigned char cbSegName; // length of segment name + char achSegName[1]; /* cbSegName Bytes of segment-name member*/ + } SEGDEF; + + typedef struct + { + unsigned short int wSymVal; // symbol address or constant + unsigned char cbSymName; // length of symbol name + char achSymName[1]; // cbSymName Bytes of symbol-name member + } SYMDEF16; + + typedef struct + { + unsigned int wSymVal; // symbol address or constant + unsigned char cbSymName; // length of symbol name + char achSymName[1]; // cbSymName Bytes of symbol-name member + } SYMDEF32; + + typedef struct + { + unsigned short int ppNextLine; // ptr to next linedef (0 if last) + unsigned short int wReserved1; // reserved + unsigned short int pLines; // pointer to line numbers + unsigned short int cLines; // reserved + unsigned char cbFileName; // length of filename + char achFileName[1];// cbFileName Bytes of filename + } LINEDEF; + + typedef struct + { + unsigned short int wCodeOffset; // executable offset + unsigned short int dwFileOffset; // source offset + } LINEINF; + + #define SEGDEFOFFSET(MapDef) (MapDef.ppSegDef*16) + #define NEXTSEGDEFOFFSET(SegDef) (SegDef.ppNextSeg*16) + + #define ASYMPTROFFSET(SegDefOffset,Segdef) (SegDefOffset+SegDef.pSymDef) + #define SYMDEFOFFSET(SegDefOffset,SegDef,n) (ASYMPTROFFSET(SegDefOffset,SegDef)+(n)*(sizeof(unsigned short int))) + + #define ACONSTPTROFFSET(MapDef) (MapDef.ppConstDef) + #define CONSTDEFOFFSET(MapDef,n) ((MapDef.ppConstDef)+(n)*(sizeof(unsigned short int))) + + #define LINEDEFOFFSET(SegDef) (SegDef.ppLineDef*16) + #define NEXTLINEDEFOFFSET(LineDef) (LineDef.ppNextLine*16) + #define LINESOFFSET(LinedefOffset,LineDef) ((LinedefOffset)+LineDef.pLines) + + /******************************************************************** + * + * EXE declarations taken from exe.h + * + ********************************************************************/ + + #ifndef WORD + typedef unsigned short WORD; + #endif + + typedef WORD bbmask; + + struct exe { + WORD eid; // contains EXEID, below + WORD elast; // # of bytes in last page + WORD epagsiz; // # of pages in whole file + WORD erelcnt; // # of relocation entrys + WORD ehdrsiz; // size of header, in paragraphs + WORD eminfre; // min # of free paragraphs needed + WORD emaxfre; // max # of free paragraphs needed + WORD eiSS; // initial SS value + WORD eiSP; // initial SP value + WORD enegsum; // negative sum of entire file + WORD eiIP; // initial IP value + WORD eiCS; // initial CS value + WORD ereloff; // offset in file of relocation table + WORD eovlnum; // number of the overlay + + /* the following fields may not be present. + * ereloff = 28 not present + * = 30 exe.ever present and valid + * = 32 exe.ever field contains garbage + * ereloff > 32 exe.ever present and valid + * = 0 if "don't know" + */ + + WORD ever; // version # of producing linker + WORD dumy; // unused + + /* the following fields may not be present - if the exe.ereloff + * value encompasses the fields then they are present and valid. + */ + + bbmask ebb; // behavior bits + WORD dumy2[7]; // must be 0 until defined + }; + + + #define EXEID 0x5a4d // magic ID value + + /******************************************************************** + * + * Object Module Format (OMF) declarations + * + ********************************************************************/ + + struct exehdr_rec + { + BYTE signature[2]; // Must be "MZ" + USHORT image_len; // Image Length + USHORT pages; // Pages + USHORT reloc_items; // Relocation table items + USHORT min_paragraphs; // Mininum 16-bytes paragraphs + USHORT max_paragraphs; // Maximum 16-bytes paragraphs + USHORT stack_pos; // Stack position + USHORT offset_in_sp; // Offset in SP + USHORT checksum; // Checksum + USHORT offset_in_ip; // Offset in IP + USHORT code_pos; // Code segment pos. + USHORT reloc_item_pos; // Position of first relocation item + USHORT overlay_number; // Overlay number + BYTE unused[8]; // Unused bytes + USHORT oem_id; // OEM Identifier + BYTE oem_info[24]; // OEM Info + ULONG lexe_offset; // Offset to linear header + }; + + struct lexehdr_rec + { + BYTE signature[2]; // Must be "LX" + BYTE b_ord; // Byte ordering + BYTE w_ord; // Word ordering + ULONG format_level; // Format level + USHORT cpu_type; // CPU Type + USHORT os_type; // Operating system + ULONG module_version; // Module version + ULONG mod_flags; // Module flags + ULONG mod_pages; // Module pages + ULONG EIP_object; // EIP Object no. + ULONG EIP; // EIP Value + ULONG ESP_object; // ESP Object no + ULONG ESP; // ESP Value + ULONG page_size; // Page size + ULONG page_ofs_shift; // Page offset shift + ULONG fixup_sect_size; // Fixup section size + ULONG fixup_sect_checksum; // Fixup section checksum + ULONG loader_sect_size; // Loader section size + ULONG loader_sect_checksum; // Loader section checksum + ULONG obj_table_ofs; // Object table offset + ULONG obj_count; // Object count + ULONG obj_page_tab_ofs; // Object page table offset + ULONG obj_iter_page_ofs; // Object iteration pages offset + ULONG res_tab_ofs; // Resource table offset + ULONG res_table_entries; // Resource table entries + ULONG res_name_tab_ofs; // Resident name table offset; + ULONG ent_tab_ofs; // Entry table offset + ULONG mod_dir_ofs; // Module directives offset + ULONG mod_dir_count; // Number of module directives + ULONG fixup_page_tab_ofs; // Fixup page table offset + ULONG fixup_rec_tab_ofs; // Fixup record table offset + ULONG imp_tab_ofs; // Import module table offset + ULONG imp_mod_entries; // Import module entries + ULONG imp_proc_tab_ofs; // Import proc table offset + ULONG per_page_check_ofs; // Per page checksum offset + ULONG data_page_offset; // Data pages offset + ULONG preload_page_count; // Preload pages count + ULONG nonres_tab_ofs; // Nonresident name table offset + ULONG nonres_tab_len; // Nonresident name table len + ULONG nonres_tab_check; // Nonresident tables checksum + ULONG auto_ds_objectno; // Auto DS object number + ULONG debug_info_ofs; // Debug info offset + ULONG debug_info_len; // Debug info length + ULONG inst_preload_count; // Instance preload count + ULONG inst_demand_count; // Instance demand count + ULONG heapsize; // Heap size + ULONG stacksize; // Stack size + }; + + struct debug_head_rec + { + BYTE signature[3]; // Debug signature + BYTE type; // Debug info type + }; + + struct dir_inf_rec + { + USHORT dirstruct_size; // Size of directory structure + USHORT number_of_entries; // Number of dnt_rec's in the array + USHORT unknown; // Unknown data + // Followed by an array of dnt_rec structures + }; + + struct dnt_rec + { + USHORT subsect_type; // sst Subsection type + USHORT mod_index; // Module index (1-based) + ULONG offset; // Offset of start of section + ULONG size; // Size of section + }; + + // Modules subsection + struct modules_rec + { + USHORT code_seg_base; // Code segment base + ULONG code_seg_offset; // Code segment offset + ULONG code_seg_len; // Code segment length + USHORT overlay_no; // Overlay number + USHORT lib_idx; // Index into library section or 0 + BYTE segments; // Number of segments + BYTE reserved; + BYTE debug_style[2]; // "HL" for HLL, "CV" or 0 for CodeView + BYTE debug_version[2]; // 00 01 or 00 03 for HLL, 00 00 for CV + BYTE name_len; // Length of name (which follows) + }; + + // Publics subsection + struct publics_rec + { + ULONG offset; // Offset + USHORT segment; // Segment + USHORT type; // Type index + BYTE name_len; // Length of name (wich follows) + }; + + #if 0 + // Linenumbers header + struct linhead_rec + { + BYTE id; // 0x95 for flat mem, 32 bit progs + USHORT length; // Record length + USHORT base_group; // Base group + USHORT base_segment; // Base segment + }; + #endif + + // First linenumber record + struct linfirst_rec + { + USHORT lineno; // Line number (0) + BYTE entry_type; // Entry type + BYTE reserved; // Reserved + USHORT entries_count; // Number of table entries + USHORT segment_no; // Segment number + ULONG filename_tabsize; // File names table size + }; + + // Source line numbers + struct linsource_rec + { + USHORT source_line; // Source file line number + USHORT source_idx; // Source file index + ULONG offset; // Offset into segment + }; + + // Listing statement numbers + struct linlist_rec + { + ULONG list_line; // Listing file linenumber + ULONG statement; // Listing file statement number + ULONG offset; // Offset into segment + }; + + // Source and Listing statement numbers + struct linsourcelist_rec + { + USHORT source_line; // Source file line number + USHORT source_idx; // Source file index + ULONG list_line; // Listing file linenumber + ULONG statement; // Listing file statement number + ULONG offset; // Offset into segment + }; + + // Path table + struct pathtab_rec + { + ULONG offset; // Offset into segment + USHORT path_code; // Path code + USHORT source_idx; // Source file index + }; + + // File names table + struct filenam_rec + { + ULONG first_char; // First displayable char in list file + ULONG disp_chars; // Number of displayable chars in list line + ULONG filecount; // Number of source/listing files + }; + + // Symbol types + #define SYM_BEGIN 0x00 // Begin block + #define SYM_PROC 0x01 // Function + #define SYM_END 0x02 // End block of function + #define SYM_AUTO 0x04 // Auto variable + #define SYM_STATIC 0x05 // Static variable + #define SYM_LABEL 0x0B // Label + #define SYM_WITH 0x0C // With start symbol (not used) + #define SYM_REG 0x0D // Register variable + #define SYM_CONST 0x0E // Constant + #define SYM_ENTRY 0x0F // Secondary entry (not in C) + #define SYM_SKIP 0x10 // For incremental linking (not used) + #define SYM_CHANGESEG 0x11 // Change segment (#pragma alloc_text) + #define SYM_TYPEDEF 0x12 // Typedef variable + #define SYM_PUBLIC 0x13 // Public reference + #define SYM_MEMBER 0x14 // Member of minor or major structure + #define SYM_BASED 0x15 // Based variable + #define SYM_TAG 0x16 // Tag in struct, union, enum ... + #define SYM_TABLE 0x17 // Table (used in RPG - not C) + #define SYM_MAP 0x18 // Map variable (extern in C) + #define SYM_CLASS 0x19 // Class symbol (C++) + #define SYM_MEMFUNC 0x1A // Member function + #define SYM_AUTOSCOPE 0x1B // Scoped auto for C++ (not used) + #define SYM_STATICSCOPE 0x1C // scoped static for C++ (not used) + #define SYM_CPPPROC 0x1D // C++ Proc + #define SYM_CPPSTAT 0x1E // C++ Static var + #define SYM_COMP 0x40 // Compiler information + + // Symbolic begin record + struct symbegin_rec + { + ULONG offset; // Segment offset + ULONG length; // Length of block + BYTE name_len; // Length of block name + // Block name follows + }; + + // Symbolic auto var record + struct symauto_rec + { + ULONG stack_offset; // Stack offset + USHORT type_idx; // Type index + BYTE name_len; // Length of name + // Var name follows + }; + + // Symbolic procedure record + struct symproc_rec + { + ULONG offset; // Segment offset + USHORT type_idx; // Type index + ULONG length; // Length of procedure + USHORT pro_len; // Length of prologue + ULONG pro_bodylen; // Length of prologue + body + USHORT class_type; // Class type + BYTE near_far; // Near or far + BYTE name_len; // Length of name + // Function name follows + }; + + // Symbolic static var record + struct symstatic_rec + { + ULONG offset; // Segment offset + USHORT segaddr; // Segment address + USHORT type_idx; // Type index + BYTE name_len; // Length of name + // Var name follows + }; + + // Symbolic label var record + struct symlabel_rec + { + ULONG offset; // Segment offset + BYTE near_far; // Near or far + BYTE name_len; // Length of name + // Var name follows + }; + + // Symbolic register var record + struct symreg_rec + { + USHORT type_idx; // Type index + BYTE reg_no; // Register number + BYTE name_len; // Length of name + // Var name follows + }; + + // Symbolic change-segment record + struct symseg_rec + { + USHORT seg_no; // Segment number + }; + + // Symbolic typedef record + struct symtypedef_rec + { + USHORT type_idx; // Type index + BYTE name_len; // Length of name + // Name follows + }; + + // Symbolic public record + struct sympublic_rec + { + ULONG offset; // Segment offset + USHORT segaddr; // Segment address + USHORT type_idx; // Type index + BYTE name_len; // Length of name + // Name follows + }; + + // Symbolic member record + struct symmember_rec + { + ULONG offset; // Offset to subrecord + BYTE name_len; // Length of name + // Name follows + }; + + // Symbolic based record + struct symbased_rec + { + ULONG offset; // Offset to subrecord + USHORT type_idx; // Type index + BYTE name_len; // Length of name + // Name follows + }; + + // Symbolic tag record + struct symtag_rec + { + USHORT type_idx; // Type index + BYTE name_len; // Length of name + // Name follows + }; + + // Symbolic table record + struct symtable_rec + { + ULONG offset; // Segment offset + USHORT segaddr; // Segment address + USHORT type_idx; // Type index + ULONG idx_ofs; // Index offset to subrecord + BYTE name_len; // Length of name + // Name follows + }; + + // Type record + struct type_rec + { + USHORT length; // Length of sub-record + BYTE type; // Sub-record type + BYTE type_qual; // Type qualifier + }; + + // Types + #define TYPE_CLASS 0x40 // Class + #define TYPE_BASECLASS 0x41 // Base class + #define TYPE_FRIEND 0x42 // Friend + #define TYPE_CLASSDEF 0x43 // Class definition + #define TYPE_MEMBERFUNC 0x45 // Member function + #define TYPE_CLASSMEMBER 0x46 // Class member + #define TYPE_REF 0x48 // Reference + #define TYPE_MEMBERPTR 0x49 // Member pointer + #define TYPE_SCALARS 0x51 // Scalars + #define TYPE_SET 0x52 // Set + #define TYPE_ENTRY 0x53 // Entry + #define TYPE_FUNCTION 0x54 // Function + #define TYPE_AREA 0x55 // Area + #define TYPE_LOGICAL 0x56 // Logical + #define TYPE_STACK 0x57 // Stack + #define TYPE_MACRO 0x59 // Macro + #define TYPE_BITSTRING 0x5C // Bit string + #define TYPE_USERDEF 0x5D // User defined + #define TYPE_CHARSTR 0x60 // Character string + #define TYPE_PICTURE 0x61 // Picture + #define TYPE_GRAPHIC 0x62 // Graphic + #define TYPE_FORMATLAB 0x65 // Format label + #define TYPE_FILE 0x67 // File + #define TYPE_SUBRANGE 0x6F // Subrange + #define TYPE_CODELABEL 0x72 // Code label + #define TYPE_PROCEDURE 0x75 // Procedure + #define TYPE_ARRAY 0x78 // Array + #define TYPE_STRUCT 0x79 // Structure / Union / Record + #define TYPE_POINTER 0x7A // Pointer + #define TYPE_ENUM 0x7B // Enum + #define TYPE_LIST 0x7F // List + + // Type userdef + struct type_userdefrec + { + BYTE FID_index; // Field ID + USHORT type_index; // Type index + BYTE FID_string; // String ID + BYTE name_len; // Length of name which follows + }; + + // Type function + struct type_funcrec + { + USHORT params; + USHORT max_params; + BYTE FID_index; // Field ID + USHORT type_index; // Type index of return value + BYTE FID_index1; // String ID + USHORT typelist_index; // Index of list of params + }; + + // Type struct + struct type_structrec + { + ULONG size; // Size of structure + USHORT field_count; // Number of fields in structure + BYTE FID_index; // Field ID + USHORT type_list_idx; // Index to type list + BYTE FID_index1; // Field ID + USHORT type_name_idx; // Index to names / offsets + BYTE dont_know; // Haven't a clue, but it seems to be needed + BYTE name_len; // Length of structure name which follows + }; + + // Type list, type qualifier 1: contains types for structures + // This record is repeated for the number of items in the structure definition + struct type_list1 + { + BYTE FID_index; // Field identifier for index + USHORT type_index; // Type index. + }; + + // Type list, type qualifier 2: contains names and offsets for structure items + // This record is repeated for the number of items in the structure definition + struct type_list2 + { + BYTE FID_string; // String identifier + BYTE name_len; // Length of name which follows + }; + + // Type list, subrecord to the above, contains offset of variable in the structure + struct type_list2_1 + { + BYTE FID_span; // Defines what type of variable follows + union { + BYTE b_len; + USHORT s_len; + ULONG l_len; + } u; + }; + + // Type pointer + struct type_pointerrec + { + BYTE FID_index; // Index identifier + USHORT type_index; // Type index + BYTE FID_string; // String identifier + BYTE name_len; // Length of name which follows + }; + + /******************************************************************** + * + * Prototypes + * + ********************************************************************/ + + BOOL dbgPrintStackFrame(FILE *LogFile, + PSZ pszModuleName, // in: module name (fully q'fied) + ULONG ulObject, + ULONG ulOffset); + + VOID dbgPrintStack(FILE *file, + PUSHORT StackBottom, + PUSHORT StackTop, + PUSHORT Ebp, + PUSHORT ExceptionAddress); + + APIRET APIENTRY DosQueryModFromEIP(HMODULE *phMod, // out: trapping module + ULONG *pulObjNum, // out: object/segment number + ULONG ulBuffLen, // in: sizeof(*pszBuff) + CHAR *pszBuff, // out: module name + ULONG *pulOffset, // out: offset in module + ULONG ulAddress); // in: address to be analyzed + + APIRET APIENTRY DOSQUERYMODFROMEIP(HMODULE * phMod, + ULONG * pObjNum, + ULONG BuffLen, + PCHAR pBuff, + ULONG * pOffset, + PVOID Address); + + typedef ULONG *_Seg16 PULONG16; + APIRET16 APIENTRY16 DOS16SIZESEG(USHORT Seg, PULONG16 Size); + typedef APIRET16(APIENTRY16 _PFN16) (VOID); + ULONG APIENTRY DosSelToFlat(ULONG); + + APIRET16 APIENTRY16 DOSQPROCSTATUS(ULONG * _Seg16 pBuf, USHORT cbBuf); + + #define CONVERT(fp,QSsel) MAKEP((QSsel),OFFSETOF(fp)) + + #pragma pack() // added V0.9.0 + + + /******************************************************************** + * + * Executable definitions + * + ********************************************************************/ + + #define EXE386 1 + + #ifndef __NEWEXE__ + #define __NEWEXE__ + + #pragma pack(1) + + /*_________________________________________________________________* + | | + | | + | DOS3 .EXE FILE HEADER DEFINITION | + | | + |_________________________________________________________________| + * */ + + + #define EMAGIC 0x5A4D // Old magic number + #define ENEWEXE sizeof(struct exe_hdr) + // Value of E_LFARLC for new .EXEs + #define ENEWHDR 0x003C // Offset in old hdr. of ptr. to new + #define ERESWDS 0x0010 // No. of reserved words (OLD) + #define ERES1WDS 0x0004 // No. of reserved words in e_res + #define ERES2WDS 0x000A // No. of reserved words in e_res2 + #define ECP 0x0004 // Offset in struct of E_CP + #define ECBLP 0x0002 // Offset in struct of E_CBLP + #define EMINALLOC 0x000A // Offset in struct of E_MINALLOC + + /* + *@@ exe_hdr: + * DOS 1, 2, 3 .EXE header. + */ + + struct exe_hdr + { + unsigned short e_magic; // Magic number + unsigned short e_cblp; // Bytes on last page of file + unsigned short e_cp; // Pages in file + unsigned short e_crlc; // Relocations + unsigned short e_cparhdr; // Size of header in paragraphs + unsigned short e_minalloc; // Minimum extra paragraphs needed + unsigned short e_maxalloc; // Maximum extra paragraphs needed + unsigned short e_ss; // Initial (relative) SS value + unsigned short e_sp; // Initial SP value + unsigned short e_csum; // Checksum + unsigned short e_ip; // Initial IP value + unsigned short e_cs; // Initial (relative) CS value + unsigned short e_lfarlc; // File address of relocation table + unsigned short e_ovno; // Overlay number + unsigned short e_res[ERES1WDS];// Reserved words + unsigned short e_oemid; // OEM identifier (for e_oeminfo) + unsigned short e_oeminfo; // OEM information; e_oemid specific + unsigned short e_res2[ERES2WDS];// Reserved words + long e_lfanew; // File address of new exe header + }; + + #define E_MAGIC(x) (x).e_magic + #define E_CBLP(x) (x).e_cblp + #define E_CP(x) (x).e_cp + #define E_CRLC(x) (x).e_crlc + #define E_CPARHDR(x) (x).e_cparhdr + #define E_MINALLOC(x) (x).e_minalloc + #define E_MAXALLOC(x) (x).e_maxalloc + #define E_SS(x) (x).e_ss + #define E_SP(x) (x).e_sp + #define E_CSUM(x) (x).e_csum + #define E_IP(x) (x).e_ip + #define E_CS(x) (x).e_cs + #define E_LFARLC(x) (x).e_lfarlc + #define E_OVNO(x) (x).e_ovno + #define E_RES(x) (x).e_res + #define E_OEMID(x) (x).e_oemid + #define E_OEMINFO(x) (x).e_oeminfo + #define E_RES2(x) (x).e_res2 + #define E_LFANEW(x) (x).e_lfanew + + + /*_________________________________________________________________* + | | + | | + | OS/2 & WINDOWS .EXE FILE HEADER DEFINITION - 286 version | + | | + |_________________________________________________________________| + * */ + + #define NEMAGIC 0x454E // New magic number + #define NERESBYTES 8 // Eight bytes reserved (now) + #define NECRC 8 // Offset into new header of NE_CRC + + /* + *@@ new_exe: + * New Executable (NE) header. + * Follows DOS header in the executable file. + */ + + struct new_exe + { + unsigned short ne_magic; // Magic number NE_MAGIC + unsigned char ne_ver; // Version number + unsigned char ne_rev; // Revision number + unsigned short ne_enttab; // Offset of Entry Table + unsigned short ne_cbenttab; // Number of bytes in Entry Table + long ne_crc; // Checksum of whole file + unsigned short ne_flags; // Flag word + unsigned short ne_autodata; // Automatic data segment number + unsigned short ne_heap; // Initial heap allocation + unsigned short ne_stack; // Initial stack allocation + long ne_csip; // Initial CS:IP setting + long ne_sssp; // Initial SS:SP setting + unsigned short ne_cseg; // Count of file segments + unsigned short ne_cmod; // Entries in Module Reference Table + unsigned short ne_cbnrestab; // Size of non-resident name table + unsigned short ne_segtab; // Offset of Segment Table + unsigned short ne_rsrctab; // Offset of Resource Table + unsigned short ne_restab; // Offset of resident name table + unsigned short ne_modtab; // Offset of Module Reference Table + unsigned short ne_imptab; // Offset of Imported Names Table + long ne_nrestab; // Offset of Non-resident Names Table + unsigned short ne_cmovent; // Count of movable entries + unsigned short ne_align; // Segment alignment shift count + unsigned short ne_cres; // Count of resource entries + unsigned char ne_exetyp; // Target operating system + unsigned char ne_flagsothers; // Other .EXE flags + char ne_res[NERESBYTES]; // Pad structure to 64 bytes + }; + + #pragma pack() + + #define NE_MAGIC(x) (x).ne_magic + #define NE_VER(x) (x).ne_ver + #define NE_REV(x) (x).ne_rev + #define NE_ENTTAB(x) (x).ne_enttab + #define NE_CBENTTAB(x) (x).ne_cbenttab + #define NE_CRC(x) (x).ne_crc + #define NE_FLAGS(x) (x).ne_flags + #define NE_AUTODATA(x) (x).ne_autodata + #define NE_HEAP(x) (x).ne_heap + #define NE_STACK(x) (x).ne_stack + #define NE_CSIP(x) (x).ne_csip + #define NE_SSSP(x) (x).ne_sssp + #define NE_CSEG(x) (x).ne_cseg + #define NE_CMOD(x) (x).ne_cmod + #define NE_CBNRESTAB(x) (x).ne_cbnrestab + #define NE_SEGTAB(x) (x).ne_segtab + #define NE_RSRCTAB(x) (x).ne_rsrctab + #define NE_RESTAB(x) (x).ne_restab + #define NE_MODTAB(x) (x).ne_modtab + #define NE_IMPTAB(x) (x).ne_imptab + #define NE_NRESTAB(x) (x).ne_nrestab + #define NE_CMOVENT(x) (x).ne_cmovent + #define NE_ALIGN(x) (x).ne_align + #define NE_CRES(x) (x).ne_cres + #define NE_RES(x) (x).ne_res + #define NE_EXETYP(x) (x).ne_exetyp + #define NE_FLAGSOTHERS(x) (x).ne_flagsothers + + #define NE_USAGE(x) (WORD)*((WORD *)(x)+1) + #define NE_PNEXTEXE(x) (WORD)(x).ne_cbenttab + #define NE_ONEWEXE(x) (WORD)(x).ne_crc + #define NE_PFILEINFO(x) (WORD)((DWORD)(x).ne_crc >> 16) + + + /* + * Target operating systems + */ + + #define NE_UNKNOWN 0x0 /* Unknown (any "new-format" OS) */ + #define NE_OS2 0x1 /* OS/2 (default) */ + #define NE_WINDOWS 0x2 /* Windows */ + #define NE_DOS4 0x3 /* DOS 4.x */ + #define NE_DEV386 0x4 /* Windows 386 */ + + + /* + * Format of NE_FLAGS(x): + * + * p Not-a-process + * x Unused + * e Errors in image + * x Unused + * b Bound Family/API + * ttt Application type + * f Floating-point instructions + * 3 386 instructions + * 2 286 instructions + * 0 8086 instructions + * P Protected mode only + * p Per-process library initialization + * i Instance data + * s Solo data + */ + #define NENOTP 0x8000 /* Not a process */ + #define NEIERR 0x2000 /* Errors in image */ + #define NEBOUND 0x0800 /* Bound Family/API */ + #define NEAPPTYP 0x0700 /* Application type mask */ + #define NENOTWINCOMPAT 0x0100 /* Not compatible with P.M. Windowing */ + #define NEWINCOMPAT 0x0200 /* Compatible with P.M. Windowing */ + #define NEWINAPI 0x0300 /* Uses P.M. Windowing API */ + #define NEFLTP 0x0080 /* Floating-point instructions */ + #define NEI386 0x0040 /* 386 instructions */ + #define NEI286 0x0020 /* 286 instructions */ + #define NEI086 0x0010 /* 8086 instructions */ + #define NEPROT 0x0008 /* Runs in protected mode only */ + #define NEPPLI 0x0004 /* Per-Process Library Initialization */ + #define NEINST 0x0002 /* Instance data */ + #define NESOLO 0x0001 /* Solo data */ + + /* + * Format of NE_FLAGSOTHERS(x): + * + * 7 6 5 4 3 2 1 0 - bit no + * | | | | + * | | | +---------------- Support for long file names + * | | +------------------ Windows 2.x app runs in prot mode + * | +-------------------- Windows 2.x app gets prop. font + * +------------------------------ WLO appl on OS/2 (markwlo.exe) + * + */ + + #define NELONGNAMES 0x01 + #define NEWINISPROT 0x02 + #define NEWINGETPROPFON 0x04 + #define NEWLOAPPL 0x80 + + + + struct new_seg /* New .EXE segment table entry */ + { + unsigned short ns_sector; /* File sector of start of segment */ + unsigned short ns_cbseg; /* Number of bytes in file */ + unsigned short ns_flags; /* Attribute flags */ + unsigned short ns_minalloc; /* Minimum allocation in bytes */ + }; + + #define NS_SECTOR(x) (x).ns_sector + #define NS_CBSEG(x) (x).ns_cbseg + #define NS_FLAGS(x) (x).ns_flags + #define NS_MINALLOC(x) (x).ns_minalloc + + + /* + * Format of NS_FLAGS(x) + * + * Flag word has the following format: + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no + * | | | | | | | | | | | | | | | + * | | | | | | | | | | | | +-+-+--- Segment type DATA/CODE + * | | | | | | | | | | | +--------- Iterated segment + * | | | | | | | | | | +----------- Movable segment + * | | | | | | | | | +------------- Segment can be shared + * | | | | | | | | +--------------- Preload segment + * | | | | | | | +----------------- Execute/read-only for code/data segment + * | | | | | | +------------------- Segment has relocations + * | | | | | +--------------------- Code conforming/Data is expand down + * | | | +--+----------------------- I/O privilege level + * | | +----------------------------- Discardable segment + * | +-------------------------------- 32-bit code segment + * +----------------------------------- Huge segment/GDT allocation requested + * + */ + + #define NSTYPE 0x0007 /* Segment type mask */ + + #ifdef EXE386 + #define NSCODE 0x0000 /* Code segment */ + #define NSDATA 0x0001 /* Data segment */ + #define NSITER 0x0008 /* Iterated segment flag */ + #define NSMOVE 0x0010 /* Movable segment flag */ + #define NSSHARED 0x0020 /* Shared segment flag */ + #define NSPRELOAD 0x0040 /* Preload segment flag */ + #define NSEXRD 0x0080 /* Execute-only (code segment), or + * read-only (data segment) + */ + #define NSRELOC 0x0100 /* Segment has relocations */ + #define NSCONFORM 0x0200 /* Conforming segment */ + #define NSEXPDOWN 0x0200 /* Data segment is expand down */ + #define NSDPL 0x0C00 /* I/O privilege level (286 DPL bits) */ + #define SHIFTDPL 10 /* Left shift count for SEGDPL field */ + #define NSDISCARD 0x1000 /* Segment is discardable */ + #define NS32BIT 0x2000 /* 32-bit code segment */ + #define NSHUGE 0x4000 /* Huge memory segment, length of + * segment and minimum allocation + * size are in segment sector units + */ + #define NSGDT 0x8000 /* GDT allocation requested */ + + #define NSPURE NSSHARED /* For compatibility */ + + #define NSALIGN 9 /* Segment data aligned on 512 byte boundaries */ + + #define NSLOADED 0x0004 /* ns_sector field contains memory addr */ + #endif + + + struct new_segdata /* Segment data */ + { + union + { + struct + { + unsigned short ns_niter; /* number of iterations */ + unsigned short ns_nbytes; /* number of bytes */ + char ns_iterdata; /* iterated data bytes */ + } ns_iter; + struct + { + char ns_data; /* data bytes */ + } ns_noniter; + } ns_union; + }; + + struct new_rlcinfo /* Relocation info */ + { + unsigned short nr_nreloc; /* number of relocation items that */ + }; /* follow */ + + #pragma pack(1) + + + struct new_rlc /* Relocation item */ + { + char nr_stype; /* Source type */ + char nr_flags; /* Flag byte */ + unsigned short nr_soff; /* Source offset */ + union + { + struct + { + char nr_segno; /* Target segment number */ + char nr_res; /* Reserved */ + unsigned short nr_entry; /* Target Entry Table offset */ + } nr_intref; /* Internal reference */ + struct + { + unsigned short nr_mod; /* Index into Module Reference Table */ + unsigned short nr_proc; /* Procedure ordinal or name offset */ + } nr_import; /* Import */ + struct + { + unsigned short nr_ostype; /* OSFIXUP type */ + unsigned short nr_osres; /* reserved */ + } nr_osfix; /* Operating system fixup */ + } nr_union; /* Union */ + }; + + #pragma pack() + + + #define NR_STYPE(x) (x).nr_stype + #define NR_FLAGS(x) (x).nr_flags + #define NR_SOFF(x) (x).nr_soff + #define NR_SEGNO(x) (x).nr_union.nr_intref.nr_segno + #define NR_RES(x) (x).nr_union.nr_intref.nr_res + #define NR_ENTRY(x) (x).nr_union.nr_intref.nr_entry + #define NR_MOD(x) (x).nr_union.nr_import.nr_mod + #define NR_PROC(x) (x).nr_union.nr_import.nr_proc + #define NR_OSTYPE(x) (x).nr_union.nr_osfix.nr_ostype + #define NR_OSRES(x) (x).nr_union.nr_osfix.nr_osres + + + + /* + * Format of NR_STYPE(x) and R32_STYPE(x): + * + * 7 6 5 4 3 2 1 0 - bit no + * | | | | + * +-+-+-+--- source type + * + */ + + #define NRSTYP 0x0f /* Source type mask */ + #define NRSBYT 0x00 /* lo byte (8-bits)*/ + #define NRSSEG 0x02 /* 16-bit segment (16-bits) */ + #define NRSPTR 0x03 /* 16:16 pointer (32-bits) */ + #define NRSOFF 0x05 /* 16-bit offset (16-bits) */ + #define NRPTR48 0x06 /* 16:32 pointer (48-bits) */ + #define NROFF32 0x07 /* 32-bit offset (32-bits) */ + #define NRSOFF32 0x08 /* 32-bit self-relative offset (32-bits) */ + + + /* + * Format of NR_FLAGS(x) and R32_FLAGS(x): + * + * 7 6 5 4 3 2 1 0 - bit no + * | | | + * | +-+--- Reference type + * +------- Additive fixup + */ + + #define NRADD 0x04 /* Additive fixup */ + #define NRRTYP 0x03 /* Reference type mask */ + #define NRRINT 0x00 /* Internal reference */ + #define NRRORD 0x01 /* Import by ordinal */ + #define NRRNAM 0x02 /* Import by name */ + #define NRROSF 0x03 /* Operating system fixup */ + + + #if (EXE386 == 0) + + /* Resource type or name string */ + struct rsrc_string + { + char rs_len; /* number of bytes in string */ + char rs_string[ 1 ]; /* text of string */ + }; + + #define RS_LEN( x ) (x).rs_len + #define RS_STRING( x ) (x).rs_string + + /* Resource type information block */ + struct rsrc_typeinfo + { + unsigned short rt_id; + unsigned short rt_nres; + long rt_proc; + }; + + #define RT_ID( x ) (x).rt_id + #define RT_NRES( x ) (x).rt_nres + #define RT_PROC( x ) (x).rt_proc + + /* Resource name information block */ + struct rsrc_nameinfo + { + /* The following two fields must be shifted left by the value of */ + /* the rs_align field to compute their actual value. This allows */ + /* resources to be larger than 64k, but they do not need to be */ + /* aligned on 512 byte boundaries, the way segments are */ + unsigned short rn_offset; /* file offset to resource data */ + unsigned short rn_length; /* length of resource data */ + unsigned short rn_flags; /* resource flags */ + unsigned short rn_id; /* resource name id */ + unsigned short rn_handle; /* If loaded, then global handle */ + unsigned short rn_usage; /* Initially zero. Number of times */ + /* the handle for this resource has */ + /* been given out */ + }; + + #define RN_OFFSET( x ) (x).rn_offset + #define RN_LENGTH( x ) (x).rn_length + #define RN_FLAGS( x ) (x).rn_flags + #define RN_ID( x ) (x).rn_id + #define RN_HANDLE( x ) (x).rn_handle + #define RN_USAGE( x ) (x).rn_usage + + #define RSORDID 0x8000 /* if high bit of ID set then integer id */ + /* otherwise ID is offset of string from + the beginning of the resource table */ + + /* Ideally these are the same as the */ + /* corresponding segment flags */ + #define RNMOVE 0x0010 /* Moveable resource */ + #define RNPURE 0x0020 /* Pure (read-only) resource */ + #define RNPRELOAD 0x0040 /* Preloaded resource */ + #define RNDISCARD 0xF000 /* Discard priority level for resource */ + + /* Resource table */ + struct new_rsrc + { + unsigned short rs_align; /* alignment shift count for resources */ + struct rsrc_typeinfo rs_typeinfo; + }; + + #define RS_ALIGN( x ) (x).rs_align + + + #endif /* NOT EXE386 */ + + #endif /* __NEWEXE__ */ + + #ifndef DWORD + #define DWORD long int + #endif + + #ifndef WORD + #define WORD short int + #endif + + #ifndef __EXE386__ + #define __EXE386__ + + #pragma pack(1) /* Force byte alignment */ + + /*_________________________________________________________________* + | | + | | + | OS/2 .EXE FILE HEADER DEFINITION - 386 version 0:32 | + | | + |_________________________________________________________________| + * */ + + #define BITPERWORD 16 + #define BITPERBYTE 8 + #define OBJPAGELEN 4096 + #define E32MAGIC1 'L' /* New magic number "LX" */ + #define E32MAGIC2 'X' /* New magic number "LX" */ + #define E32MAGIC 0x584c /* New magic number "LX" */ + #define E32RESBYTES1 0 /* First bytes reserved */ + #define E32RESBYTES2 0 /* Second bytes reserved */ + #define E32RESBYTES3 20 /* Third bytes reserved */ + #define E32LEBO 0x00 /* Little Endian Byte Order */ + #define E32BEBO 0x01 /* Big Endian Byte Order */ + #define E32LEWO 0x00 /* Little Endian Word Order */ + #define E32BEWO 0x01 /* Big Endian Word Order */ + #define E32LEVEL 0L /* 32-bit EXE format level */ + #define E32CPU286 0x001 /* Intel 80286 or upwardly compatibile */ + #define E32CPU386 0x002 /* Intel 80386 or upwardly compatibile */ + #define E32CPU486 0x003 /* Intel 80486 or upwardly compatibile */ + + + + struct e32_exe /* New 32-bit .EXE header */ + { + unsigned char e32_magic[2]; /* Magic number E32_MAGIC */ + unsigned char e32_border; /* The byte ordering for the .EXE */ + unsigned char e32_worder; /* The word ordering for the .EXE */ + unsigned long e32_level; /* The EXE format level for now = 0 */ + unsigned short e32_cpu; /* The CPU type */ + unsigned short e32_os; /* The OS type */ + unsigned long e32_ver; /* Module version */ + unsigned long e32_mflags; /* Module flags */ + unsigned long e32_mpages; /* Module # pages */ + unsigned long e32_startobj; /* Object # for instruction pointer */ + unsigned long e32_eip; /* Extended instruction pointer */ + unsigned long e32_stackobj; /* Object # for stack pointer */ + unsigned long e32_esp; /* Extended stack pointer */ + unsigned long e32_pagesize; /* .EXE page size */ + unsigned long e32_pageshift; /* Page alignment shift in .EXE */ + unsigned long e32_fixupsize; /* Fixup section size */ + unsigned long e32_fixupsum; /* Fixup section checksum */ + unsigned long e32_ldrsize; /* Loader section size */ + unsigned long e32_ldrsum; /* Loader section checksum */ + unsigned long e32_objtab; /* Object table offset */ + unsigned long e32_objcnt; /* Number of objects in module */ + unsigned long e32_objmap; /* Object page map offset */ + unsigned long e32_itermap; /* Object iterated data map offset */ + unsigned long e32_rsrctab; /* Offset of Resource Table */ + unsigned long e32_rsrccnt; /* Number of resource entries */ + unsigned long e32_restab; /* Offset of resident name table */ + unsigned long e32_enttab; /* Offset of Entry Table */ + unsigned long e32_dirtab; /* Offset of Module Directive Table */ + unsigned long e32_dircnt; /* Number of module directives */ + unsigned long e32_fpagetab; /* Offset of Fixup Page Table */ + unsigned long e32_frectab; /* Offset of Fixup Record Table */ + unsigned long e32_impmod; /* Offset of Import Module Name Table */ + unsigned long e32_impmodcnt; /* Number of entries in Import Module Name Table */ + unsigned long e32_impproc; /* Offset of Import Procedure Name Table */ + unsigned long e32_pagesum; /* Offset of Per-Page Checksum Table */ + unsigned long e32_datapage; /* Offset of Enumerated Data Pages */ + unsigned long e32_preload; /* Number of preload pages */ + unsigned long e32_nrestab; /* Offset of Non-resident Names Table */ + unsigned long e32_cbnrestab; /* Size of Non-resident Name Table */ + unsigned long e32_nressum; /* Non-resident Name Table Checksum */ + unsigned long e32_autodata; /* Object # for automatic data object */ + unsigned long e32_debuginfo; /* Offset of the debugging information */ + unsigned long e32_debuglen; /* The length of the debugging info. in bytes */ + unsigned long e32_instpreload;/* Number of instance pages in preload section of .EXE file */ + unsigned long e32_instdemand; /* Number of instance pages in demand load section of .EXE file */ + unsigned long e32_heapsize; /* Size of heap - for 16-bit apps */ + unsigned long e32_stacksize; /* Size of stack */ + unsigned char e32_res3[E32RESBYTES3]; + /* Pad structure to 196 bytes */ + }; + + + + #define E32_MAGIC1(x) (x).e32_magic[0] + #define E32_MAGIC2(x) (x).e32_magic[1] + #define E32_BORDER(x) (x).e32_border + #define E32_WORDER(x) (x).e32_worder + #define E32_LEVEL(x) (x).e32_level + #define E32_CPU(x) (x).e32_cpu + #define E32_OS(x) (x).e32_os + #define E32_VER(x) (x).e32_ver + #define E32_MFLAGS(x) (x).e32_mflags + #define E32_MPAGES(x) (x).e32_mpages + #define E32_STARTOBJ(x) (x).e32_startobj + #define E32_EIP(x) (x).e32_eip + #define E32_STACKOBJ(x) (x).e32_stackobj + #define E32_ESP(x) (x).e32_esp + #define E32_PAGESIZE(x) (x).e32_pagesize + #define E32_PAGESHIFT(x) (x).e32_pageshift + #define E32_FIXUPSIZE(x) (x).e32_fixupsize + #define E32_FIXUPSUM(x) (x).e32_fixupsum + #define E32_LDRSIZE(x) (x).e32_ldrsize + #define E32_LDRSUM(x) (x).e32_ldrsum + #define E32_OBJTAB(x) (x).e32_objtab + #define E32_OBJCNT(x) (x).e32_objcnt + #define E32_OBJMAP(x) (x).e32_objmap + #define E32_ITERMAP(x) (x).e32_itermap + #define E32_RSRCTAB(x) (x).e32_rsrctab + #define E32_RSRCCNT(x) (x).e32_rsrccnt + #define E32_RESTAB(x) (x).e32_restab + #define E32_ENTTAB(x) (x).e32_enttab + #define E32_DIRTAB(x) (x).e32_dirtab + #define E32_DIRCNT(x) (x).e32_dircnt + #define E32_FPAGETAB(x) (x).e32_fpagetab + #define E32_FRECTAB(x) (x).e32_frectab + #define E32_IMPMOD(x) (x).e32_impmod + #define E32_IMPMODCNT(x) (x).e32_impmodcnt + #define E32_IMPPROC(x) (x).e32_impproc + #define E32_PAGESUM(x) (x).e32_pagesum + #define E32_DATAPAGE(x) (x).e32_datapage + #define E32_PRELOAD(x) (x).e32_preload + #define E32_NRESTAB(x) (x).e32_nrestab + #define E32_CBNRESTAB(x) (x).e32_cbnrestab + #define E32_NRESSUM(x) (x).e32_nressum + #define E32_AUTODATA(x) (x).e32_autodata + #define E32_DEBUGINFO(x) (x).e32_debuginfo + #define E32_DEBUGLEN(x) (x).e32_debuglen + #define E32_INSTPRELOAD(x) (x).e32_instpreload + #define E32_INSTDEMAND(x) (x).e32_instdemand + #define E32_HEAPSIZE(x) (x).e32_heapsize + #define E32_STACKSIZE(x) (x).e32_stacksize + + + + /* + * Format of E32_MFLAGS(x): + * + * Low word has the following format: + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no + * | | | | | | | | + * | | | | | | | +------- Per-Process Library Initialization + * | | | | | | +--------- SystemDLL (internal fixups discarded) + * | | | | | +----------- No Internal Fixups for Module in .EXE + * | | | | +------------- No External Fixups for Module in .EXE + * | | | +------------------- Incompatible with PM Windowing + * | | +--------------------- Compatible with PM Windowing + * | | Uses PM Windowing API + * | +-------------------------------- Module not Loadable + * +-------------------------------------- Library Module + */ + + + #define E32NOTP 0x8000L /* Library Module - used as NENOTP */ + #define E32NOLOAD 0x2000L /* Module not Loadable */ + #define E32PMAPI 0x0300L /* Uses PM Windowing API */ + #define E32PMW 0x0200L /* Compatible with PM Windowing */ + #define E32NOPMW 0x0100L /* Incompatible with PM Windowing */ + #define E32NOEXTFIX 0x0020L /* NO External Fixups in .EXE */ + #define E32NOINTFIX 0x0010L /* NO Internal Fixups in .EXE */ + #define E32SYSDLL 0x0008L /* System DLL, Internal Fixups discarded*/ + #define E32LIBINIT 0x0004L /* Per-Process Library Initialization */ + #define E32LIBTERM 0x40000000L /* Per-Process Library Termination */ + #define E32APPMASK 0x0300L /* Application Type Mask */ + + + /* + * Format of E32_MFLAGS(x): + * + * High word has the following format: + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no + * | | + * | +--- Protected memory library module + * +----- Device driver + */ + + #define E32PROTDLL 0x10000L /* Protected memory library module */ + #define E32DEVICE 0x20000L /* Device driver */ + #define E32MODEXE 0x00000L /* .EXE module */ + #define E32MODDLL 0x08000L /* .DLL module */ + #define E32MODPROTDLL 0x18000L /* Protected memory library module */ + #define E32MODPDEV 0x20000L /* Physical device driver */ + #define E32MODVDEV 0x28000L /* Virtual device driver */ + #define E32MODMASK 0x38000L /* Module type mask */ + + /* + * RELOCATION DEFINITIONS - RUN-TIME FIXUPS + */ + + typedef union _RELOC_OFS + { + unsigned short offset16; + unsigned long offset32; + } RELOC_OFS; /* 16-bit or 32-bit offset */ + + + /***ET+ r32_rlc - Relocation item */ + + struct r32_rlc /* Relocation item */ + { + unsigned char nr_stype; /* Source type - field shared with new_rlc */ + unsigned char nr_flags; /* Flag byte - field shared with new_rlc */ + short r32_soff; /* Source offset */ + unsigned short r32_objmod; /* Target object number or Module ordinal */ + + union targetid + { + RELOC_OFS intref; /* Internal fixup */ + + union extfixup + { + RELOC_OFS proc; /* Procedure name offset */ + unsigned long ord; /* Procedure odrinal */ + } extref; /* External fixup */ + + struct addfixup + { + unsigned short entry; /* Entry ordinal */ + RELOC_OFS addval; /* Value added to the address */ + } addfix; /* Additive fixup */ + } + r32_target; /* Target data */ + unsigned short r32_srccount; /* Number of chained fixup records */ + unsigned short r32_chain; /* Chain head */ + }; + + /* + * In 32-bit .EXE file run-time relocations are written as varying size + * records, so we need many size definitions. + */ + + #define RINTSIZE16 8 + #define RINTSIZE32 10 + #define RORDSIZE 8 + #define RNAMSIZE16 8 + #define RNAMSIZE32 10 + #define RADDSIZE16 10 + #define RADDSIZE32 12 + + #if FALSE + /* + * Access macros defined in NEWEXE.H !!! + */ + #define NR_STYPE(x) (x).nr_stype + #define NR_FLAGS(x) (x).nr_flags + #endif + + #define R32_SOFF(x) (x).r32_soff + #define R32_OBJNO(x) (x).r32_objmod + #define R32_MODORD(x) (x).r32_objmod + #define R32_OFFSET16(x) (x).r32_target.intref.offset16 + #define R32_OFFSET32(x) (x).r32_target.intref.offset32 + #define R32_PROCOFF16(x) (x).r32_target.extref.proc.offset16 + #define R32_PROCOFF32(x) (x).r32_target.extref.proc.offset32 + #define R32_PROCORD(x) (x).r32_target.extref.ord + #define R32_ENTRY(x) (x).r32_target.addfix.entry + #define R32_ADDVAL16(x) (x).r32_target.addfix.addval.offset16 + #define R32_ADDVAL32(x) (x).r32_target.addfix.addval.offset32 + #define R32_SRCCNT(x) (x).r32_srccount + #define R32_CHAIN(x) (x).r32_chain + + + + /* + * Format of NR_STYPE(x) + * + * 7 6 5 4 3 2 1 0 - bit no + * | | | | | | + * | | +-+-+-+--- Source type + * | +----------- Fixup to 16:16 alias + * +------------- List of source offset follows fixup record + */ + + #if FALSE + + /* DEFINED in newexe.h !!! */ + + #define NRSTYP 0x0f /* Source type mask */ + #define NRSBYT 0x00 /* lo byte (8-bits)*/ + #define NRSSEG 0x02 /* 16-bit segment (16-bits) */ + #define NRSPTR 0x03 /* 16:16 pointer (32-bits) */ + #define NRSOFF 0x05 /* 16-bit offset (16-bits) */ + #define NRPTR48 0x06 /* 16:32 pointer (48-bits) */ + #define NROFF32 0x07 /* 32-bit offset (32-bits) */ + #define NRSOFF32 0x08 /* 32-bit self-relative offset (32-bits) */ + #endif + + + #define NRSRCMASK 0x0f /* Source type mask */ + #define NRALIAS 0x10 /* Fixup to alias */ + #define NRCHAIN 0x20 /* List of source offset follows */ + /* fixup record, source offset field */ + /* in fixup record contains number */ + /* of elements in list */ + + /* + * Format of NR_FLAGS(x) and R32_FLAGS(x): + * + * 7 6 5 4 3 2 1 0 - bit no + * | | | | | | | + * | | | | | +-+--- Reference type + * | | | | +------- Additive fixup + * | | | +----------- 32-bit Target Offset Flag (1 - 32-bit; 0 - 16-bit) + * | | +------------- 32-bit Additive Flag (1 - 32-bit; 0 - 16-bit) + * | +--------------- 16-bit Object/Module ordinal (1 - 16-bit; 0 - 8-bit) + * +----------------- 8-bit import ordinal (1 - 8-bit; + * 0 - NR32BITOFF toggles + * between 16 and 32 bit + * ordinal) + */ + + #ifdef NEVER_INCLUDE_THE_FOLLWING + /* DEFINED in newexe.h !!! */ + #define NRRTYP 0x03 /* Reference type mask */ + #define NRRINT 0x00 /* Internal reference */ + #define NRRORD 0x01 /* Import by ordinal */ + #define NRRNAM 0x02 /* Import by name */ + #define NRADD 0x04 /* Additive fixup */ + #endif + + #define NRRENT 0x03 /* Internal entry table fixup */ + + #define NR32BITOFF 0x10 /* 32-bit Target Offset */ + #define NR32BITADD 0x20 /* 32-bit Additive fixup */ + #define NR16OBJMOD 0x40 /* 16-bit Object/Module ordinal */ + #define NR8BITORD 0x80 /* 8-bit import ordinal */ + /*end*/ + + /* + * Data structures for storing run-time fixups in linker virtual memory. + * + * Each object has a list of Object Page Directories which specify + * fixups for given page. Each page has its own hash table which is + * used to detect fixups to the same target. + */ + + #define PAGEPERDIR 62 + #define LG2DIR 7 + + + typedef struct _OBJPAGEDIR + { + DWORD next; /* Virtual pointer to next dir on list */ + WORD ht[PAGEPERDIR]; /* Pointers to individual hash tables */ + } + OBJPAGEDIR; + + /* + * OBJECT TABLE + */ + + /***ET+ o32_obj Object Table Entry */ + + struct o32_obj /* Flat .EXE object table entry */ + { + unsigned long o32_size; /* Object virtual size */ + unsigned long o32_base; /* Object base virtual address */ + unsigned long o32_flags; /* Attribute flags */ + unsigned long o32_pagemap; /* Object page map index */ + unsigned long o32_mapsize; /* Number of entries in object page map */ + unsigned long o32_reserved; /* Reserved */ + }; + + + #define O32_SIZE(x) (x).o32_size + #define O32_BASE(x) (x).o32_base + #define O32_FLAGS(x) (x).o32_flags + #define O32_PAGEMAP(x) (x).o32_pagemap + #define O32_MAPSIZE(x) (x).o32_mapsize + #define O32_RESERVED(x) (x).o32_reserved + + /* + * Format of O32_FLAGS(x) + * + * High word of dword flag field is not used for now. + * Low word has the following format: + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no + * | | | | | | | | | | | | | | | + * | | | | | | | | | | | | | | +--- Readable Object + * | | | | | | | | | | | | | +----- Writeable Object + * | | | | | | | | | | | | +------- Executable Object + * | | | | | | | | | | | +--------- Resource Object + * | | | | | | | | | | +----------- Object is Discardable + * | | | | | | | | | +------------- Object is Shared + * | | | | | | | | +--------------- Object has preload pages + * | | | | | | | +----------------- Object has invalid pages + * | | | | | | +------------------- Object is permanent and swappable + * | | | | | +--------------------- Object is permanent and resident + * | | | | +----------------------- Object is permanent and long lockable + * | | | +----------------------------- 16:16 alias required (80x86 specific) + * | | +-------------------------------- Big/Default bit setting (80x86 specific) + * | +----------------------------------- Object is conforming for code (80x86 specific) + * +-------------------------------------- Object I/O privilege level (80x86 specific) + * + */ + + #define OBJREAD 0x0001L /* Readable Object */ + #define OBJWRITE 0x0002L /* Writeable Object */ + #define OBJRSRC 0x0008L /* Resource Object */ + #define OBJINVALID 0x0080L /* Object has invalid pages */ + #define LNKNONPERM 0x0600L /* Object is nonpermanent - should be */ + #define OBJNONPERM 0x0000L /* zero in the .EXE but LINK386 uses 6 */ + #define OBJPERM 0x0100L /* Object is permanent and swappable */ + #define OBJRESIDENT 0x0200L /* Object is permanent and resident */ + #define OBJCONTIG 0x0300L /* Object is resident and contiguous */ + #define OBJDYNAMIC 0x0400L /* Object is permanent and long locable */ + #define OBJTYPEMASK 0x0700L /* Object type mask */ + #define OBJALIAS16 0x1000L /* 16:16 alias required (80x86 specific) */ + #define OBJBIGDEF 0x2000L /* Big/Default bit setting (80x86 specific) */ + #define OBJIOPL 0x8000L /* Object I/O privilege level (80x86 specific) */ + #if FOR_EXEHDR + /* + * Name these flags differently for EXEHDR.EXE - avoid conflicts with 286 version + */ + #define OBJDISCARD 0x0010L /* Object is Discardable */ + #define OBJSHARED 0x0020L /* Object is Shared */ + #define OBJPRELOAD 0x0040L /* Object has preload pages */ + #define OBJEXEC 0x0004L /* Executable Object */ + #define OBJCONFORM 0x4000L /* Object is conforming for code (80x86 specific) */ + #else + /* + * Life will be easier, if we keep the same names for the following flags: + */ + #ifndef NSDISCARD + #define NSDISCARD 0x0010L /* Object is Discardable */ + #endif + #ifndef NSMOVE + #define NSMOVE NSDISCARD /* Moveable object is for sure Discardable */ + #endif + #ifndef NSSHARED + #define NSSHARED 0x0020L /* Object is Shared */ + #endif + #ifndef NSPRELOAD + #define NSPRELOAD 0x0040L /* Object has preload pages */ + #endif + #ifndef NSEXRD + #define NSEXRD 0x0004L /* Executable Object */ + #endif + #ifndef NSCONFORM + #define NSCONFORM 0x4000L /* Object is conforming for code (80x86 specific) */ + #endif + #endif + /*end*/ + + /***ET+ o32_map - Object Page Map entry */ + + struct o32_map /* Object Page Table entry */ + { + unsigned long o32_pagedataoffset; /* file offset of page */ + unsigned short o32_pagesize; /* # bytes of page data */ + unsigned short o32_pageflags; /* Per-Page attributes */ + }; + + + #define GETPAGEIDX(x) ((x).o32_pagedataoffset) + + #define PUTPAGEIDX(x,i) ((x).o32_pagedataoffset = ((unsigned long)(i))) + + #define PUTPAGESIZ(x,i) ((x).o32_pagesize = ((unsigned int)(i))) + + #define GETPAGESIZ(x) ((x).o32_pagesize) + + #define PAGEFLAGS(x) (x).o32_pageflags + + + #define VALID 0x0000 /* Valid Physical Page in .EXE */ + #define ITERDATA 0x0001 /* Iterated Data Page */ + #define INVALID 0x0002 /* Invalid Page */ + #define ZEROED 0x0003 /* Zero Filled Page */ + #define RANGE 0x0004 /* Range of pages */ + #define ITERDATA2 0x0005 /* Iterated Data Page Type II */ + /*end*/ + + /* + * RESOURCE TABLE + */ + + /***ET+ rsrc32 - Resource Table Entry */ + + struct rsrc32 /* Resource Table Entry */ + { + unsigned short type; /* Resource type */ + unsigned short name; /* Resource name */ + unsigned long cb; /* Resource size */ + unsigned short obj; /* Object number */ + unsigned long offset; /* Offset within object */ + }; + /*end*/ + + + /* + * Iteration Record format for 'EXEPACK'ed pages. + */ + struct LX_Iter + { + unsigned short LX_nIter; /* number of iterations */ + unsigned short LX_nBytes; /* number of bytes */ + unsigned char LX_Iterdata; /* iterated data byte(s) */ + }; + + + /* + * ENTRY TABLE DEFINITIONS + */ + + /***ET+ b32_bundle - Entry Table */ + + struct b32_bundle + { + unsigned char b32_cnt; /* Number of entries in this bundle */ + unsigned char b32_type; /* Bundle type */ + unsigned short b32_obj; /* Object number */ + }; /* Follows entry types */ + + struct e32_entry + { + unsigned char e32_flags; /* Entry point flags */ + union entrykind + { + RELOC_OFS e32_offset; /* 16-bit/32-bit offset entry */ + struct callgate + { + unsigned short offset; /* Offset in segment */ + unsigned short callgate; /* Callgate selector */ + } + e32_callgate; /* 286 (16-bit) call gate */ + struct fwd + { + unsigned short modord; /* Module ordinal number */ + unsigned long value; /* Proc name offset or ordinal */ + } + e32_fwd; /* Forwarder */ + } + e32_variant; /* Entry variant */ + }; + + + + #define B32_CNT(x) (x).b32_cnt + #define B32_TYPE(x) (x).b32_type + #define B32_OBJ(x) (x).b32_obj + + #define E32_EFLAGS(x) (x).e32_flags + #define E32_OFFSET16(x) (x).e32_variant.e32_offset.offset16 + #define E32_OFFSET32(x) (x).e32_variant.e32_offset.offset32 + #define E32_GATEOFF(x) (x).e32_variant.e32_callgate.offset + #define E32_GATE(x) (x).e32_variant.e32_callgate.callgate + #define E32_MODORD(x) (x).e32_variant.e32_fwd.modord + #define E32_VALUE(x) (x).e32_variant.e32_fwd.value + + #define FIXENT16 3 + #define FIXENT32 5 + #define GATEENT16 5 + #define FWDENT 7 + + /* + * BUNDLE TYPES + */ + + #define EMPTY 0x00 /* Empty bundle */ + #define ENTRY16 0x01 /* 16-bit offset entry point */ + #define GATE16 0x02 /* 286 call gate (16-bit IOPL) */ + #define ENTRY32 0x03 /* 32-bit offset entry point */ + #define ENTRYFWD 0x04 /* Forwarder entry point */ + #define TYPEINFO 0x80 /* Typing information present flag */ + + + /* + * Format for E32_EFLAGS(x) + * + * 7 6 5 4 3 2 1 0 - bit no + * | | | | | | | | + * | | | | | | | +--- exported entry + * | | | | | | +----- uses shared data + * +-+-+-+-+-+------- parameter word count + */ + + #define E32EXPORT 0x01 /* Exported entry */ + #define E32SHARED 0x02 /* Uses shared data */ + #define E32PARAMS 0xf8 /* Parameter word count mask */ + + /* + * Flags for forwarders only: + */ + + #define FWD_ORDINAL 0x01 /* Imported by ordinal */ + + + #pragma pack() /* Restore default alignment */ + + /*end*/ + + #endif /* __EXE386__ */ + +#endif diff --git a/sal/osl/os2/helpers/dosh.h b/sal/osl/os2/helpers/dosh.h new file mode 100644 index 000000000000..518f979fd4de --- /dev/null +++ b/sal/osl/os2/helpers/dosh.h @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile:$ + * $Revision:$ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* This file Copyright (C) 1997-2006 Ulrich M�ller, + * Dmitry A. Steklenev. + * This file is part of the "XWorkplace helpers" source package. + * + * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. + * + */ + +#if __cplusplus +extern "C" { +#endif + +#ifndef DOSH_HEADER_INCLUDED + #define DOSH_HEADER_INCLUDED + + CHAR doshQueryBootDrive(VOID); + +#endif + +#if __cplusplus +} +#endif diff --git a/sal/osl/os2/helpers/except.h b/sal/osl/os2/helpers/except.h new file mode 100644 index 000000000000..b2d6b17ca702 --- /dev/null +++ b/sal/osl/os2/helpers/except.h @@ -0,0 +1,258 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile:$ + * $Revision:$ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + *@@sourcefile except.h: + * header file for except.c. See remarks there. + * + * Note: Version numbering in this file relates to XWorkplace version + * numbering. + * + *@@include #define INCL_DOSEXCEPTIONS + *@@include #define INCL_DOSPROCESS + *@@include #include <os2.h> + *@@include #include <stdio.h> + *@@include #include <setjmp.h> + *@@include #include "helpers\except.h" + */ + +/* + * Copyright (C) 1999-2000 Ulrich M�ller. + * + * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. + * + */ + +#if __cplusplus +extern "C" { +#endif + +#ifndef EXCEPT_HEADER_INCLUDED + #define EXCEPT_HEADER_INCLUDED + + #if defined __IBMCPP__ || defined __IBMC__ + #ifndef INCL_DOSEXCEPTIONS + #error except.h requires INCL_DOSEXCEPTIONS to be defined. + #endif + #ifndef INCL_DOSPROCESS + #error except.h requires INCL_DOSPROCESS to be defined. + #endif + + #ifndef __stdio_h + #error except.h requires stdio.h to be included. + #endif + #ifndef __setjmp_h + #error except.h requires setjmp.h to be included. + #endif + #endif + + /******************************************************************** + * + * Declarations + * + ********************************************************************/ + + // forward declaration + typedef struct _EXCEPTIONREGISTRATIONRECORD2 *PEXCEPTIONREGISTRATIONRECORD2; + + // "OnKill" function prototype for EXCEPTIONREGISTRATIONRECORD2 + // added V0.9.0 (99-10-22) [umoeller] + // removed V0.9.7 (2000-12-08) [umoeller] + // typedef VOID APIENTRY FNEXCONKILL(PEXCEPTIONREGISTRATIONRECORD2); + // typedef FNEXCONKILL *PFNEXCONKILL; + + /* + *@@ EXCEPTIONREGISTRATIONRECORD2: + * replacement EXCEPTIONREGISTRATIONRECORD + * struct for thread exception handling. + * + *@@changed V0.9.0 (99-10-22) [umoeller]: pfnOnKill added + *@@changed V0.9.0 (99-10-22) [umoeller]: renamed from REGREC2 + */ + + typedef struct _EXCEPTIONREGISTRATIONRECORD2 + { + PVOID pNext; // as in EXCEPTIONREGISTRATIONRECORD + PFN pfnHandler; // as in EXCEPTIONREGISTRATIONRECORD + jmp_buf jmpThread; // additional buffer for setjmp + EXCEPTIONREPORTRECORD err; // exception handlers copy the report rec here + PVOID pvUser; // user ptr + } EXCEPTIONREGISTRATIONRECORD2; + + /* + *@@ EXCEPTSTRUCT: + * structure used with TRY_xxx macros. + */ + + typedef struct _EXCEPTSTRUCT + { + EXCEPTIONREGISTRATIONRECORD2 RegRec2; + ULONG ulExcpt; // != NULL if exception caught + APIRET arc; // rc of DosSetExceptionHandler + } EXCEPTSTRUCT, *PEXCEPTSTRUCT; + + // function prototypes for exception hooks (V0.9.0) + + // "open traplog file" hook + typedef FILE* APIENTRY FNEXCOPENFILE(VOID); + typedef FNEXCOPENFILE *PFNEXCOPENFILE; + + // "exception" hook + typedef VOID APIENTRY FNEXCHOOK(FILE*, PTIB, ULONG); // V0.9.16 (2001-12-02) [pr] + typedef FNEXCHOOK *PFNEXCHOOK; + + // "error" hook + typedef VOID APIENTRY FNEXCHOOKERROR(const char *pcszFile, + ULONG ulLine, + const char *pcszFunction, + APIRET arc); + typedef FNEXCHOOKERROR *PFNEXCHOOKERROR; + + /******************************************************************** + * + * Prototypes + * + ********************************************************************/ + + VOID excExplainException(FILE *file, + PSZ pszHandlerName, + PEXCEPTIONREPORTRECORD pReportRec, + PCONTEXTRECORD pContextRec); + + VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew, + PFNEXCHOOK pfnExcHookNew, + PFNEXCHOOKERROR pfnExcHookError, + BOOL fBeepOnExceptionNew); + + ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec, + PEXCEPTIONREGISTRATIONRECORD2 pRegRec2, + PCONTEXTRECORD pContextRec, + PVOID pv); + + ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec, + PEXCEPTIONREGISTRATIONRECORD2 pRegRec2, + PCONTEXTRECORD pContextRec, + PVOID pv); + + extern PFNEXCHOOKERROR G_pfnExcHookError; + + extern ULONG G_ulExplainExceptionRunning; + + /******************************************************************** + * + * Macros + * + ********************************************************************/ + + /* See except.c for explanations how to use these. */ + + #ifdef __NO_EXCEPTION_HANDLERS__ + // exception handlers can completely be disabled + #define TRY_LOUD(excptstruct) + #else + #ifdef __NO_LOUD_EXCEPTION_HANDLERS__ + #define TRY_LOUD(e) TRY_QUIET(e) + #else // __NO_LOUD_EXCEPTION_HANDLERS__ + #define TRY_LOUD(excptstruct) \ + { \ + EXCEPTSTRUCT excptstruct = {0}; \ + excptstruct.RegRec2.pfnHandler = (PFN)excHandlerLoud; \ + excptstruct.arc = DosSetExceptionHandler( \ + (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \ + if (excptstruct.arc) \ + if (G_pfnExcHookError) \ + G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, excptstruct.arc); \ + else \ + DosBeep(1000, 1000); \ + excptstruct.ulExcpt = setjmp(excptstruct.RegRec2.jmpThread); \ + if (excptstruct.ulExcpt == 0) \ + { + + #endif // __NO_LOUD_EXCEPTION_HANDLERS__ + #endif + + #ifdef __NO_EXCEPTION_HANDLERS__ + // exception handlers can completely be disabled + #define TRY_QUIET(excptstruct) + #else + #define TRY_QUIET(excptstruct) \ + { \ + EXCEPTSTRUCT excptstruct = {0}; \ + excptstruct.RegRec2.pfnHandler = (PFN)excHandlerQuiet; \ + excptstruct.arc = DosSetExceptionHandler( \ + (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \ + if (excptstruct.arc) \ + if (G_pfnExcHookError) \ + G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, excptstruct.arc); \ + else \ + DosBeep(1000, 1000); \ + excptstruct.ulExcpt = setjmp(excptstruct.RegRec2.jmpThread); \ + if (excptstruct.ulExcpt == 0) \ + { + + #endif + + #ifdef __NO_EXCEPTION_HANDLERS__ + // exception handlers can completely be disabled + #define CATCH(excptstruct) if (FALSE) { + #else + #define CATCH(excptstruct) \ + DosUnsetExceptionHandler( \ + (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \ + } /* end of TRY block */ \ + else \ + { /* exception occured: */ \ + DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); + #endif + + #ifdef __NO_EXCEPTION_HANDLERS__ + // exception handlers can completely be disabled + #define END_CATCH() } + #else + #define END_CATCH() \ + } /* end of exception-occured block */ \ + } + #endif + + /* + * CRASH: + * this macro is helpful for testing + * the exception handlers. + * This is not for general use. ;-) + */ + + #define CRASH {PSZ p = NULL; *p = 'a'; } + +#endif // EXCEPT_HEADER_INCLUDED + +#if __cplusplus +} +#endif + diff --git a/sal/osl/os2/helpers/setup.h b/sal/osl/os2/helpers/setup.h new file mode 100644 index 000000000000..6c02d8b655fb --- /dev/null +++ b/sal/osl/os2/helpers/setup.h @@ -0,0 +1,153 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile:$ + * $Revision:$ + * + * 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. + * + * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. + * + * + ************************************************************************/ + +/* + * setup.h: + * sample master include file which gets included + * from all helpers *.c sources. + */ + +#ifndef SETUP_HEADER_INCLUDED + #define SETUP_HEADER_INCLUDED + + // XWPEXPORT defines the standard linkage for the + // XWorkplace helpers. + #ifdef __EMX__ + #define XWPENTRY + #elif defined (__IBMCPP__) || defined (__IBMC__) + #define XWPENTRY _Optlink + #endif + + /************************************************************* + * * + * Additional stuff for EMX * + * * + *************************************************************/ + + #ifdef __EMX__ + // EMX doesn't have all these 16-bit typedefs; + // added (99-10-22) [umoeller] + #define APIENTRY16 _Far16 _Pascal + #define PASCAL16 _Far16 _Pascal + #define CDECL16 _Far16 _Cdecl + + typedef unsigned short APIRET16; + typedef unsigned long APIRET32; + +#if 0 +//YD do not use with gcc 3.3.5 + #define _System + #define APIENTRY + // with VAC++, this defines _System linkage, which + // EMX doesn't have, or does it?!? +#endif // 0 + + #endif + + // the following is a VAC++-specific macro, which doesn't exist + // with EMX, so we need to implement this... this was one of + // the "undefined symbols" we got (99-10-23) [umoeller] + // changed this to prefix underscore, because the STL apparently + // redefines this V0.9.3 (2000-05-15) [umoeller] + #define _min(a,b) ( ((a) > (b)) ? b : a ) + #define _max(a,b) ( ((a) > (b)) ? a : b ) + + // Uncomment the following if you have trouble with the + // exception handlers in helpers\except.c; WarpIN will + // then install _no_ additional exception handlers at all + // (include\helpers\except.h reacts to these defines). + // I'm not sure if the handlers work well with EMX. + + #ifdef __EMX__00 + #define __NO_EXCEPTION_HANDLERS__ + #endif + + /************************************************************* + * * + * Additional stuff for VAC++ 3.0 * + * * + *************************************************************/ + + // all this added V0.9.2 (2000-03-10) [umoeller] + #if ( defined ( __IBMCPP__ ) && ( __IBMCPP__ < 400 ) ) + typedef int bool; + #define true 1 + #define false 0 + #define _BooleanConst // needed for some VAC headers, which define bool also + #endif + + #ifndef __stdlib_h // <stdlib.h> + #include <stdlib.h> + #endif + #ifndef __string_h // <string.h> + #include <string.h> + #endif + + /************************************************************* + * * + * Debugging * + * * + *************************************************************/ + + // All the following redone (99-10-23) [umoeller]: + // __DEBUG__ is defined as a macro on the compiler + // command line by the makefiles if DEBUG was enabled + // in \setup.in + #ifdef __DEBUG__ + + // with debug code, disable the exception handlers + #define __NO_EXCEPTION_HANDLERS__ + + // If the following is commented out, no PMPRINTF will be + // used at all. WarpIN uses Dennis Bareis' PMPRINTF + // package to do this. + + // NOTE: We cannot use PmPrintf with EMX, + // because pmprintf.lib imports the VAC++ runtimes. + // That's the strange errors I was reporting yesterday. + #ifndef __EMX__ + #ifdef OS2_INCLUDED + #define _PMPRINTF_ + #include "helpers/pmprintf.h" + #endif + #endif + #endif + + #ifndef _PMPRINTF_ + // not defined: define empty macro so we don't + // get compiler errors + #define _Pmpf(x) + #endif + +#endif + diff --git a/sal/osl/os2/interlck.c b/sal/osl/os2/interlck.c new file mode 100644 index 000000000000..003398880cfc --- /dev/null +++ b/sal/osl/os2/interlck.c @@ -0,0 +1,54 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: interlck.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <386/builtin.h> + +#include "system.h" + +#include <osl/interlck.h> +#include <osl/diagnose.h> + +/*****************************************************************************/ +/* osl_incrementInterlockedCount */ +/*****************************************************************************/ +oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) +{ + return __atomic_increment_s32( pCount); +} + +/*****************************************************************************/ +/* osl_decrementInterlockedCount */ +/*****************************************************************************/ +oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) +{ + return __atomic_decrement_s32( pCount); +} + + diff --git a/sal/osl/os2/libutil.c b/sal/osl/os2/libutil.c new file mode 100644 index 000000000000..1cf8680ddc7b --- /dev/null +++ b/sal/osl/os2/libutil.c @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: libutil.c,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if 0 // YD + +#include <windows.h> + +static BOOL g_bInit = FALSE; +static DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; + +DWORD GetPlatformId() +{ + + if (!g_bInit) + { + OSVERSIONINFO aInfo; + + aInfo.dwOSVersionInfoSize = sizeof(aInfo); + if (GetVersionEx(&aInfo)) + g_dwPlatformId = aInfo.dwPlatformId; + + g_bInit = TRUE; + } + + return g_dwPlatformId; +} + +#endif // 0 diff --git a/sal/osl/os2/makefile.mk b/sal/osl/os2/makefile.mk new file mode 100644 index 000000000000..94a47b2bb02b --- /dev/null +++ b/sal/osl/os2/makefile.mk @@ -0,0 +1,122 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=sal +TARGET=cpposl +USE_LDUMP2=TRUE + +PROJECTPCH4DLL=TRUE +PROJECTPCH=cont_pch +PROJECTPCHSOURCE=cont_pch + +MULTITHREAD_OBJ=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# Uncomment the following line if you want to compile with -Wall +# it disables lots of unnecessary warnings comming from the Win32 +# header files (disabling warnings via command line only works with +# MSVC >= 7.x) +# +# CFLAGS+=/wd4668 /wd4711 /wd4201 /wd4710 /wd4619 /wd4514 /wd4820 + +# --- Files -------------------------------------------------------- + +.IF "$(header)" == "" + +SLOFILES= $(SLO)$/conditn.obj \ + $(SLO)$/diagnose.obj \ + $(SLO)$/dllentry.obj \ + $(SLO)$/semaphor.obj \ + $(SLO)$/interlck.obj \ + $(SLO)$/nlsupport.obj\ + $(SLO)$/mutex.obj \ + $(SLO)$/module.obj \ + $(SLO)$/process.obj \ + $(SLO)$/time.obj \ + $(SLO)$/signal.obj \ + $(SLO)$/pipe.obj \ + $(SLO)$/util.obj \ + $(SLO)$/socket.obj \ + $(SLO)$/thread.obj \ + $(SLO)$/security.obj \ + $(SLO)$/profile.obj \ + $(SLO)$/tempfile.obj \ + $(SLO)$/process_impl.obj\ + $(SLO)$/uunxapi.obj\ + $(SLO)$/file.obj \ + $(SLO)$/file_url.obj \ + $(SLO)$/file_error_transl.obj \ + $(SLO)$/file_path_helper.obj \ + $(SLO)$/debug.obj \ + $(SLO)$/except.obj \ + $(SLO)$/salinit.obj + +OBJFILES= $(OBJ)$/conditn.obj \ + $(OBJ)$/diagnose.obj \ + $(OBJ)$/libutil.obj \ + $(OBJ)$/semaphor.obj \ + $(OBJ)$/interlck.obj \ + $(OBJ)$/nlsupport.obj\ + $(OBJ)$/mutex.obj \ + $(OBJ)$/module.obj \ + $(OBJ)$/process.obj \ + $(OBJ)$/time.obj \ + $(OBJ)$/signal.obj \ + $(OBJ)$/pipe.obj \ + $(OBJ)$/util.obj \ + $(OBJ)$/socket.obj \ + $(OBJ)$/thread.obj \ + $(OBJ)$/security.obj \ + $(OBJ)$/profile.obj \ + $(OBJ)$/tempfile.obj \ + $(OBJ)$/process_impl.obj\ + $(OBJ)$/uunxapi.obj\ + $(OBJ)$/file.obj \ + $(OBJ)$/file_url.obj \ + $(OBJ)$/file_error_transl.obj \ + $(OBJ)$/file_path_helper.obj \ + $(OBJ)$/debug.obj \ + $(OBJ)$/except.obj \ + $(SLO)$/salinit.obj + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + + diff --git a/sal/osl/os2/module.c b/sal/osl/os2/module.c new file mode 100644 index 000000000000..901c029429c4 --- /dev/null +++ b/sal/osl/os2/module.c @@ -0,0 +1,284 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: module.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "system.h" + +#include <osl/module.h> +#include <osl/diagnose.h> +#include <osl/file.h> +#include <osl/thread.h> + +#include <stdlib.h> + +int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32); + +// static data for holding SAL dll module and full path +static HMODULE hModSal; +static char szSalDir[ _MAX_PATH]; +static char szSalDrive[ _MAX_PATH]; + +/*****************************************************************************/ +/* osl_loadModule */ +/*****************************************************************************/ + +ULONG APIENTRY _DosLoadModule (PSZ pszObject, ULONG uObjectLen, PCSZ pszModule, + PHMODULE phmod) +{ + APIRET rc; + rc = DosLoadModule( pszObject, uObjectLen, pszModule, phmod); + // YD 22/05/06 issue again if first call fails (why?) + if (rc == ERROR_INVALID_PARAMETER) + rc = DosLoadModule( pszObject, uObjectLen, pszModule, phmod); + return rc; +} + +oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode) +{ + HMODULE hModule; + BYTE szErrorMessage[256]; + APIRET rc; + oslModule pModule=0; + rtl_uString* ustrTmp = NULL; + + OSL_ENSURE(ustrModuleName,"osl_loadModule : string is not valid"); + + /* ensure ustrTmp hold valid string */ + if( osl_File_E_None != osl_getSystemPathFromFileURL( ustrModuleName, &ustrTmp ) ) + rtl_uString_assign( &ustrTmp, ustrModuleName ); + + if( ustrTmp ) + { + char buffer[PATH_MAX]; + + if( UnicodeToText( buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length ) ) + { + char drive[_MAX_DRIVE], dir[_MAX_DIR]; + char fname[_MAX_FNAME], ext[_MAX_EXT]; + char* dot; + // 21/02/2006 YD dll names must be 8.3: since .uno.dll files + // have hardcoded names, I'm truncating names here and also in + // the build system + _splitpath (buffer, drive, dir, fname, ext); + if (strlen(fname)>8) + fname[8] = 0; // truncate to 8.3 + dot = strchr( fname, '.'); + if (dot) + *dot = '\0'; // truncate on dot + // if drive is not specified, remove starting \ from dir name + // so dll is loaded from LIBPATH + if (drive[0] == 0 && dir[0] == '\\' && dir[1] == '\\') { + while( dir[0] == '\\') + strcpy( dir, dir+1); + } + _makepath( buffer, drive, dir, fname, ext); + + rc = _DosLoadModule( szErrorMessage, sizeof( szErrorMessage), (PCSZ)buffer, &hModule); + if (rc == NO_ERROR ) + pModule = (oslModule)hModule; + else + { + if (rc == NO_ERROR ) + pModule = (oslModule)hModule; + else + { + sal_Char szError[ PATH_MAX*2 ]; + sprintf( szError, "Module: %s; rc: %d;\nReason: %s;\n" + "Please contact technical support and report above informations.\n\n", + buffer, rc, szErrorMessage ); +#if OSL_DEBUG_LEVEL>0 + fprintf( stderr, szError); +#endif + //OSL_TRACE(szError); +#ifndef OSL_DEBUG_LEVEL + WinMessageBox(HWND_DESKTOP,HWND_DESKTOP, + szError, "Critical error: DosLoadModule failed", + 0, MB_ERROR | MB_OK | MB_MOVEABLE); +#endif + } + } + } + } + + rtl_uString_release( ustrTmp ); + + return pModule; +} + +/*****************************************************************************/ +/* osl_getModuleHandle */ +/*****************************************************************************/ + +sal_Bool SAL_CALL +osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult) +{ + HMODULE hmod; + APIRET rc; + rc = DosQueryModuleHandle(pModuleName->buffer, &hmod); + if( rc == NO_ERROR) + { + *pResult = (oslModule) hmod; + return sal_True; + } + + return sal_False; +} + +/*****************************************************************************/ +/* osl_unloadModule */ +/*****************************************************************************/ +void SAL_CALL osl_unloadModule(oslModule Module) +{ +#if OSL_DEBUG_LEVEL>0 + if (!Module) + fprintf( stderr, "osl_unloadModule NULL HANDLE.\n"); +#endif + + DosFreeModule((HMODULE)Module); +} + +/*****************************************************************************/ +/* osl_getSymbol */ +/*****************************************************************************/ +void* SAL_CALL +osl_getSymbol(oslModule Module, rtl_uString* pSymbolName) +{ + return (void *) osl_getFunctionSymbol(Module, pSymbolName); +} + +/*****************************************************************************/ +/* osl_getFunctionSymbol */ +/*****************************************************************************/ +oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName ) +{ + rtl_String *symbolName = NULL; + oslGenericFunction address; + + OSL_ASSERT(Module); + OSL_ASSERT(strSymbolName); + + rtl_uString2String( + &symbolName, + strSymbolName->buffer, + strSymbolName->length, + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS + ); + + address=osl_getAsciiFunctionSymbol(Module, rtl_string_getStr(symbolName)); + rtl_string_release(symbolName); + + return address; +} + +/*****************************************************************************/ +/* osl_getAsciiFunctionSymbol */ +/*****************************************************************************/ +oslGenericFunction SAL_CALL +osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol ) +{ + PFN pFunction; + APIRET rc; + void* pHandle=0; + + OSL_ENSURE(Module,"osl_getSymbol : module handle is not valid"); + OSL_ENSURE(Module,"osl_getSymbol : ustrSymbolName"); + + if ( Module!= 0 && pSymbol != 0 ) + { + + rc = DosQueryProcAddr( (HMODULE) Module, 0, (PCSZ)pSymbol, &pFunction ); + if( rc == NO_ERROR ) + { + pHandle = (void*)pFunction; + } + else + { + // YD try again adding the '_' prefix + char _pszSymbolName[255]; + strcpy( _pszSymbolName, "_"); + strcat( _pszSymbolName, pSymbol); + rc = DosQueryProcAddr( (HMODULE) Module, 0, (PCSZ)_pszSymbolName, &pFunction ); + if( rc == NO_ERROR ) + pHandle = (void*)pFunction; + } + + } + + return pHandle; +} + +/*****************************************************************************/ +/* osl_getModuleURLFromAddress */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl) +{ + //APIRET APIENTRY DosQueryModFromEIP (HMODULE *phMod, ULONG *pObjNum, + // ULONG BuffLen, PCHAR pBuff, ULONG *pOffset, ULONG Address) + HMODULE hMod; + ULONG ObjNum; + CHAR Buff[2*_MAX_PATH]; + ULONG Offset; + APIRET rc; + + // get module handle (and name) + rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, &Offset, (ULONG)addr); + if (rc) + return sal_False; + + // get module full path + rc = DosQueryModuleName( hMod, sizeof( Buff), Buff); + if (rc) + return sal_False; + +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE("module.c::osl_getModuleURLFromAddress - %s\n", Buff); +#endif + + // convert to URL + rtl_uString *ustrSysPath = NULL; + rtl_string2UString( &ustrSysPath, Buff, strlen(Buff), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(ustrSysPath != NULL); + osl_getFileURLFromSystemPath( ustrSysPath, ppLibraryUrl ); + rtl_uString_release( ustrSysPath ); + + return sal_True; +} + +/*****************************************************************************/ +/* osl_getModuleURLFromFunctionAddress */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress( oslGenericFunction addr, rtl_uString ** ppLibraryUrl ) +{ + return osl_getModuleURLFromAddress( ( void * )addr, ppLibraryUrl ); +} + +/*****************************************************************************/ + diff --git a/sal/osl/os2/mutex.c b/sal/osl/os2/mutex.c new file mode 100644 index 000000000000..94253e48a89d --- /dev/null +++ b/sal/osl/os2/mutex.c @@ -0,0 +1,170 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: mutex.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <sys/fmutex.h> + +#include "system.h" + +#include <osl/mutex.h> +#include <osl/diagnose.h> + +/* + Implementation notes: + The void* hidden by oslMutex points to an OS/2 mutex semaphore. +*/ +typedef struct _oslMutexImpl { + HMTX m_Mutex; + int m_Locks; + ULONG m_Owner; + ULONG m_Requests; +} oslMutexImpl; + +// static mutex to control access to private members of oslMutexImpl +static HMTX MutexLock = 0; + +/*****************************************************************************/ +/* osl_createMutex */ +/*****************************************************************************/ +oslMutex SAL_CALL osl_createMutex() +{ + oslMutexImpl *pMutexImpl; + HMTX hMutex; + APIRET rc; + + pMutexImpl= (oslMutexImpl*)calloc(sizeof(oslMutexImpl), 1); + OSL_ASSERT(pMutexImpl); /* alloc successful? */ + + /* create semaphore */ + rc = DosCreateMutexSem( NULL, &pMutexImpl->m_Mutex, 0, FALSE ); + if( rc != 0 ) + { + free(pMutexImpl); + return NULL; + } + + // create static mutex for private members + if (MutexLock == 0) + DosCreateMutexSem( NULL, &MutexLock, 0, FALSE ); + + return (oslMutex)pMutexImpl; +} + +/*****************************************************************************/ +/* osl_destroyMutex */ +/*****************************************************************************/ +void SAL_CALL osl_destroyMutex(oslMutex Mutex) +{ + oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; + if (pMutexImpl) + { + DosCloseMutexSem( pMutexImpl->m_Mutex); + free(pMutexImpl); + } +} + +/*****************************************************************************/ +/* osl_acquireMutex */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex) +{ + oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; + APIRET rc = 0; + OSL_ASSERT(Mutex); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + pMutexImpl->m_Requests++; + DosReleaseMutexSem( MutexLock); + + rc = DosRequestMutexSem( pMutexImpl->m_Mutex, SEM_INDEFINITE_WAIT ); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + pMutexImpl->m_Requests--; + if (pMutexImpl->m_Locks++ == 0) + pMutexImpl->m_Owner = _gettid(); + DosReleaseMutexSem( MutexLock); + + return( rc == 0 ); +} + +/*****************************************************************************/ +/* osl_tryToAcquireMutex */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex) +{ + sal_Bool ret = sal_False; + oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; + OSL_ASSERT(Mutex); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + if ( ((pMutexImpl->m_Requests == 0) && (pMutexImpl->m_Locks == 0)) || + (pMutexImpl->m_Owner == _gettid()) ) + ret = osl_acquireMutex(Mutex); + + DosReleaseMutexSem( MutexLock); + + return ret; +} + +/*****************************************************************************/ +/* osl_releaseMutex */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex) +{ + oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex; + APIRET rc; + OSL_ASSERT(Mutex); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + if (--(pMutexImpl->m_Locks) == 0) + pMutexImpl->m_Owner = 0; + + DosReleaseMutexSem( MutexLock); + + rc = DosReleaseMutexSem( pMutexImpl->m_Mutex); + + return sal_True; +} + + + +/*****************************************************************************/ +/* osl_getGlobalMutex */ +/*****************************************************************************/ + +oslMutex g_Mutex = NULL; + +oslMutex * SAL_CALL osl_getGlobalMutex(void) +{ + if (g_Mutex == NULL) + g_Mutex = osl_createMutex(); + return &g_Mutex; +} diff --git a/sal/osl/os2/nlsupport.c b/sal/osl/os2/nlsupport.c new file mode 100644 index 000000000000..0efccaa787e6 --- /dev/null +++ b/sal/osl/os2/nlsupport.c @@ -0,0 +1,463 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: nlsupport.c,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define INCL_WIN +#include "svpm.h" + +#include <osl/nlsupport.h> +#include <osl/diagnose.h> +#include <osl/process.h> +#include <rtl/memory.h> + +#include <string.h> + +/***************************************************************************** + typedefs + *****************************************************************************/ + + +typedef struct { + const char *key; + const rtl_TextEncoding value; +} _pair; + + +/***************************************************************************** + compare function for binary search + *****************************************************************************/ + +static int +_pair_compare (const char *key, const _pair *pair) +{ + int result = rtl_str_compareIgnoreAsciiCase( key, pair->key ); + return result; +} + +/***************************************************************************** + binary search on encoding tables + *****************************************************************************/ + +static const _pair* +_pair_search (const char *key, const _pair *base, unsigned int member ) +{ + unsigned int lower = 0; + unsigned int upper = member; + unsigned int current; + int comparison; + + /* check for validity of input */ + if ( (key == NULL) || (base == NULL) || (member == 0) ) + return NULL; + + /* binary search */ + while ( lower < upper ) + { + current = (lower + upper) / 2; + comparison = _pair_compare( key, base + current ); + if (comparison < 0) + upper = current; + else if (comparison > 0) + lower = current + 1; + else + return base + current; + } + + return NULL; +} + + +/***************************************************************************** + convert rtl_Locale to locale string + *****************************************************************************/ + +static char * _compose_locale( rtl_Locale * pLocale, char * buffer, size_t n ) +{ + /* check if a valid locale is specified */ + if( pLocale && pLocale->Language && (pLocale->Language->length == 2) ) + { + size_t offset = 0; + + /* convert language code to ascii */ + { + rtl_String *pLanguage = NULL; + + rtl_uString2String( &pLanguage, + pLocale->Language->buffer, pLocale->Language->length, + RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); + + if( pLanguage->length < n ) + { + strcpy( buffer, pLanguage->buffer ); + offset = pLanguage->length; + } + + rtl_string_release( pLanguage ); + } + + /* convert country code to ascii */ + if( pLocale->Country && (pLocale->Country->length == 2) ) + { + rtl_String *pCountry = NULL; + + rtl_uString2String( &pCountry, + pLocale->Country->buffer, pLocale->Country->length, + RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); + + if( offset + pCountry->length + 1 < n ) + { + strcpy( buffer + offset++, "_" ); + strcpy( buffer + offset, pCountry->buffer ); + offset += pCountry->length; + } + + rtl_string_release( pCountry ); + } + + /* convert variant to ascii - check if there is enough space for the variant string */ + if( pLocale->Variant && pLocale->Variant->length && + ( pLocale->Variant->length < n - 6 ) ) + { + rtl_String *pVariant = NULL; + + rtl_uString2String( &pVariant, + pLocale->Variant->buffer, pLocale->Variant->length, + RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); + + if( offset + pVariant->length + 1 < n ) + { + strcpy( buffer + offset, pVariant->buffer ); + offset += pVariant->length; + } + + rtl_string_release( pVariant ); + } + + return buffer; + } + + return NULL; +} + +/***************************************************************************** + convert locale string to rtl_Locale + *****************************************************************************/ + +static rtl_Locale * _parse_locale( const char * locale ) +{ + static sal_Unicode c_locale[2] = { (sal_Unicode) 'C', 0 }; + + /* check if locale contains a valid string */ + if( locale ) + { + size_t len = strlen( locale ); + + if( len >= 2 ) + { + rtl_uString * pLanguage = NULL; + rtl_uString * pCountry = NULL; + rtl_uString * pVariant = NULL; + + size_t offset = 2; + + /* convert language code to unicode */ + rtl_string2UString( &pLanguage, locale, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(pLanguage != NULL); + + /* convert country code to unicode */ + if( len >= 5 && '_' == locale[2] ) + { + rtl_string2UString( &pCountry, locale + 3, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(pCountry != NULL); + offset = 5; + } + + /* convert variant code to unicode - do not rely on "." as delimiter */ + if( len > offset ) { + rtl_string2UString( &pVariant, locale + offset, len - offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(pVariant != NULL); + } + + rtl_Locale * ret = rtl_locale_register( pLanguage->buffer, pCountry ? pCountry->buffer : c_locale + 1, pVariant ? pVariant->buffer : c_locale + 1 ); + + if (pVariant) rtl_uString_release(pVariant); + if (pCountry) rtl_uString_release(pCountry); + if (pLanguage) rtl_uString_release(pLanguage); + + return ret; + } + else + return rtl_locale_register( c_locale, c_locale + 1, c_locale + 1 ); + } + + return NULL; +} + +/* + * This implementation of osl_getTextEncodingFromLocale maps + * from the ISO language codes. + */ + +const _pair _full_locale_list[] = { + { "ja_JP.eucJP", RTL_TEXTENCODING_EUC_JP }, + { "ja_JP.EUC", RTL_TEXTENCODING_EUC_JP }, + { "ko_KR.EUC", RTL_TEXTENCODING_EUC_KR }, + { "zh_CN.EUC", RTL_TEXTENCODING_EUC_CN }, + { "zh_TW.EUC", RTL_TEXTENCODING_EUC_TW } +}; + +const _pair _locale_extension_list[] = { + { "big5", RTL_TEXTENCODING_BIG5 }, + { "big5hk", RTL_TEXTENCODING_BIG5_HKSCS }, + { "gb18030", RTL_TEXTENCODING_GB_18030 }, + { "euc", RTL_TEXTENCODING_EUC_JP }, + { "iso8859-1", RTL_TEXTENCODING_ISO_8859_1 }, + { "iso8859-10", RTL_TEXTENCODING_ISO_8859_10 }, + { "iso8859-13", RTL_TEXTENCODING_ISO_8859_13 }, + { "iso8859-14", RTL_TEXTENCODING_ISO_8859_14 }, + { "iso8859-15", RTL_TEXTENCODING_ISO_8859_15 }, + { "iso8859-2", RTL_TEXTENCODING_ISO_8859_2 }, + { "iso8859-3", RTL_TEXTENCODING_ISO_8859_3 }, + { "iso8859-4", RTL_TEXTENCODING_ISO_8859_4 }, + { "iso8859-5", RTL_TEXTENCODING_ISO_8859_5 }, + { "iso8859-6", RTL_TEXTENCODING_ISO_8859_6 }, + { "iso8859-7", RTL_TEXTENCODING_ISO_8859_7 }, + { "iso8859-8", RTL_TEXTENCODING_ISO_8859_8 }, + { "iso8859-9", RTL_TEXTENCODING_ISO_8859_9 }, + { "koi8-r", RTL_TEXTENCODING_KOI8_R }, + { "koi8-u", RTL_TEXTENCODING_KOI8_U }, + { "pck", RTL_TEXTENCODING_MS_932 }, +#if (0) + { "sun_eu_greek", RTL_TEXTENCODING_DONTKNOW }, +#endif + { "utf-16", RTL_TEXTENCODING_UNICODE }, + { "utf-7", RTL_TEXTENCODING_UTF7 }, + { "utf-8", RTL_TEXTENCODING_UTF8 } +}; + +const _pair _iso_language_list[] = { + { "af", RTL_TEXTENCODING_ISO_8859_1 }, + { "ar", RTL_TEXTENCODING_ISO_8859_6 }, + { "az", RTL_TEXTENCODING_ISO_8859_9 }, + { "be", RTL_TEXTENCODING_ISO_8859_5 }, + { "bg", RTL_TEXTENCODING_ISO_8859_5 }, + { "ca", RTL_TEXTENCODING_ISO_8859_1 }, + { "cs", RTL_TEXTENCODING_ISO_8859_2 }, + { "da", RTL_TEXTENCODING_ISO_8859_1 }, + { "de", RTL_TEXTENCODING_ISO_8859_1 }, + { "el", RTL_TEXTENCODING_ISO_8859_7 }, + { "en", RTL_TEXTENCODING_ISO_8859_1 }, + { "es", RTL_TEXTENCODING_ISO_8859_1 }, + { "et", RTL_TEXTENCODING_ISO_8859_4 }, + { "eu", RTL_TEXTENCODING_ISO_8859_1 }, + { "fa", RTL_TEXTENCODING_ISO_8859_6 }, + { "fi", RTL_TEXTENCODING_ISO_8859_1 }, + { "fo", RTL_TEXTENCODING_ISO_8859_1 }, + { "fr", RTL_TEXTENCODING_ISO_8859_1 }, + { "gr", RTL_TEXTENCODING_ISO_8859_7 }, + { "he", RTL_TEXTENCODING_ISO_8859_8 }, + { "hi", RTL_TEXTENCODING_DONTKNOW }, + { "hr", RTL_TEXTENCODING_ISO_8859_2 }, + { "hu", RTL_TEXTENCODING_ISO_8859_2 }, + { "hy", RTL_TEXTENCODING_DONTKNOW }, + { "id", RTL_TEXTENCODING_ISO_8859_1 }, + { "is", RTL_TEXTENCODING_ISO_8859_1 }, + { "it", RTL_TEXTENCODING_ISO_8859_1 }, + { "iw", RTL_TEXTENCODING_ISO_8859_8 }, + { "ja", RTL_TEXTENCODING_EUC_JP }, + { "ka", RTL_TEXTENCODING_DONTKNOW }, + { "kk", RTL_TEXTENCODING_ISO_8859_5 }, + { "ko", RTL_TEXTENCODING_EUC_KR }, + { "lt", RTL_TEXTENCODING_ISO_8859_4 }, + { "lv", RTL_TEXTENCODING_ISO_8859_4 }, + { "mk", RTL_TEXTENCODING_ISO_8859_5 }, + { "mr", RTL_TEXTENCODING_DONTKNOW }, + { "ms", RTL_TEXTENCODING_ISO_8859_1 }, + { "nl", RTL_TEXTENCODING_ISO_8859_1 }, + { "no", RTL_TEXTENCODING_ISO_8859_1 }, + { "pl", RTL_TEXTENCODING_ISO_8859_2 }, + { "pt", RTL_TEXTENCODING_ISO_8859_1 }, + { "ro", RTL_TEXTENCODING_ISO_8859_2 }, + { "ru", RTL_TEXTENCODING_ISO_8859_5 }, + { "sa", RTL_TEXTENCODING_DONTKNOW }, + { "sk", RTL_TEXTENCODING_ISO_8859_2 }, + { "sl", RTL_TEXTENCODING_ISO_8859_2 }, + { "sq", RTL_TEXTENCODING_ISO_8859_2 }, + { "sv", RTL_TEXTENCODING_ISO_8859_1 }, + { "sw", RTL_TEXTENCODING_ISO_8859_1 }, + { "ta", RTL_TEXTENCODING_DONTKNOW }, + { "th", RTL_TEXTENCODING_DONTKNOW }, + { "tr", RTL_TEXTENCODING_ISO_8859_9 }, + { "tt", RTL_TEXTENCODING_ISO_8859_5 }, + { "uk", RTL_TEXTENCODING_ISO_8859_5 }, + { "ur", RTL_TEXTENCODING_ISO_8859_6 }, + { "uz", RTL_TEXTENCODING_ISO_8859_9 }, + { "vi", RTL_TEXTENCODING_DONTKNOW }, + { "zh", RTL_TEXTENCODING_BIG5 } +}; + +/***************************************************************************** + return the text encoding corresponding to the given locale + *****************************************************************************/ + +rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale ) +{ + const _pair *language = 0; + char locale_buf[64] = ""; + char *cp; + + WinMessageBox(HWND_DESKTOP,HWND_DESKTOP, + "Please contact technical support and report above informations.\n\n", + "Critical error: osl_getTextEncodingFromLocale", + 0, MB_ERROR | MB_OK | MB_MOVEABLE); + + /* default to process locale if pLocale == NULL */ + if( NULL == pLocale ) + osl_getProcessLocale( &pLocale ); + + /* convert rtl_Locale to locale string */ + if( _compose_locale( pLocale, locale_buf, 64 ) ) + { + /* check special handling list (EUC) first */ + const unsigned int members = sizeof( _full_locale_list ) / sizeof( _pair ); + language = _pair_search( locale_buf, _full_locale_list, members); + + if( NULL == language ) + { + /* + * check if there is a charset qualifier at the end of the given locale string + * e.g. de.ISO8859-15 or de.ISO8859-15@euro which strongly indicates what + * charset to use + */ + cp = strrchr( locale_buf, '.' ); + + if( NULL != cp ) + { + const unsigned int members = sizeof( _locale_extension_list ) / sizeof( _pair ); + language = _pair_search( cp + 1, _locale_extension_list, members); + } + } + + /* use iso language code to determine the charset */ + if( NULL == language ) + { + const unsigned int members = sizeof( _iso_language_list ) / sizeof( _pair ); + + /* iso lang codes have 2 charaters */ + locale_buf[2] = '\0'; + + language = _pair_search( locale_buf, _iso_language_list, members); + } + } + + /* a matching item in our list provides a mapping from codeset to + * rtl-codeset */ + if ( language != NULL ) + return language->value; + + return RTL_TEXTENCODING_DONTKNOW; +} + +/***************************************************************************** + return the current process locale + *****************************************************************************/ + +void _imp_getProcessLocale( rtl_Locale ** ppLocale ) +{ + /* simulate behavior off setlocale */ + char * locale = getenv( "LC_ALL" ); + + if( NULL == locale ) + locale = getenv( "LC_CTYPE" ); + + if( NULL == locale ) + locale = getenv( "LANG" ); + + if( NULL == locale ) + locale = "C"; + + *ppLocale = _parse_locale( locale ); +} + +/***************************************************************************** + set the current process locale + *****************************************************************************/ + +int _imp_setProcessLocale( rtl_Locale * pLocale ) +{ +#ifdef IRIX + char env_buf[80]; +#endif + 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( IRIX ) + snprintf(env_buf, sizeof(env_buf), "LC_ALL=%s", locale_buf); + env_buf[sizeof(env_buf)] = '\0'; + putenv(env_buf); +#elif defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ ) + setenv( "LC_ALL", locale_buf, 1); +#else + setenv( "LC_ALL", locale_buf ); +#endif + } + + if( getenv( "LC_CTYPE" ) ) { +#if defined( IRIX ) + snprintf(env_buf, sizeof(env_buf), "LC_CTYPE=%s", locale_buf); + env_buf[sizeof(env_buf)] = '\0'; + putenv(env_buf); +#elif defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ ) + setenv("LC_CTYPE", locale_buf, 1 ); +#else + setenv( "LC_CTYPE", locale_buf ); +#endif + } + + if( getenv( "LANG" ) ) { +#if defined( IRIX ) + snprintf(env_buf, sizeof(env_buf), "LANG=%s", locale_buf); + env_buf[sizeof(env_buf)] = '\0'; + putenv(env_buf); +#elif defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ ) + setenv("LC_CTYPE", locale_buf, 1 ); +#else + setenv( "LANG", locale_buf ); +#endif + } + } + + return 0; +} + + diff --git a/sal/osl/os2/path_helper.cxx b/sal/osl/os2/path_helper.cxx new file mode 100644 index 000000000000..fbf249fc1ece --- /dev/null +++ b/sal/osl/os2/path_helper.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: path_helper.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/******************************************************************* + Includes + ******************************************************************/ + +#include "path_helper.hxx" +#include <osl/diagnose.h> +#include <rtl/ustring.hxx> + +#include <algorithm> +#include <wchar.h> +#include <wctype.h> + +/******************************************************************* + Constants + ******************************************************************/ + +const rtl::OUString BACKSLASH = rtl::OUString::createFromAscii("\\"); +const rtl::OUString SLASH = rtl::OUString::createFromAscii("/"); + +/******************************************************************* + osl_systemPathEnsureSeparator + ******************************************************************/ + +void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath) +{ + OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \ + "osl_systemPathEnsureSeparator: Invalid parameter"); + + rtl::OUString path(*ppustrPath); + sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH)); + + if (i < (path.getLength()-1)) + { + path += BACKSLASH; + rtl_uString_assign(ppustrPath, path.pData); + } + + OSL_POSTCOND(path.lastIndexOf(BACKSLASH) == (path.getLength() - 1), \ + "osl_systemPathEnsureSeparator: Post condition failed"); +} + +/******************************************************************* + osl_systemPathRemoveSeparator + ******************************************************************/ + +void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath) +{ + rtl::OUString path(*ppustrPath); + + if (!osl::systemPathIsLogicalDrivePattern(path)) + { + sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH)); + + if (i > -1 && (i == (path.getLength() - 1))) + { + path = rtl::OUString(path.getStr(), path.getLength() - 1); + rtl_uString_assign(ppustrPath, path.pData); + } + } +} + +/******************************************************************* + osl_is_logical_drive_pattern + ******************************************************************/ + +// is [A-Za-z]:[/|\]\0 +const sal_Unicode* LDP = L":"; +const sal_Unicode* LDP_WITH_BACKSLASH = L":\\"; +const sal_Unicode* LDP_WITH_SLASH = L":/"; + +// degenerated case returned by the Windows FileOpen dialog +// when someone enters for instance "x:filename", the Win32 +// API accepts this case +const sal_Unicode* LDP_WITH_DOT_BACKSLASH = L":.\\"; + +sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath) +{ + const sal_Unicode* p = rtl_uString_getStr(const_cast<rtl_uString*>(pustrPath)); + if (iswalpha(*p++)) + { + return ((0 == wcscmp(p, LDP)) || + (0 == wcscmp(p, LDP_WITH_BACKSLASH)) || + (0 == wcscmp(p, LDP_WITH_SLASH)) || + (0 == wcscmp(p, LDP_WITH_DOT_BACKSLASH))); + } + return 0; +} + + diff --git a/sal/osl/os2/path_helper.h b/sal/osl/os2/path_helper.h new file mode 100644 index 000000000000..de833df30ef8 --- /dev/null +++ b/sal/osl/os2/path_helper.h @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: path_helper.h,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PATH_HELPER_H_ +#define _PATH_HELPER_H_ + +#include <sal/types.h> +#include <rtl/ustring.h> +#include <osl/file.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/******************************************************************* + osl_systemPathEnsureSeparator + Adds a trailing path separator to the given system path if not + already there and if the path is not the root path or a logical + drive alone + ******************************************************************/ + +void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath); + +/******************************************************************* + osl_systemPathRemoveSeparator + Removes the last separator from the given system path if any and + if the path is not the root path '\' + ******************************************************************/ + +void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath); + +/******************************************************************* + osl_is_logical_drive_pattern + Returns whether a given path is only a logical drive pattern or not. + A logical drive pattern is something like "a:\", "c:\". + No logical drive pattern is something like "c:\test" + ******************************************************************/ + +sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sal/osl/os2/path_helper.hxx b/sal/osl/os2/path_helper.hxx new file mode 100644 index 000000000000..6ba7d09f5af1 --- /dev/null +++ b/sal/osl/os2/path_helper.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: path_helper.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// YD #pragma warning (disable : 4800) + +#ifndef _PATH_HELPER_HXX_ +#define _PATH_HELPER_HXX_ + +#include "path_helper.h" +#include <rtl/ustring.hxx> + +namespace osl +{ + +/******************************************************************* + osl_systemPathEnsureSeparator + Adds a trailing path separator to the given system path if not + already there and if the path is not the root path or a logical + drive alone + ******************************************************************/ + +inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path) +{ + osl_systemPathEnsureSeparator(&Path.pData); +} + +/******************************************************************* + osl_systemPathRemoveSeparator + Removes the last separator from the given system path if any and + if the path is not the root path '\' + ******************************************************************/ + +inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path) +{ + osl_systemPathRemoveSeparator(&Path.pData); +} + +/******************************************************************* + osl_systemPathIsLogicalDrivePattern + ******************************************************************/ + +inline bool systemPathIsLogicalDrivePattern(/*in*/ const rtl::OUString& path) +{ + return osl_systemPathIsLogicalDrivePattern(path.pData); +} + +} // end namespace osl + +#endif diff --git a/sal/osl/os2/pipe.cxx b/sal/osl/os2/pipe.cxx new file mode 100644 index 000000000000..0d72855df272 --- /dev/null +++ b/sal/osl/os2/pipe.cxx @@ -0,0 +1,558 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pipe.cxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +//#define INCL_DOSERRORS +#include "system.h" + +#include <osl/pipe.h> +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <osl/mutex.h> +#include <osl/semaphor.h> +#include <osl/conditn.h> +#include <osl/interlck.h> +#include <osl/process.h> +#include <rtl/ustring.hxx> + +#define PIPENAMEMASK "OSL_PIPE_%s" +#define SECPIPENAMEMASK "OSL_PIPE_%s_%s" + +typedef enum { + MSG_SYN, + MSG_FIN, + MSG_DATA, + MSG_UNKNOWN +} MessageType; + +struct oslPipeImpl { + oslInterlockedCount m_Reference; + HPIPE hPipe; + HMTX m_NamedObject; + APIRET nLastError; + //oslSecurity m_Security; + sal_Bool m_bClosed; +}; + +/* default size for input/output buffer */ +static const ULONG ulBufSize = 4096; + +/* OS/2 path for pipes */ +static const CHAR pszPipePath[] = "\\PIPE\\"; +static const UCHAR nPipePathLen = sizeof (pszPipePath) - 1; + +/* global last error value to be returned from oslGetLastPipeError */ +static APIRET ngLastError; + +using rtl::OString; +using rtl::OUString; +using rtl::OUStringToOString; + +/*****************************************************************************/ +/* osl_create/destroy-PipeImpl */ +/*****************************************************************************/ + +static oslInterlockedCount nPipes = 0; + +oslPipe __osl_createPipeImpl(void) +{ + oslPipe pPipe; + + pPipe = (oslPipe) calloc(1,sizeof(struct oslPipeImpl)); + + pPipe->m_bClosed = sal_False; + pPipe->m_Reference = 1; + pPipe->hPipe = NULL; + pPipe->m_NamedObject = NULL; + + return pPipe; +} + +void __osl_destroyPipeImpl(oslPipe pPipe) +{ + if (pPipe != NULL) + { + DosCloseMutexSem( pPipe->m_NamedObject); + free(pPipe); + } +} + + +/*****************************************************************************/ +/* osl_createPipe */ +/*****************************************************************************/ +oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, + oslSecurity Security) +{ + oslPipe pPipe; + + ULONG ulAction; + CHAR strPipeNameBuffer [CCHMAXPATHCOMP]; + rtl_String* strPipeName=0; + sal_Char* pszPipeName=0; + + /* check parameters */ + OSL_ASSERT( ustrPipeName ); + //YD 17/04/06 OSL_ASSERT( Security == 0 ); + + /* allocate impl-structure */ + pPipe = __osl_createPipeImpl(); + if (!pPipe) + { + OSL_TRACE( "osl_createPipe failed allocating memory.\n" ); + return NULL; + } + + /* create pipe name */ + OString sPipe = OUStringToOString(ustrPipeName, RTL_TEXTENCODING_ASCII_US); +#if OSL_DEBUG_LEVEL>0 + debug_printf("osl_createPipe options 0x%x\n", Options); +#endif + + switch( Options ) + { + case osl_Pipe_OPEN: + { + APIRET fPipeAvailable; + + sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr()); +#if OSL_DEBUG_LEVEL>0 + debug_printf("osl_createPipe %s\n", strPipeNameBuffer); +#endif + ngLastError = DosOpen( (PCSZ)strPipeNameBuffer, + &(pPipe->hPipe), &ulAction, + 0, FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, + (PEAOP2) NULL); + // if pipe is busy, wait for it + if (ngLastError == ERROR_PIPE_BUSY) + do + { + /* free instance should be available first */ + fPipeAvailable = DosWaitNPipe( (PCSZ)strPipeNameBuffer, -1); + /* first try to open system pipe */ + if ( fPipeAvailable == NO_ERROR ) + { + // We got it ! + ngLastError = NO_ERROR; + break; + } + // Pipe instance maybe catched by another client -> try again + printf("osl_createPipe wait for Pipe available\n"); + } while ( fPipeAvailable ); + } + break; + case osl_Pipe_CREATE: + { + sprintf (strPipeNameBuffer, "\\SEM32\\OSL_SEM_%s", sPipe.getStr()); + // check if semaphore exists (pipe create must fail for existig pipes) + ngLastError = DosCreateMutexSem( (PCSZ)strPipeNameBuffer, &(pPipe->m_NamedObject), 0, TRUE ); + if (ngLastError) + break; + + sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr()); +#if OSL_DEBUG_LEVEL>0 + debug_printf("osl_createPipe %s\n", strPipeNameBuffer); +#endif + ngLastError = DosCreateNPipe( (PCSZ)strPipeNameBuffer, + &(pPipe->hPipe), + NP_ACCESS_DUPLEX, /* open pipe for read and write access */ + 0xFF, /* allow unlimited number of instances */ + ulBufSize, /* output buffer size */ + ulBufSize, /* input buffer size */ + 0L /* use default time-out time */ + ); + } + break; + default: + ngLastError = ERROR_INVALID_PARAMETER; + } + + /* if failed, release allocated memory */ + if (ngLastError) + { + OSL_TRACE( "osl_createPipe failed %s the pipe %s, Error Code %d.\n", + Options == osl_Pipe_OPEN ? "opening" : "creating", + strPipeNameBuffer, + ngLastError ); + __osl_destroyPipeImpl(pPipe); + return NULL; + } + + pPipe->m_Reference= 1; + pPipe->m_bClosed = sal_False; + //pPipe->m_Security = Security; + pPipe->nLastError = NO_ERROR; + return (oslPipe)pPipe; +} + +/*****************************************************************************/ +/* osl_copyPipe */ +/*****************************************************************************/ +oslPipe SAL_CALL osl_copyPipe(oslPipe pPipe) +{ + //oslPipe* pPipe = (oslPipe*) Pipe; + oslPipe pNewPipe; + + + /* check parameter */ + OSL_ASSERT (pPipe); + + /* allocate impl-structure */ + pNewPipe = __osl_createPipeImpl(); + if (!pNewPipe) return NULL; + + /* create new handle */ + pNewPipe->hPipe = (HPIPE) -1; + ngLastError = DosDupHandle( pPipe->hPipe, &(pNewPipe->hPipe) ); + + /* if failed, release allocated memory */ + if (ngLastError) + { + OSL_TRACE( "osl_copyPipe failed duplicating pipe handle, Error-Code: %d.\n", + ngLastError ); + free (pNewPipe); + return NULL; + } + + pNewPipe->nLastError = NO_ERROR; + return (oslPipe)pNewPipe; +} + +void SAL_CALL osl_acquirePipe( oslPipe pPipe ) +{ + osl_incrementInterlockedCount( &(pPipe->m_Reference) ); +} + +void SAL_CALL osl_releasePipe( oslPipe pPipe ) +{ +// OSL_ASSERT( pPipe ); + + if( 0 == pPipe ) + return; + + if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) ) + { + if( ! pPipe->m_bClosed ) + osl_closePipe( pPipe ); + + __osl_destroyPipeImpl( pPipe ); + } +} + +/*****************************************************************************/ +/* osl_destroyPipe */ +/*************close****************************************************************/ +void SAL_CALL osl_closePipe(oslPipe pPipe) +{ + //oslPipe* pPipe = (oslPipe*) Pipe; + /* check parameter */ + OSL_ASSERT (pPipe); + + if( pPipe && ! pPipe->m_bClosed ) + { + pPipe->m_bClosed = sal_True; + /* if we have a system pipe close it */ + if (pPipe->hPipe != 0) + { + /* disconnect client */ + DosDisConnectNPipe (pPipe->hPipe); + + /* close the pipe */ + DosClose (pPipe->hPipe); + } + } +} + +/*****************************************************************************/ +/* osl_acceptPipe */ +/*****************************************************************************/ +oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) +{ + +#define PINFO ((PIPEINFO *) &PipeInfoBuffer) + + ///oslPipe* pPipe = (oslPipe*) Pipe; + oslPipe pNewPipe; + BYTE PipeInfoBuffer[sizeof(PIPEINFO) + CCHMAXPATHCOMP]; + + /* check parameter */ + OSL_ASSERT (pPipe); + + /* get pipe information */ + pPipe->nLastError = DosQueryNPipeInfo(pPipe->hPipe, + 1, + (PVOID) &PipeInfoBuffer, + sizeof(PipeInfoBuffer)); + + if (pPipe->nLastError) + { + OSL_TRACE( "osl_acceptPipe failed for requesting pipe information.\n", + pPipe->nLastError ); + return NULL; + } + + /* create a new instance of the pipe if possible */ + if (PINFO->cbMaxInst == -1 || /* unlimited instances */ + PINFO->cbMaxInst > PINFO->cbCurInst) + { + HPIPE hPipe; + + pNewPipe = __osl_createPipeImpl(); + + if (!pNewPipe) + { + OSL_TRACE( "osl_acceptPipe failed creating new instance.\n", ngLastError ); + free(pNewPipe); + return NULL; + } + + //pNewPipe->m_Security = pPipe->m_Security; + + pNewPipe->nLastError = + DosCreateNPipe( (PCSZ)PINFO->szName, + &(pNewPipe->hPipe), + NP_ACCESS_DUPLEX, /* open pipe for read and write access */ + 0xFF, /* allow unlimited number of instances */ + ulBufSize, /* output buffer size */ + ulBufSize, /* input buffer size */ + 0L /* use default time-out time */ + ); + + if (pNewPipe->nLastError) + { + OSL_TRACE( "osl_acceptPipe failed creating new named pipe, Error-Code: %d.\n", + pNewPipe->nLastError ); + free(pNewPipe); + return NULL; + } + + /* switch pipe handles */ + hPipe = pPipe->hPipe; + pPipe->hPipe = pNewPipe->hPipe; + pNewPipe->hPipe = hPipe; + + /* connect new handle to client */ + pNewPipe->nLastError = DosConnectNPipe( pNewPipe->hPipe ); + + /* if failed, release allocated memory */ + if (pNewPipe->nLastError) + { + OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n", + pNewPipe->nLastError ); + + osl_closePipe((oslPipe)pNewPipe); + return NULL; + } + return (oslPipe)pNewPipe; + } + else + { + /* connect original handle to client */ + pPipe->nLastError = DosConnectNPipe( pPipe->hPipe ); + + if (pPipe->nLastError) + { + OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n", + pPipe->nLastError ); + return NULL; + } + + return (oslPipe)pPipe; + } +} + +/*****************************************************************************/ +/* osl_receivePipe */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe, + void* pBuffer, + sal_Int32 BytesToRead) +{ + //oslPipe* pPipe = (oslPipe*) Pipe; + ULONG ulActual; + + /* check parameter */ + OSL_ASSERT (pPipe); + + /* read data from pipe */ + pPipe->nLastError = DosRead( pPipe->hPipe, pBuffer, BytesToRead, &ulActual ); + + /* return -1 if failed */ + if( pPipe->nLastError ) + { + OSL_TRACE( "osl_receivePipe failed receiving from Pipe, Error-Code: %d.\n", + pPipe->nLastError ); + return -1; + } + + return ulActual; +} + + +/*****************************************************************************/ +/* osl_sendPipe */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, + const void* pBuffer, + sal_Int32 BytesToSend) +{ + //oslPipe* pPipe = (oslPipe*) Pipe; + ULONG ulActual; + + /* check parameter */ + OSL_ASSERT (pPipe); + + /* read data from pipe */ + pPipe->nLastError = DosWrite( pPipe->hPipe, (PVOID) pBuffer, BytesToSend, &ulActual ); + + /* return -1 if failed */ + if( pPipe->nLastError ) + { + OSL_TRACE( "osl_receivePipe failed writing to Pipe, Error-Code: %d.\n", + pPipe->nLastError ); + return -1; + } + + return ulActual; +} + + +/*****************************************************************************/ +/* osl_getLastPipeError */ +/*****************************************************************************/ + +oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) +{ + //oslPipe* pPipe = (oslPipe*) Pipe; + APIRET rc; + + /* return local error value if possible */ + if (pPipe) + { + rc = pPipe->nLastError; + pPipe->nLastError = NO_ERROR; + } else + rc = ngLastError; + + /* map OS/2 error values */ + switch (rc) + { + case NO_ERROR: return osl_Pipe_E_None; + case ERROR_PATH_NOT_FOUND: return osl_Pipe_E_NotFound; + case ERROR_NOT_ENOUGH_MEMORY: return osl_Pipe_E_NoBufferSpace; + default: return osl_Pipe_E_invalidError; + } +} + +/*****************************************************************************/ + +sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n ) +{ + /* loop until all desired bytes were send or an error occured */ + sal_Int32 BytesSend= 0; + sal_Int32 BytesToSend= n; + + OSL_ASSERT(pPipe); + while (BytesToSend > 0) + { + sal_Int32 RetVal; + + RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend); + + /* error occured? */ + if(RetVal <= 0) + { + break; + } + + BytesToSend -= RetVal; + BytesSend += RetVal; + pBuffer= (sal_Char*)pBuffer + RetVal; + } + + return BytesSend; +} + +sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n ) +{ + /* loop until all desired bytes were read or an error occured */ + sal_Int32 BytesRead= 0; + sal_Int32 BytesToRead= n; + + OSL_ASSERT( pPipe ); + while (BytesToRead > 0) + { + sal_Int32 RetVal; + RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead); + + /* error occured? */ + if(RetVal <= 0) + { + break; + } + + BytesToRead -= RetVal; + BytesRead += RetVal; + pBuffer= (sal_Char*)pBuffer + RetVal; + } + return BytesRead; +} + + +/****************************************************************************** + * + * New io resource transfer functions + * + *****************************************************************************/ + + +/********************************************** + osl_sendResourcePipe + *********************************************/ + +sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket) +{ + sal_Bool bRet = sal_False; + + return bRet; +} + +/********************************************** + osl_receiveResourcePipe + *********************************************/ + +oslSocket osl_receiveResourcePipe(oslPipe pPipe) +{ + oslSocket pSocket=0; + + return (oslSocket) pSocket; +} + + diff --git a/sal/osl/os2/pipeimpl.cxx b/sal/osl/os2/pipeimpl.cxx new file mode 100644 index 000000000000..d08a370c428c --- /dev/null +++ b/sal/osl/os2/pipeimpl.cxx @@ -0,0 +1,755 @@ +# include "pipeimpl.h" + +#ifndef _INC_MALLOC +# include <malloc.h> +#endif + +#ifndef _INC_TCHAR +# ifdef UNICODE +# define _UNICODE +# endif +# include <tchar.h> +#endif + +const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_"); +const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_"); +const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_"); + +const DWORD PIPE_BUFFER_SIZE = 4096; + + +//============================================================================ +// PipeData +//============================================================================ + +struct PipeData +{ + DWORD dwProcessId; + HANDLE hReadPipe; + HANDLE hWritePipe; +}; + +//============================================================================ +// Pipe +//============================================================================ + +#ifdef UNICODE +#define Pipe PipeW +#define ClientPipe ClientPipeW +#define ServerPipe ServerPipeW +#else +#define Pipe PipeA +#define ClientPipe ClientPipeA +#define ServerPipe ServerPipeA +#endif + +class Pipe +{ +protected: + HANDLE m_hReadPipe; // Handle to use for reading + HANDLE m_hWritePipe; // Handle to use for writing + + Pipe( HANDLE hReadPipe, HANDLE hWritePipe ); + + static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner ); + static HANDLE CreatePipeDataMapping( LPCTSTR lpName ); + static HANDLE OpenPipeDataMapping( LPCTSTR lpName ); + static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount ); + +public: + Pipe( const Pipe& ); + const Pipe& operator = ( const Pipe& ); + virtual ~Pipe(); + + virtual bool Close(); + virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true ); + virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true ); + + virtual Pipe *AcceptConnection() + { + SetLastError( ERROR_INVALID_HANDLE ); + return NULL; + } + + void * operator new( size_t nBytes ) + { + return HeapAlloc( GetProcessHeap(), 0, nBytes ); + } + + void operator delete( void *ptr ) + { + HeapFree( GetProcessHeap(), 0, ptr ); + } + + bool is() const + { + return (FALSE != HeapValidate( GetProcessHeap(), 0, this )); + } + +}; + +//============================================================================ +// ClientPipe +//============================================================================ + +class ClientPipe : public Pipe +{ +protected: + ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ); +public: + static ClientPipe* Create( LPCTSTR lpName ); +}; + +//============================================================================ +// ServerPipe +//============================================================================ + +class ServerPipe : public Pipe +{ +protected: + HANDLE m_hMapping; + HANDLE m_hSynchronize; + LPTSTR m_lpName; + + ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ); +public: + virtual ~ServerPipe(); + + static ServerPipe *Create( LPCTSTR lpName ); + + virtual Pipe *AcceptConnection(); +}; + +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- + +HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName ) +{ + HANDLE hMapping = NULL; + LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) ); + + if ( lpMappingName ) + { + _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING ); + _tcscat( lpMappingName, lpName ); + + LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) ); + + if ( lpMappingFileName ) + { + DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName ); + + if ( MAX_PATH + _tcslen(lpName) < nChars + 1 ) + { + lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) ); + if ( lpMappingFileName ) + nChars = GetTempPath( nChars, lpMappingFileName ); + else + { + nChars = 0; + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + } + } + + if ( nChars ) + { + _tcscat( lpMappingFileName, lpMappingName ); + + HANDLE hFile = CreateFile( + lpMappingFileName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL ); + + if ( IsValidHandle(hFile) ) + { + hMapping = CreateFileMapping( + (HANDLE)hFile, + (LPSECURITY_ATTRIBUTES)NULL, + PAGE_READWRITE, + 0, + sizeof(PipeData), + lpMappingName ); + + CloseHandle( hFile ); + } + } + } + else + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + } + + return hMapping; +} + +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- + +HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName ) +{ + HANDLE hMapping = NULL; + LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) ); + + if ( lpMappingName ) + { + _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING ); + _tcscat( lpMappingName, lpName ); + + hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName ); + } + + return hMapping; +} + +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- + +HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner ) +{ + HANDLE hMutex = NULL; + LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) ); + + if ( lpMutexName ) + { + _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE ); + _tcscat( lpMutexName, lpName ); + + hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName ); + } + + return hMutex; +} + +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- + +HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount ) +{ + HANDLE hSemaphore = NULL; + LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) ); + + if ( lpSemaphoreName ) + { + _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION ); + _tcscat( lpSemaphoreName, lpName ); + + hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName ); + } + + return hSemaphore; +} + + +//---------------------------------------------------------------------------- +// Pipe copy ctor +//---------------------------------------------------------------------------- + +Pipe::Pipe( const Pipe& rPipe ) : +m_hReadPipe( INVALID_HANDLE_VALUE ), +m_hWritePipe( INVALID_HANDLE_VALUE ) +{ + DuplicateHandle( + GetCurrentProcess(), + rPipe.m_hReadPipe, + GetCurrentProcess(), + &m_hReadPipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + DuplicateHandle( + GetCurrentProcess(), + rPipe.m_hWritePipe, + GetCurrentProcess(), + &m_hWritePipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); +} + +//---------------------------------------------------------------------------- +// Pipe assignment operator +//---------------------------------------------------------------------------- + +const Pipe& Pipe::operator = ( const Pipe& rPipe ) +{ + Close(); + + DuplicateHandle( + GetCurrentProcess(), + rPipe.m_hReadPipe, + GetCurrentProcess(), + &m_hReadPipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + DuplicateHandle( + GetCurrentProcess(), + rPipe.m_hWritePipe, + GetCurrentProcess(), + &m_hWritePipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + return *this; +} + +//---------------------------------------------------------------------------- +// Pipe ctor +//---------------------------------------------------------------------------- + +Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) : +m_hReadPipe( INVALID_HANDLE_VALUE ), +m_hWritePipe( INVALID_HANDLE_VALUE ) +{ + DuplicateHandle( + GetCurrentProcess(), + hReadPipe, + GetCurrentProcess(), + &m_hReadPipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + DuplicateHandle( + GetCurrentProcess(), + hWritePipe, + GetCurrentProcess(), + &m_hWritePipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); +} + +//---------------------------------------------------------------------------- +// Pipe dtor +//---------------------------------------------------------------------------- + +Pipe::~Pipe() +{ + Close(); +} + +//---------------------------------------------------------------------------- +// Pipe Close +//---------------------------------------------------------------------------- + +bool Pipe::Close() +{ + bool fSuccess = false; // Assume failure + + if ( IsValidHandle(m_hReadPipe) ) + { + CloseHandle( m_hReadPipe ); + m_hReadPipe = INVALID_HANDLE_VALUE; + } + + if ( IsValidHandle(m_hWritePipe) ) + { + CloseHandle( m_hWritePipe ); + m_hWritePipe = INVALID_HANDLE_VALUE; + } + + return fSuccess; +} + +//---------------------------------------------------------------------------- +// Pipe Write +//---------------------------------------------------------------------------- + +bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait ) +{ + DWORD dwBytesAvailable = 0; + BOOL fSuccess = TRUE; + + if ( !bWait ) + fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL ); + + if ( fSuccess ) + { + if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable ) + dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ; + + return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL ); + } + + return false; +} + +//---------------------------------------------------------------------------- +// Pipe Read +//---------------------------------------------------------------------------- + +bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait ) +{ + DWORD dwBytesAvailable = 0; + BOOL fSuccess = TRUE; + + if ( !bWait ) + fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL ); + + if ( fSuccess ) + { + if ( bWait || dwBytesAvailable ) + return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL ); + else + { + *lpBytesRead = 0; + return true; + } + } + + return false; +} + + + +//---------------------------------------------------------------------------- +// Client pipe dtor +//---------------------------------------------------------------------------- + +ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ) +{ +} + +//---------------------------------------------------------------------------- +// Client pipe creation +//---------------------------------------------------------------------------- + +ClientPipe *ClientPipe::Create( LPCTSTR lpName ) +{ + ClientPipe *pPipe = NULL; // Assume failure + + HANDLE hMapping = OpenPipeDataMapping( lpName ); + + if ( IsValidHandle(hMapping) ) + { + PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); + + if ( pData ) + { + HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId ); + + if ( IsValidHandle(hSourceProcess) ) + { + BOOL fSuccess; + HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE; + + fSuccess = DuplicateHandle( + hSourceProcess, + pData->hReadPipe, + GetCurrentProcess(), + &hReadPipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + fSuccess = fSuccess && DuplicateHandle( + hSourceProcess, + pData->hWritePipe, + GetCurrentProcess(), + &hWritePipe, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + if ( fSuccess ) + pPipe = new ClientPipe( hReadPipe, hWritePipe ); + + if ( IsValidHandle(hWritePipe) ) + CloseHandle( hWritePipe ); + + if ( IsValidHandle(hReadPipe) ) + CloseHandle( hReadPipe ); + + HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 ); + + ReleaseSemaphore( hConnectionRequest, 1, NULL ); + + CloseHandle( hConnectionRequest ); + + CloseHandle( hSourceProcess ); + } + + UnmapViewOfFile( pData ); + } + + CloseHandle( hMapping ); + } + + return pPipe; +} + + + +//---------------------------------------------------------------------------- +// ServerPipe ctor +//---------------------------------------------------------------------------- + +ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ), +m_hMapping( NULL ), +m_hSynchronize( NULL ), +m_lpName( NULL ) +{ + DuplicateHandle( + GetCurrentProcess(), + hMapping, + GetCurrentProcess(), + &m_hMapping, + 0, + FALSE, + DUPLICATE_SAME_ACCESS ); + + DuplicateHandle( + GetCurrentProcess(), + hSynchronize, + GetCurrentProcess(), + &m_hSynchronize, + 0, + FALSE, + DUPLICATE_SAME_ACCESS + ); + m_lpName = new TCHAR[_tcslen(lpName) + 1]; + if ( m_lpName ) + _tcscpy( m_lpName, lpName ); +} + +//---------------------------------------------------------------------------- +// ServerPipe dtor +//---------------------------------------------------------------------------- + +ServerPipe::~ServerPipe() +{ + if ( IsValidHandle(m_hMapping) ) + CloseHandle( m_hMapping ); + if ( m_lpName ) + delete[]m_lpName; +} + +//---------------------------------------------------------------------------- +// ServerPipe AcceptConnection +//---------------------------------------------------------------------------- + +Pipe *ServerPipe::AcceptConnection() +{ + Pipe *pPipe = NULL; // Assume failure; + + HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 ); + + if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) ) + { + pPipe = new Pipe( *this ); + Close(); + + // Create new inbound Pipe + + HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL; + + BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE ); + + + if ( fSuccess ) + { + // Create outbound pipe + + HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL; + + if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) ) + { + m_hReadPipe = hServerReadPipe; + m_hWritePipe = hServerWritePipe; + + PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) ); + + HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE ); + + CloseHandle( pData->hReadPipe ); + CloseHandle( pData->hWritePipe ); + + pData->hReadPipe = hClientReadPipe; + pData->hWritePipe = hClientWritePipe; + + ReleaseMutex( hSynchronize ); + + CloseHandle( hSynchronize ); + + } + else + { + CloseHandle( hClientWritePipe ); + CloseHandle( hServerWritePipe ); + } + } + + ReleaseMutex( hConnectionRequest ); + } + + CloseHandle( hConnectionRequest ); + + return pPipe; +} + +//---------------------------------------------------------------------------- +// Pipe creation +//---------------------------------------------------------------------------- + +ServerPipe *ServerPipe::Create( LPCTSTR lpName ) +{ + ServerPipe *pPipe = NULL; + + HANDLE hMapping = CreatePipeDataMapping( lpName ); + + if ( IsValidHandle(hMapping) ) + { + if ( ERROR_FILE_EXISTS != GetLastError() ) + { + HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE); + + WaitForSingleObject( hSynchronize, INFINITE ); + + PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); + + if ( pData ) + { + + // Initialize pipe data + + pData->dwProcessId = 0; + pData->hReadPipe = NULL; + pData->hWritePipe = NULL; + + // Create inbound pipe + + HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL; + + BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE ); + + if ( fSuccess ) + { + // Create outbound pipe + + HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL; + + fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ); + + if ( fSuccess ) + { + pData->dwProcessId = GetCurrentProcessId(); + pData->hReadPipe = hClientReadPipe; + pData->hWritePipe = hClientWritePipe; + pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe ); + + CloseHandle( hServerWritePipe ); + CloseHandle( hServerReadPipe ); + } + else + { + CloseHandle( hServerReadPipe ); + CloseHandle( hClientWritePipe ); + } + } + + UnmapViewOfFile( pData ); + } + + ReleaseMutex( hSynchronize ); + CloseHandle( hSynchronize ); + } + + CloseHandle( hMapping ); + } + + return pPipe; +} + + +//---------------------------------------------------------------------------- +// C style API +//---------------------------------------------------------------------------- + +const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" ); + +extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName ) +{ + int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX ); + if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) ) + lpName += nPrefixLen; + return (HANDLE)ServerPipe::Create( lpName ); +} + +extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName ) +{ + int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX ); + if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) ) + lpName += nPrefixLen; + return (HANDLE)ClientPipe::Create( lpName ); +} + +extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe ) +{ + Pipe *pPipe = (Pipe *)hPipe; + + if ( pPipe->is() ) + return (HANDLE)pPipe->AcceptConnection(); + else + { + SetLastError( ERROR_INVALID_HANDLE ); + return NULL; + } +} + +extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ ) +{ + return FALSE; +} + +extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait ) +{ + Pipe *pPipe = (Pipe *)hPipe; + + if ( pPipe->is() ) + return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait ); + else + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } +} + +extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait ) +{ + Pipe *pPipe = (Pipe *)hPipe; + + if ( pPipe->is() ) + return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait ); + else + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } +} + +extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe ) +{ + Pipe *pPipe = (Pipe *)hPipe; + + if ( pPipe->is() ) + { + delete pPipe; + return TRUE; + } + else + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } +} diff --git a/sal/osl/os2/pipeimpl.h b/sal/osl/os2/pipeimpl.h new file mode 100644 index 000000000000..cff082dee5a3 --- /dev/null +++ b/sal/osl/os2/pipeimpl.h @@ -0,0 +1,82 @@ +#ifndef _PIPEIMPL_H_ +#define _PIPEIMPL_H_ + +#ifndef _WINDOWS_ +# include <windows.h> +#endif + +#ifndef _INC_MALLOC +# include <malloc.h> +#endif + +#ifndef _INC_TCHAR +# ifdef UNICODE +# define _UNICODE +# endif +# include <tchar.h> +#endif + +#define EXPORT_PIPE_API + +//============================================================================ +// Helper functions +//============================================================================ + +// Because the value of an invalid HANDLE returned by API functions differs +// between different functions and differs on different Windows platforms, +// this function checks wether the handle has a meaningfull value. +#ifndef __cplusplus + +#define IsValidHandle( handle ) ((DWORD)(handle) + 1 > 1) + +#else + +inline bool IsValidHandle( HANDLE handle ) +{ + return INVALID_HANDLE_VALUE != handle && NULL != handle; +} + +extern "C" { + +#endif // __cplusplus + + +EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeA( LPCSTR lpName ); +EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeW( LPCWSTR lpName ); + +#ifdef UNICODE +#define CreateSimplePipe CreateSimplePipeW +#else +#define CreateSimplePipe CreateSimplePipeA +#endif + +EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeA( LPCSTR lpName ); +EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeW( LPCWSTR lpName ); + +#ifdef UNICODE +#define OpenSimplePipe OpenSimplePipeW +#else +#define OpenSimplePipe OpenSimplePipeA +#endif + +EXPORT_PIPE_API HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe ); + +EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeA( LPCSTR lpName, DWORD dwTimeOut ); +EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeW( LPCWSTR lpName, DWORD dwTimeOut ); + +#ifdef UNICODE +#define WaitForSimplePipe WaitForSimplePipeW +#else +#define WaitForSimplePipe WaitForSimplePipeA +#endif + + +EXPORT_PIPE_API BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait ); +EXPORT_PIPE_API BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait ); +EXPORT_PIPE_API BOOL WINAPI CloseSimplePipe( HANDLE hPipe ); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PIPEIMPL_H_ diff --git a/sal/osl/os2/process.c b/sal/osl/os2/process.c new file mode 100644 index 000000000000..a3408ddbf7d0 --- /dev/null +++ b/sal/osl/os2/process.c @@ -0,0 +1,1016 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: process.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "system.h" +#include <osl/thread.h> + +#include <osl/diagnose.h> +//#include <osl/socket.h> + +#ifndef _OSL_FILE_PATH_HELPER_H_ +#include "file_path_helper.h" +#endif + +#include "procimpl.h" +//#include "sockimpl.h" +//#include "secimpl.h" + +#include <ctype.h> + +//#ifndef _RTL_USTRING_HXX_ +#include <rtl/ustring.hxx> +//#endif + +// for exception logging +#include <stdio.h> +#include <setjmp.h> +#include "helpers/except.h" + + +#define MAX_ARGS 255 +#define PIPENAMEMASK "\\PIPE\\OSL_PIPE_%u" +#define SEMNAMEMASK "\\SEM32\\OSL_SEM_%u" + +typedef enum { + MSG_DATA, + MSG_END, + MSG_ACK, + MSG_REL, + MSG_UNKNOWN +} MessageType; + +typedef struct { + MessageType m_Type; + oslDescriptorFlag m_Flags; + oslDescriptorType m_Data; + HANDLE m_Value; +} Message; + +typedef struct { + HPIPE m_hPipe; +} Pipe; + +typedef struct _oslSocketCallbackArg { + HANDLE m_socket; + Pipe* m_pipe; +} oslSocketCallbackArg; + +/* process termination queue */ +static sal_Bool bInitSessionTerm = sal_False; +static const sal_Char * const SessionTermQueueName = "\\QUEUES\\SESSIONS.QUE"; +static HQUEUE SessionTermQueue; + +/****************************************************************************** + * + * Function Declarations + * + *****************************************************************************/ + +oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName, + sal_Char *pszArguments[], + oslProcessOption Options, + oslSecurity Security, + sal_Char *pszDirectory, + sal_Char *pszEnvironments[], + oslProcess *pProcess, + oslFileHandle *pInputWrite, + oslFileHandle *pOutputRead, + oslFileHandle *pErrorRead ); + +/* implemented in file.c */ +extern oslFileError FileURLToPath( char *, size_t, rtl_uString* ); + +static sal_Bool InitSessionTerm( void ) +{ + DosCreateQueue( &SessionTermQueue, QUE_FIFO, (PCSZ) SessionTermQueueName ); + + return sal_True; +} + +/****************************************************************************** + * + * Functions for starting a process + * + *****************************************************************************/ + +/********************************************** + osl_executeProcess_WithRedirectedIO + *********************************************/ + +oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO( + rtl_uString *ustrImageName, + rtl_uString *ustrArguments[], + sal_uInt32 nArguments, + oslProcessOption Options, + oslSecurity Security, + rtl_uString *ustrWorkDir, + rtl_uString *ustrEnvironment[], + sal_uInt32 nEnvironmentVars, + oslProcess *pProcess, + oslFileHandle *pInputWrite, + oslFileHandle *pOutputRead, + oslFileHandle *pErrorRead + ) +{ + + oslProcessError Error; + sal_Char* pszWorkDir=0; + sal_Char** pArguments=0; + sal_Char** pEnvironment=0; + unsigned int index; + + char szImagePath[PATH_MAX] = ""; + char szWorkDir[PATH_MAX] = ""; + +#if 0 + if (Options & osl_Process_SEARCHPATH) + { + const rtl::OUString PATH1; + OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH")); + + rtl_uString * pSearchPath = 0; + osl_getEnvironment (PATH.pData, &pSearchPath); + if (pSearchPath) + { + rtl_uString * pSearchResult = 0; + osl_searchPath (ustrImageName, pSearchPath, &pSearchResult); + if (pSearchResult) + { + rtl_uString_assign (ustrImageName, pSearchResult); + rtl_uString_release (pSearchResult); + } + rtl_uString_release (pSearchPath); + } + } +#endif + + if ( ustrImageName && ustrImageName->length ) + { + FileURLToPath( szImagePath, PATH_MAX, ustrImageName ); + } + + if ( ustrWorkDir != 0 && ustrWorkDir->length ) + { + FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir ); + pszWorkDir = szWorkDir; + } + + if ( pArguments == 0 && nArguments > 0 ) + { + pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) ); + } + + + for ( index = 0 ; index < nArguments ; ++index ) + { + rtl_String* strArg =0; + + + rtl_uString2String( &strArg, + rtl_uString_getStr(ustrArguments[index]), + rtl_uString_getLength(ustrArguments[index]), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS ); + + pArguments[index]=strdup(rtl_string_getStr(strArg)); + rtl_string_release(strArg); + pArguments[index+1]=0; + } + + for ( index = 0 ; index < nEnvironmentVars ; ++index ) + { + rtl_String* strEnv=0; + + if ( pEnvironment == 0 ) + { + pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) ); + } + + rtl_uString2String( &strEnv, + rtl_uString_getStr(ustrEnvironment[index]), + rtl_uString_getLength(ustrEnvironment[index]), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS ); + + pEnvironment[index]=strdup(rtl_string_getStr(strEnv)); + rtl_string_release(strEnv); + pEnvironment[index+1]=0; + } + + int rc, pid; + int saveOutput = -1, saveInput = -1, saveError = -1; + int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 }; + FILE *i, *o, *e; + + if (pInputWrite) + pipe( stdInput); + if (pOutputRead) + pipe( stdOutput); + if (pErrorRead) + pipe( stdError); + + fcntl( stdInput[0], F_SETFD, FD_CLOEXEC); + fcntl( stdInput[1], F_SETFD, FD_CLOEXEC); + fcntl( stdOutput[0], F_SETFD, FD_CLOEXEC); + fcntl( stdOutput[1], F_SETFD, FD_CLOEXEC); + fcntl( stdError[0], F_SETFD, FD_CLOEXEC); + fcntl( stdError[1], F_SETFD, FD_CLOEXEC); + + saveInput = dup( STDIN_FILENO); + fcntl( saveInput, F_SETFD, FD_CLOEXEC); + dup2( stdInput[0], STDIN_FILENO ); + close( stdInput[0] ); + + saveOutput = dup( STDOUT_FILENO); + fcntl( saveOutput, F_SETFD, FD_CLOEXEC); + dup2( stdOutput[1], STDOUT_FILENO ); + close( stdOutput[1] ); + + saveError = dup( STDERR_FILENO); + fcntl( saveError, F_SETFD, FD_CLOEXEC); + dup2( stdError[1], STDERR_FILENO ); + close( stdError[1] ); + + Error = osl_psz_executeProcess(szImagePath, + pArguments, + Options, + Security, + pszWorkDir, + pEnvironment, + pProcess, + pInputWrite, + pOutputRead, + pErrorRead + ); + + if ( pInputWrite ) + *(pInputWrite) = osl_createFileHandleFromFD( stdInput[1] ); + + if ( pOutputRead ) + *(pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] ); + + if ( pErrorRead ) + *(pErrorRead) = osl_createFileHandleFromFD( stdError[0] ); + + // restore handles + dup2( saveInput, STDIN_FILENO); + close( saveInput); + dup2( saveOutput, STDOUT_FILENO); + close( saveOutput); + dup2( saveError, STDERR_FILENO); + close( saveError); + + if ( pArguments != 0 ) + { + for ( index = 0 ; index < nArguments ; ++index ) + { + if ( pArguments[index] != 0 ) + { + free(pArguments[index]); + } + } + free(pArguments); + } + + if ( pEnvironment != 0 ) + { + for ( index = 0 ; index < nEnvironmentVars ; ++index ) + { + if ( pEnvironment[index] != 0 ) + { + free(pEnvironment[index]); + } + } + free(pEnvironment); + } + + return Error; +} + +/********************************************** + osl_executeProcess + *********************************************/ + +oslProcessError SAL_CALL osl_executeProcess( + rtl_uString *ustrImageName, + rtl_uString *ustrArguments[], + sal_uInt32 nArguments, + oslProcessOption Options, + oslSecurity Security, + rtl_uString *ustrWorkDir, + rtl_uString *ustrEnvironment[], + sal_uInt32 nEnvironmentVars, + oslProcess *pProcess + ) +{ + return osl_executeProcess_WithRedirectedIO( + ustrImageName, + ustrArguments, + nArguments, + Options, + Security, + ustrWorkDir, + ustrEnvironment, + nEnvironmentVars, + pProcess, + NULL, + NULL, + NULL + ); +} + +/********************************************** + osl_psz_executeProcess + *********************************************/ + +oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName, + sal_Char *pszArguments[], + oslProcessOption Options, + oslSecurity Security, + sal_Char *pszDirectory, + sal_Char *pszEnvironments[], + oslProcess *pProcess, + oslFileHandle *pInputWrite, + oslFileHandle *pOutputRead, + oslFileHandle *pErrorRead + ) +{ + ULONG ulSessID = 0; /* Session ID returned */ + PID pidProcess; + APIRET rc; + sal_Char* pStr; + sal_Char* args; + sal_Char* envs; + int i; + int n = 1; + oslProcessImpl* pProcImpl; + ULONG nAppType, nOwnAppType; + ULONG nCurrentDisk, nDriveMap, nBufSize; + int first = 0; + sal_Char path[ _MAX_PATH ]; + sal_Char currentDir[ _MAX_PATH ]; + sal_Char ownfilename[ _MAX_PATH ]; + RESULTCODES resultCode; + char** p; + + /* get imagename from arg list, if not specified */ + if (pszImageName == NULL) + pszImageName = pszArguments[first++]; + + OSL_ASSERT(pszImageName != NULL); + + /* check application type */ + rc = DosQueryAppType( (PCSZ) pszImageName, &nAppType ); + if( rc != NO_ERROR ) + { + if( (rc == ERROR_FILE_NOT_FOUND) || (rc == ERROR_PATH_NOT_FOUND) ) + return osl_Process_E_NotFound; + else + return osl_Process_E_Unknown; + } + + /* backup current disk information */ + if(DosQueryCurrentDisk(&nCurrentDisk, &nDriveMap)) + { + nCurrentDisk = 0; + } + + /* backup current directory information */ + nBufSize = _MAX_PATH; + if(DosQueryCurrentDir(0, (BYTE*)currentDir, &nBufSize)) + { + *currentDir = '\0'; + } + + /* change to working directory */ + if(pszDirectory && pszDirectory[1] == ':') + { + BYTE nDrive = toupper(pszDirectory[0]) - 'A' + 1; + + if(NO_ERROR == DosSetDefaultDisk(nDrive)) + { + DosSetCurrentDir((PSZ) pszDirectory); + } + } + + /* query current executable filename and application type */ + { + CHAR szName[CCHMAXPATH]; + PPIB ppib; + PTIB ptib; + APIRET rc; + rc = DosGetInfoBlocks(&ptib, &ppib); + rc = DosQueryModuleName(ppib->pib_hmte, sizeof(szName), szName); + DosQueryAppType( (PCSZ)szName, &nOwnAppType ); + } + + /* combination of flags WAIT and DETACHED not supported */ + if( (Options & osl_Process_DETACHED) && (Options & osl_Process_WAIT) ) + Options &= !osl_Process_DETACHED; + + /* start in same session if possible and detached flag not set */ + if( ((nAppType & 0x00000007) == (nOwnAppType & 0x00000007)) +/* && ((Options & osl_Process_DETACHED) == 0) */ ) + { + CHAR szbuf[CCHMAXPATH]; + + /* calculate needed space for arguments */ + n = strlen( pszImageName ) + 1; + if( pszArguments ) + for (i = first; pszArguments[i] != NULL; i++) + n += strlen(pszArguments[i]) + 1; + + /* allocate space for arguments */ + args = (sal_Char*)malloc(n + 1); + pStr = args; + + /* add program name as first string to arguments */ + memcpy(pStr, pszImageName, strlen( pszImageName ) ); + pStr += strlen( pszImageName ); + *pStr++ = '\0'; + + /* add given strings to arguments */ + if( pszArguments ) + for (i = first; pszArguments[i] != NULL; i++) + { + memcpy(pStr, pszArguments[i], strlen( pszArguments[i] ) ); + pStr += strlen( pszArguments[i] ); + if (pszArguments[i+1] != NULL) + *pStr++ = ' '; + } + + /* set end marker for arguments */ + *pStr++ = '\0'; + *pStr = '\0'; + + OSL_TRACE( "osl_executeProcess with DosExecPgm (args: %s)\n", args ); + + /* calculate needed space for environment: since enviroment var search + is a linear scan of the current enviroment, we place new variables + before existing ones; so the child will find new definitions before + olders; this doesn't require us to replace existing vars */ + // existing enviroment size + n = 0; + p = environ; + while( *p) + { + int l = strlen( *p); + n += l + 1; + p++; + } + // new env size (if exists) + if( pszEnvironments ) + { + for (i = 0; pszEnvironments[i] != NULL; i++) + n += strlen(pszEnvironments[i]) + 1; + } + /* allocate space for environment */ + envs = (sal_Char*)malloc(n + 1); + pStr = envs; + + // add new vars + if( pszEnvironments ) + { + /* add given strings to environment */ + for (i = 0; pszEnvironments[i] != NULL; i++) + { + memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) ); + pStr += strlen( pszEnvironments[i] ); + *pStr++ = '\0'; + } + } + // add existing vars + p = environ; + while( *p) + { + memcpy(pStr, *p, strlen( *p ) ); + pStr += strlen( *p ); + *pStr++ = '\0'; + p++; + } + /* set end marker for environment */ + *pStr = '\0'; + + + if(Options & osl_Process_DETACHED) + { + rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_BACKGROUND, + (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName ); + } + else + { + rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_ASYNCRESULT, + (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName ); + } + + pidProcess = resultCode.codeTerminate; + + /* cleanup */ + free(envs); + free(args); + + /* error handling */ + if( rc != NO_ERROR ) + return osl_Process_E_Unknown; + } + + else + { + STARTDATA SData = { 0 }; + UCHAR achObjBuf[ 256 ] = { 0 }; + + /* combine arguments separated by spaces */ + if( pszArguments ) + { + for (i = first; pszArguments[i] != NULL; i++) + n += strlen(pszArguments[i]) + 1; + // YD DosStartSession requires low-mem buffers! + args = (sal_Char*)_tmalloc(n); + *args = '\0'; + for (i = first; pszArguments[i] != NULL; i++) + { + strcat(args, pszArguments[i]); + strcat(args, " "); + } + } + else + args = NULL; + + /* combine environment separated by NULL */ + if( pszEnvironments ) + { + for (i = 0; pszEnvironments[i] != NULL; i++) + n += strlen(pszEnvironments[i]) + 1; + // YD DosStartSession requires low-mem buffers! + envs = (sal_Char*)_tmalloc(n + 1); + pStr = (sal_Char*)envs; + for (i = 0; pszEnvironments[i] != NULL; i++) + { + memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) ); + pStr += strlen( pszEnvironments[i] ); + *pStr = '\0'; + pStr++; + } + *pStr = '\0'; + } + else + envs = NULL; + + /* initialize data structure */ + memset( &SData, 0, sizeof( STARTDATA ) ); + SData.Length = sizeof(STARTDATA); + + OSL_TRACE( "osl_executeProcess with DosStartSession (args: %s)\n", args ); + + /* OS/2 Application ? */ + if(nAppType & 0x00000007) + { + + /* inherit options from parent */ + SData.InheritOpt = SSF_INHERTOPT_PARENT; + + switch (Options & (osl_Process_NORMAL | osl_Process_MINIMIZED | + osl_Process_MAXIMIZED | osl_Process_FULLSCREEN)) + { + case osl_Process_MINIMIZED: + SData.SessionType = SSF_TYPE_DEFAULT; + SData.PgmControl |= SSF_CONTROL_MINIMIZE; + break; + + case osl_Process_MAXIMIZED: + SData.SessionType = SSF_TYPE_DEFAULT; + SData.PgmControl |= SSF_CONTROL_MAXIMIZE; + break; + + case osl_Process_FULLSCREEN: + SData.SessionType = SSF_TYPE_FULLSCREEN; + break; + + default: + SData.SessionType = SSF_TYPE_DEFAULT; + } /* switch */ + } + + + if( Options & osl_Process_DETACHED ) + { + /* start an independent session */ + SData.Related = SSF_RELATED_INDEPENDENT; + SData.TermQ = NULL; + } + else + { + /* start a child session and set Termination Queue */ + SData.Related = SSF_RELATED_CHILD; + + if(! bInitSessionTerm) + bInitSessionTerm = InitSessionTerm(); + + SData.TermQ = (BYTE*) SessionTermQueueName; + } + + SData.FgBg = SSF_FGBG_FORE; /* start session in foreground */ + SData.TraceOpt = SSF_TRACEOPT_NONE; /* No trace */ + + SData.PgmTitle = NULL; + SData.PgmInputs = (BYTE*)args; + SData.PgmName = (PSZ) pszImageName; + SData.Environment = (BYTE*)envs; + + if( Options & osl_Process_HIDDEN ) + SData.PgmControl |= SSF_CONTROL_INVISIBLE; + else + SData.PgmControl |= SSF_CONTROL_VISIBLE; + + SData.ObjectBuffer = (PSZ) achObjBuf; + SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf); + + + /* Start the session */ + rc = DosStartSession( &SData, &ulSessID, &pidProcess ); + + /* ignore error "session started in background" */ + if( rc == ERROR_SMG_START_IN_BACKGROUND ) + rc = NO_ERROR; + + + if(envs) + _tfree(envs); + if(args) + _tfree(args); + + if( rc != NO_ERROR ) + return osl_Process_E_Unknown; + + } /* else */ + + + /* restore current disk */ + if(nCurrentDisk) + { + DosSetDefaultDisk(nCurrentDisk); + } + + /* restore current drive information */ + if(*currentDir) + { + DosSetCurrentDir((PCSZ)currentDir); + } + + /* allocate intern process structure and store child process ID */ + pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl)); + pProcImpl->pProcess = pidProcess; + pProcImpl->nSessionID = ulSessID; + + pProcImpl->bResultCodeValid = FALSE; + + if( Options & osl_Process_WAIT ) + osl_joinProcess(pProcImpl); + + *pProcess = (oslProcess)pProcImpl; + + if( rc == NO_ERROR ) + return osl_Process_E_None; + else + + return osl_Process_E_Unknown; +} + +/*----------------------------------------------------------------------------*/ + +oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process) +{ + if (Process == NULL) + return osl_Process_E_Unknown; + + /* Stop the session */ + DosStopSession( STOP_SESSION_SPECIFIED, ((oslProcessImpl*)Process)->nSessionID ); + + return osl_Process_E_None; +} + +/*----------------------------------------------------------------------------*/ + +oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident) +{ + HANDLE hProcess; + oslProcessImpl* pProcImpl; + + /* check, if given PID is a valid process */ + if (FALSE) + { + pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl)); +/* + pProcImpl->pProcess = pidProcess; + pProcImpl->nSessionID = ulSessID; +*/ + } + else + pProcImpl = NULL; + + return (pProcImpl); +} + +/*----------------------------------------------------------------------------*/ + +void SAL_CALL osl_freeProcessHandle(oslProcess Process) +{ + /* free intern process structure */ + if (Process != NULL) + free((oslProcessImpl*)Process); +} + +/*----------------------------------------------------------------------------*/ + +oslProcessError SAL_CALL osl_joinProcess(oslProcess Process) +{ + oslProcessImpl* pProcImpl = (oslProcessImpl*) Process; + APIRET rc; + + if (Process == NULL) + return osl_Process_E_Unknown; + + /* process of same session ? */ + if( pProcImpl->nSessionID == 0 ) + { + RESULTCODES resultCode; + PID pidEnded; + + rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode, + &pidEnded, pProcImpl->pProcess ); + + if( rc == NO_ERROR ) + { + pProcImpl->nResultCode = resultCode.codeResult; + pProcImpl->bResultCodeValid = TRUE; + + return osl_Process_E_None; + } + } + else + { + ULONG pcbData, ulElement = 0; + REQUESTDATA rdData; + BYTE bPriority; + struct { + USHORT SessionID; + USHORT ReturnValue; + } *pvBuffer; + + /* search/wait for the correct entry in termination queue */ + while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData, + (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT, + &bPriority, NULLHANDLE )) == NO_ERROR ) + { + + if( pvBuffer->SessionID == pProcImpl->nSessionID ) + { + pProcImpl->nResultCode = pvBuffer->ReturnValue; + pProcImpl->bResultCodeValid = TRUE; + + /* remove item from queue */ + rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData, + (PPVOID)&pvBuffer, ulElement, DCWW_WAIT, + &bPriority, NULLHANDLE ); + + if( rc == NO_ERROR ) + return osl_Process_E_None; + else + return osl_Process_E_Unknown; + } + } /* while */ + } + return osl_Process_E_Unknown; +} + +/***************************************************************************/ + +//YD FIXME incomplete! +oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout) +{ + return osl_joinProcess( Process); +} + +/*----------------------------------------------------------------------------*/ + +oslProcessError SAL_CALL osl_getCommandArgs( sal_Char* pszBuffer, sal_uInt32 Max) +{ + + static int CmdLen = -1; + static sal_Char CmdLine[_MAX_CMD]; + + OSL_ASSERT(pszBuffer); + OSL_ASSERT(Max > 1); + + /* Query commandline during first call of function only */ + if (CmdLen < 0) + { + sal_Bool bEscaped = sal_False; + sal_Bool bSeparated = sal_True; + sal_Char* pszBufferOrg = pszBuffer; + sal_Char* pszCmdLine; + + /* get pointer to commandline */ + { + PTIB pptib = NULL; + PPIB pppib = NULL; + + DosGetInfoBlocks(&pptib, &pppib); + pszCmdLine = pppib->pib_pchcmd; + } + + /* skip first string */ + while( *pszCmdLine ) + pszCmdLine++; + + /* concatenate commandline arguments for the given string */ + Max -= 2; + while ( !((*pszCmdLine == '\0') && (*(pszCmdLine + 1) == '\0')) && (Max > 0)) + { + /* + * C-Runtime expects char to be unsigned and so to be + * preceeded with 00 instead of FF when converting to int + */ + int n = *((unsigned char *) pszCmdLine); + if (! (isspace(n) || (*pszCmdLine == '\0')) ) + { + if (*pszCmdLine == '"') + { + if (*(pszCmdLine + 1) != '"') + bEscaped = ! bEscaped; + else + { + pszCmdLine++; + *pszBuffer++ = *pszCmdLine; + Max--; + } + } + else + { + *pszBuffer++ = *pszCmdLine; + Max--; + } + bSeparated = sal_False; + } + else + { + if (bEscaped) + *pszBuffer++ = *pszCmdLine; + else + if (! bSeparated) + { + *pszBuffer++ = '\0'; + bSeparated = sal_True; + } + Max--; + } + + pszCmdLine++; + } + + *pszBuffer++ = '\0'; + *pszBuffer++ = '\0'; + + /* restore pointer and save commandline for next query */ + CmdLen = pszBuffer - pszBufferOrg; + pszBuffer = pszBufferOrg; + memcpy( CmdLine, pszBuffer, CmdLen ); + } + else + memcpy( pszBuffer, CmdLine, CmdLen ); + + OSL_TRACE( "osl_getCommandArgs (args: %s)\n", pszBuffer ); + + return osl_Process_E_None; +} + +/*----------------------------------------------------------------------------*/ + +oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, + oslProcessInfo* pInfo) +{ + if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo))) + return osl_Process_E_Unknown; + + pInfo->Fields = 0; + + if (Fields & osl_Process_IDENTIFIER) + { + if( Process == NULL ) + { + PTIB pptib = NULL; + PPIB pppib = NULL; + + DosGetInfoBlocks( &pptib, &pppib ); + pInfo->Ident = pppib->pib_ulpid; + } + else + pInfo->Ident = ((oslProcessImpl*)Process)->pProcess; + + pInfo->Fields |= osl_Process_IDENTIFIER; + } + + if (Fields & osl_Process_EXITCODE) + { + oslProcessImpl* pProcImpl = (oslProcessImpl*) Process; + + if( pProcImpl->bResultCodeValid ) + { + pInfo->Code = pProcImpl->nResultCode; + pInfo->Fields |= osl_Process_EXITCODE; + } + else + { + APIRET rc; + + if( pProcImpl->nSessionID == 0 ) + { + RESULTCODES resultCode; + PID pidEnded; + + rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode, + &pidEnded, pProcImpl->pProcess ); + + if( rc == NO_ERROR ) + { + pProcImpl->nResultCode = resultCode.codeResult; + pProcImpl->bResultCodeValid = TRUE; + + pInfo->Code = pProcImpl->nResultCode; + pInfo->Fields |= osl_Process_EXITCODE; + + return osl_Process_E_None; + } + } + else + { + ULONG pcbData, ulElement = 0; + REQUESTDATA rdData; + BYTE bPriority; + struct { + USHORT SessionID; + USHORT ReturnValue; + } *pvBuffer; + + /* search/wait for the correct entry in termination queue */ + while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData, + (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT, + &bPriority, NULLHANDLE )) == NO_ERROR ) + { + + if( pvBuffer->SessionID == pProcImpl->nSessionID ) + { + pProcImpl->nResultCode = pvBuffer->ReturnValue; + pProcImpl->bResultCodeValid = TRUE; + + pInfo->Code = pProcImpl->nResultCode; + pInfo->Fields |= osl_Process_EXITCODE; + + /* remove item from queue */ + rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData, + (PPVOID)&pvBuffer, ulElement, DCWW_WAIT, + &bPriority, NULLHANDLE ); + + break; + } + } + } + } + } + + if (Fields & osl_Process_HEAPUSAGE) + { + } + if (Fields & osl_Process_CPUTIMES) + { + } + + return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown; +} diff --git a/sal/osl/os2/process_impl.cxx b/sal/osl/os2/process_impl.cxx new file mode 100644 index 000000000000..97b137043444 --- /dev/null +++ b/sal/osl/os2/process_impl.cxx @@ -0,0 +1,371 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: process_impl.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#define INCL_DOS +#include <os2.h> + +#include "osl/process.h" +#include <osl/mutex.h> + +#ifndef INCLUDED_LIMITS_H +#include <limits.h> +#define INCLUDED_LIMITS_H +#endif + +#ifndef INCLUDED_PTHREAD_H +#include <pthread.h> +#define INCLUDED_PTHREAD_H +#endif + +#ifndef INCLUDED_STDLIB_H +#include <stdlib.h> +#define INCLUDED_STDLIB_H +#endif + +#ifndef INCLUDED_STRING_H +#include <string.h> +#define INCLUDED_STRING_H +#endif +#include "osl/diagnose.h" +#include <osl/file.h> +#include "osl/module.h" +#include "osl/thread.h" +#include "rtl/ustring.hxx" + +#ifndef _OSL_FILE_PATH_HELPER_H_ +#include "file_path_helper.h" +#endif + +#ifndef _OSL_UUNXAPI_H_ +#include "uunxapi.h" +#endif + +/*************************************** + osl_bootstrap_getExecutableFile_Impl(). + + @internal + @see rtl_bootstrap + @see #i37371# + + **************************************/ + +extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl ( + rtl_uString ** ppFileURL +) SAL_THROW_EXTERN_C(); + + +oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl ( + rtl_uString ** ppFileURL +) SAL_THROW_EXTERN_C() +{ + oslProcessError result = osl_Process_E_NotFound; + CHAR szName[CCHMAXPATH]; + PPIB ppib; + PTIB ptib; + APIRET rc; + + rc = DosGetInfoBlocks(&ptib, &ppib); + rc = DosQueryModuleName(ppib->pib_hmte, sizeof(szName), szName); + + if (rc == 0) + { + rtl_uString * pAbsPath = 0; + + rtl_string2UString( + &pAbsPath, + szName, strlen(szName), osl_getThreadTextEncoding(), + OSTRING_TO_OUSTRING_CVTFLAGS); + + if (pAbsPath) + { + /* Convert from path to url. */ + if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None) + { + /* Success. */ + result = osl_Process_E_None; + } + rtl_uString_release (pAbsPath); + } + } + + return (result); +} + +/*************************************** + CommandArgs_Impl. + **************************************/ +struct CommandArgs_Impl +{ + oslMutex m_mutex; + sal_uInt32 m_nCount; + rtl_uString ** m_ppArgs; +}; + +static struct CommandArgs_Impl g_command_args = +{ + osl_createMutex(), + 0, + 0 +}; + +/*************************************** + osl_getExecutableFile(). + **************************************/ +oslProcessError SAL_CALL osl_getExecutableFile (rtl_uString ** ppustrFile) +{ + oslProcessError result = osl_Process_E_NotFound; + + osl_acquireMutex(g_command_args.m_mutex); + if (g_command_args.m_nCount > 0) + { + /* CommandArgs set. Obtain argv[0]. */ + rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]); + result = osl_Process_E_None; + } + osl_releaseMutex(g_command_args.m_mutex); + + return (result); +} + +/*************************************** + osl_getCommandArgCount(). + **************************************/ +sal_uInt32 SAL_CALL osl_getCommandArgCount (void) +{ + sal_uInt32 result = 0; + + osl_acquireMutex(g_command_args.m_mutex); + if (g_command_args.m_nCount > 0) + result = g_command_args.m_nCount - 1; + osl_releaseMutex(g_command_args.m_mutex); + + return (result); +} + +/*************************************** + osl_getCommandArg(). + **************************************/ +oslProcessError SAL_CALL osl_getCommandArg (sal_uInt32 nArg, rtl_uString ** strCommandArg) +{ + oslProcessError result = osl_Process_E_NotFound; + + osl_acquireMutex(g_command_args.m_mutex); + if (g_command_args.m_nCount > (nArg + 1)) + { + rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]); + result = osl_Process_E_None; + } + osl_releaseMutex(g_command_args.m_mutex); + + return (result); +} + +/*************************************** + osl_setCommandArgs(). + **************************************/ +void SAL_CALL osl_setCommandArgs (int argc, char ** argv) +{ + + osl_acquireMutex(g_command_args.m_mutex); + OSL_ENSURE (g_command_args.m_nCount == 0, "osl_setCommandArgs(): CommandArgs already set."); + if (g_command_args.m_nCount == 0) + { + rtl_uString** ppArgs = (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*)); + if (ppArgs != 0) + { + rtl_TextEncoding encoding = osl_getThreadTextEncoding(); + for (int i = 0; i < argc; i++) + { + rtl_string2UString ( + &(ppArgs[i]), + argv[i], rtl_str_getLength (argv[i]), encoding, + OSTRING_TO_OUSTRING_CVTFLAGS); + } + if (ppArgs[0] != 0) + { + /* see @ osl_getExecutableFile(). */ + if (rtl_ustr_indexOfChar (rtl_uString_getStr(ppArgs[0]), sal_Unicode('/')) == -1) + { + const rtl::OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH")); + + rtl_uString * pSearchPath = 0; + osl_getEnvironment (PATH.pData, &pSearchPath); + if (pSearchPath) + { + rtl_uString * pSearchResult = 0; + osl_searchPath (ppArgs[0], pSearchPath, &pSearchResult); + if (pSearchResult) + { + rtl_uString_assign (&(ppArgs[0]), pSearchResult); + rtl_uString_release (pSearchResult); + } + rtl_uString_release (pSearchPath); + } + } + + rtl_uString * pArg0 = 0; + if (realpath_u (ppArgs[0], &pArg0)) + { + osl_getFileURLFromSystemPath (pArg0, &(ppArgs[0])); + rtl_uString_release (pArg0); + } + } + g_command_args.m_nCount = argc; + g_command_args.m_ppArgs = ppArgs; + } + } + osl_releaseMutex(g_command_args.m_mutex); + +} + +/*************************************** + osl_getEnvironment(). + **************************************/ +oslProcessError SAL_CALL osl_getEnvironment(rtl_uString* pustrEnvVar, rtl_uString** ppustrValue) +{ + oslProcessError result = osl_Process_E_NotFound; + rtl_TextEncoding encoding = osl_getThreadTextEncoding(); + rtl_String* pstr_env_var = 0; + + OSL_PRECOND(pustrEnvVar, "osl_getEnvironment(): Invalid parameter"); + OSL_PRECOND(ppustrValue, "osl_getEnvironment(): Invalid parameter"); + + rtl_uString2String( + &pstr_env_var, + rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding, + OUSTRING_TO_OSTRING_CVTFLAGS); + if (pstr_env_var != 0) + { + const char* p_env_var = getenv (rtl_string_getStr (pstr_env_var)); + if (p_env_var != 0) + { + rtl_string2UString( + ppustrValue, + p_env_var, strlen(p_env_var), encoding, + OSTRING_TO_OUSTRING_CVTFLAGS); + OSL_ASSERT(*ppustrValue != NULL); + + result = osl_Process_E_None; + } + rtl_string_release(pstr_env_var); + } + + return (result); +} + +/*************************************** + osl_getProcessWorkingDir(). + **************************************/ +oslProcessError SAL_CALL osl_getProcessWorkingDir(rtl_uString **ppustrWorkingDir) +{ + oslProcessError result = osl_Process_E_Unknown; + char buffer[PATH_MAX]; + + OSL_PRECOND(ppustrWorkingDir, "osl_getProcessWorkingDir(): Invalid parameter"); + + if (getcwd (buffer, sizeof(buffer)) != 0) + { + rtl_uString* ustrTmp = 0; + + rtl_string2UString( + &ustrTmp, + buffer, strlen(buffer), osl_getThreadTextEncoding(), + OSTRING_TO_OUSTRING_CVTFLAGS); + if (ustrTmp != 0) + { + if (osl_getFileURLFromSystemPath (ustrTmp, ppustrWorkingDir) == osl_File_E_None) + result = osl_Process_E_None; + rtl_uString_release (ustrTmp); + } + } + + return (result); +} + +/****************************************************************************** + * + * new functions to set/return the current process locale + * + *****************************************************************************/ + +struct ProcessLocale_Impl +{ + oslMutex m_mutex; + rtl_Locale * m_pLocale; +}; + +static struct ProcessLocale_Impl g_process_locale = +{ + osl_createMutex(), + 0 +}; + +extern "C" void _imp_getProcessLocale( rtl_Locale ** ); +extern "C" int _imp_setProcessLocale( rtl_Locale * ); + +/********************************************** + osl_getProcessLocale(). + *********************************************/ +oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale ) +{ + OSL_PRECOND(ppLocale, "osl_getProcessLocale(): Invalid parameter."); + + osl_acquireMutex(g_process_locale.m_mutex); + + if (g_process_locale.m_pLocale == 0) + _imp_getProcessLocale (&(g_process_locale.m_pLocale)); + *ppLocale = g_process_locale.m_pLocale; + + osl_releaseMutex(g_process_locale.m_mutex); + + return (osl_Process_E_None); +} + +/********************************************** + osl_setProcessLocale(). + *********************************************/ +oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale ) +{ + oslProcessError result = osl_Process_E_Unknown; + + OSL_PRECOND(pLocale, "osl_setProcessLocale(): Invalid parameter."); + + osl_acquireMutex(g_process_locale.m_mutex); + if (_imp_setProcessLocale (pLocale) == 0) + { + g_process_locale.m_pLocale = pLocale; + result = osl_Process_E_None; + } + osl_releaseMutex(g_process_locale.m_mutex); + + return (result); +} + diff --git a/sal/osl/os2/procimpl.h b/sal/osl/os2/procimpl.h new file mode 100644 index 000000000000..b1deaa006cb1 --- /dev/null +++ b/sal/osl/os2/procimpl.h @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: procimpl.h,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _OSL_PROCIMPL_H_ +#define _OSL_PROCIMPL_H_ + + +#include <osl/process.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _oslProcessImpl { + + PID pProcess; + sal_uInt32 nSessionID; + sal_uInt32 nResultCode; + BOOL bResultCodeValid; +} oslProcessImpl; + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/sal/osl/os2/profile.c b/sal/osl/os2/profile.c new file mode 100644 index 000000000000..f5334f88ddf9 --- /dev/null +++ b/sal/osl/os2/profile.c @@ -0,0 +1,2298 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: profile.c,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "system.h" + +// YD #define min(a,b) (((a) < (b)) ? (a) : (b)) + +#include <osl/security.h> +#include <osl/diagnose.h> +#include <osl/profile.h> +#include <osl/process.h> +#include <osl/thread.h> +#include <osl/file.h> + +#define LINES_INI 32 +#define LINES_ADD 10 +#define SECTIONS_INI 5 +#define SECTIONS_ADD 3 +#define ENTRIES_INI 5 +#define ENTRIES_ADD 3 + + +#define STR_INI_EXTENSION ".ini" +#define STR_INI_METAHOME "?~" +#define STR_INI_METASYS "?$" +#define STR_INI_METACFG "?^" +#define STR_INI_METAINS "?#" + +#define STR_INI_BOOLYES "yes" +#define STR_INI_BOOLON "on" +#define STR_INI_BOOLONE "1" +#define STR_INI_BOOLNO "no" +#define STR_INI_BOOLOFF "off" +#define STR_INI_BOOLZERO "0" + +#define FLG_USER 0x00FF +#define FLG_AUTOOPEN 0x0100 +#define FLG_MODIFIED 0x0200 + +#define SVERSION_LOCATION STR_INI_METACFG +#define SVERSION_FALLBACK STR_INI_METASYS +#define SVERSION_NAME "sversion" +#define SVERSION_SECTION "Versions" +#define SVERSION_SOFFICE "StarOffice" +#define SVERSION_PROFILE "soffice.ini" +#define SVERSION_OPTION "userid:" +#define SVERSION_DIRS { "bin", "program" } +#define SVERSION_USER "user" + +#define _BUILD_STR_(n) # n +#define BUILD_STR(n) _BUILD_STR_(n) + +/* implemented in file.c */ +extern oslFileError FileURLToPath( char *, size_t, rtl_uString* ); + +/*****************************************************************************/ +/* Data Type Definition */ +/*****************************************************************************/ + +typedef struct _osl_TStamp +{ + FDATE m_Date; + FTIME m_Time; +} osl_TStamp; + +typedef enum _osl_TLockMode +{ + un_lock, read_lock, write_lock +} osl_TLockMode; + +typedef struct _osl_TFile +{ + HFILE m_Handle; +/* + sal_Char* m_pReadPtr; + sal_Char m_ReadBuf[512]; + sal_Char* m_pWritePtr; + sal_Char m_WriteBuf[512]; +*/ + sal_Char* m_pReadPtr; + sal_Char m_ReadBuf[512]; +/* sal_Char* m_pWritePtr; */ +/* sal_Char m_WriteBuf[512]; */ + sal_Char* m_pWriteBuf; + sal_uInt32 m_nWriteBufLen; + sal_uInt32 m_nWriteBufFree; +} osl_TFile; + +typedef struct _osl_TProfileEntry +{ + sal_uInt32 m_Line; + sal_uInt32 m_Offset; + sal_uInt32 m_Len; +} osl_TProfileEntry; + +typedef struct _osl_TProfileSection +{ + sal_uInt32 m_Line; + sal_uInt32 m_Offset; + sal_uInt32 m_Len; + sal_uInt32 m_NoEntries; + sal_uInt32 m_MaxEntries; + osl_TProfileEntry* m_Entries; +} osl_TProfileSection; + + +/* + Profile-data structure hidden behind oslProfile: +*/ +typedef struct _osl_TProfileImpl +{ + sal_uInt32 m_Flags; + osl_TFile* m_pFile; + osl_TStamp m_Stamp; + //sal_Char m_Filename[_MAX_PATH + 1]; + sal_uInt32 m_NoLines; + sal_uInt32 m_MaxLines; + sal_uInt32 m_NoSections; + sal_uInt32 m_MaxSections; + sal_Char** m_Lines; + rtl_uString *m_strFileName; + osl_TProfileSection* m_Sections; + HINI m_hIni; +} osl_TProfileImpl; + + +/*****************************************************************************/ +/* Static Module Function Declarations */ +/*****************************************************************************/ + +//static osl_TFile* openFile(rtl_uString* pszFilename, sal_Bool bWriteable); +//static osl_TStamp closeFile(osl_TFile* pFile); +static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags ); +static osl_TStamp closeFileImpl(osl_TFile* pFile); +static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode); +static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate); +static osl_TStamp getFileStamp(osl_TFile* pFile); + +static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen); +static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine); +static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen); +static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line); +static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo); +static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo); +static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection, + sal_uInt32 NoEntry, sal_uInt32 Line, + const sal_Char* Entry, sal_uInt32 Len); +static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection, + int Line, const sal_Char* Entry, sal_uInt32 Len); +static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry); +static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len); +static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection); +static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section, + const sal_Char* Entry, sal_uInt32 *pNoEntry); +static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile); +static sal_Bool storeProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile, sal_Bool bCleanup); +static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable); +static sal_Bool releaseProfile(osl_TProfileImpl* pProfile); +static sal_Bool lookupProfile(const sal_Char *pszPath, const sal_Char *pszFile, sal_Char *pPath); + + +static sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName); + +sal_Bool SAL_CALL osl_getFullPath(rtl_uString* pszFilename, sal_Char* pszPath, sal_uInt32 MaxLen) +{ + return NO_ERROR == DosQueryPathInfo( (PCSZ)pszFilename, FIL_QUERYFULLNAME, pszPath, MaxLen); +} + + + +/*****************************************************************************/ +/* Exported Module Functions */ +/*****************************************************************************/ + +oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, sal_uInt32 Flags) +{ + osl_TFile* pFile; + osl_TProfileImpl* pProfile; + rtl_uString *FileName=NULL; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_openProfile\n"); +#endif + OSL_VERIFY(strProfileName); + +/* if (rtl_uString_getLength(strProfileName) == 0 ) + { + OSL_VERIFY(osl_getProfileName(NULL, NULL, &FileName)); + } + else +*/ + { + rtl_uString_assign(&FileName, strProfileName); + } + + osl_getSystemPathFromFileURL(FileName, &FileName); + +#ifdef DEBUG_OSL_PROFILE + Flags=osl_Profile_FLUSHWRITE; + + // OSL_TRACE("opening '%s'\n",FileName); + if ( Flags == osl_Profile_DEFAULT ) + { + OSL_TRACE("with osl_Profile_DEFAULT \n"); + } + if ( Flags & osl_Profile_SYSTEM ) + { + OSL_TRACE("with osl_Profile_SYSTEM \n"); + } + if ( Flags & osl_Profile_READLOCK ) + { + OSL_TRACE("with osl_Profile_READLOCK \n"); + } + if ( Flags & osl_Profile_WRITELOCK ) + { + OSL_TRACE("with osl_Profile_WRITELOCK \n"); + } +/* if ( Flags & osl_Profile_READWRITE ) */ +/* { */ +/* OSL_TRACE("with osl_Profile_READWRITE \n"); */ +/* } */ + if ( Flags & osl_Profile_FLUSHWRITE ) + { + OSL_TRACE("with osl_Profile_FLUSHWRITE \n"); + } +#endif + + if ((! (Flags & osl_Profile_SYSTEM)) && + ((pFile = openFileImpl(FileName, (Flags & osl_Profile_WRITELOCK) ? sal_True : sal_False)) == NULL)) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_openProfile [not opened]\n"); +#endif + if( FileName) + rtl_uString_release( FileName); + + return (NULL); + } + + pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl)); + + pProfile->m_Flags = Flags & FLG_USER; + osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName); +// rtl_uString_assign(&pProfile->m_strFileName, strProfileName); + + if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK)) + pProfile->m_pFile = pFile; + + pProfile->m_Stamp = getFileStamp(pFile); + + loadProfile(pFile, pProfile); + + if (pProfile->m_pFile == NULL) + closeFileImpl(pFile); + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_openProfile [ok]\n"); +#endif + if( FileName) + rtl_uString_release( FileName); + + return pProfile; +} + +sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile) +{ + osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_closeProfile\n"); +#endif + + if ( pProfile == 0 ) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_closeProfile [profile==0]\n"); +#endif + return sal_False; + } + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + pProfile = acquireProfile(Profile,sal_True); + + if ( pProfile != 0 ) + { + if ( !( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) ) + { +/* if (pProfile->m_pFile == NULL) */ +/* pProfile->m_pFile = openFileImpl(pProfile->m_Filename, sal_True); */ + + storeProfile(pProfile->m_pFile, pProfile, sal_False); + } + } + else + { + pProfile = acquireProfile(Profile,sal_False); + } + + if ( pProfile == 0 ) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_closeProfile [pProfile==0]\n"); +#endif + return sal_False; + } + + if (pProfile->m_pFile != NULL) + closeFileImpl(pProfile->m_pFile); + } + + pProfile->m_pFile = NULL; + rtl_uString_release(pProfile->m_strFileName); + pProfile->m_strFileName = NULL; + + /* release whole profile data types memory */ + if ( pProfile->m_NoLines > 0) + { + unsigned int index=0; + if ( pProfile->m_Lines != 0 ) + { + for ( index = 0 ; index < pProfile->m_NoLines ; ++index) + { + if ( pProfile->m_Lines[index] != 0 ) + { + free(pProfile->m_Lines[index]); + } + } + free(pProfile->m_Lines); + } + if ( pProfile->m_Sections != 0 ) + { + /*osl_TProfileSection* pSections=pProfile->m_Sections;*/ + for ( index = 0 ; index < pProfile->m_NoSections ; ++index ) + { + if ( pProfile->m_Sections[index].m_Entries != 0 ) + { + free(pProfile->m_Sections[index].m_Entries); + } + } + free(pProfile->m_Sections); + } + + } + free(pProfile); + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_closeProfile [ok]\n"); +#endif + return (sal_True); +} + +sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile) +{ + osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile; + osl_TFile* pFile; + sal_Bool bRet = sal_False; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_flushProfile()\n"); +#endif + + if ( pProfile == 0 ) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n"); +#endif + return sal_False; + } + + pFile = pProfile->m_pFile; + if ( !( pFile != 0 && pFile->m_Handle >= 0 ) ) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_flushProfile() [invalid file]\n"); +#endif + return sal_False; + } + + if ( pProfile->m_Flags & FLG_MODIFIED ) + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("swapping to storeprofile\n"); +#endif + bRet = storeProfile(pFile,pProfile,sal_False); + } + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_flushProfile() [ok]\n"); +#endif + return bRet; +} + +sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile, + const sal_Char* pszSection, const sal_Char* pszEntry, + sal_Char* pszString, sal_uInt32 MaxLen, + const sal_Char* pszDefault) +{ + sal_uInt32 NoEntry; + const sal_Char* pStr = 0; + osl_TProfileSection* pSec; + osl_TProfileImpl* pProfile = 0; + + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_readProfileString\n"); +#endif + + pProfile = acquireProfile(Profile, sal_False); + + if (pProfile == NULL) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_readProfileString [pProfile==0]\n"); +#endif + + + return (sal_False); + } + + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) && + (NoEntry < pSec->m_NoEntries) && + ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line], + '=')) != NULL)) + pStr++; + else + pStr = pszDefault; + + if ( pStr != 0 ) + { + pStr = stripBlanks(pStr, NULL); + MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr); + pStr = stripBlanks(pStr, &MaxLen); + strncpy(pszString, pStr, MaxLen); + pszString[MaxLen] = '\0'; + } + } + else + PrfQueryProfileString(pProfile->m_hIni, (PCSZ)pszSection, + (PCSZ)pszEntry, (PCSZ)pszDefault, + pszString, MaxLen); + + releaseProfile(pProfile); + + if ( pStr == 0 ) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_readProfileString [pStr==0]\n"); +#endif + + + return (sal_False); + } + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_readProfileString [ok]\n"); +#endif + + return (sal_True); +} + + +sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile, + const sal_Char* pszSection, const sal_Char* pszEntry, + sal_Bool Default) +{ + sal_Char Line[32]; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_readProfileBool\n"); +#endif + + if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), "")) + { + if ((stricmp(Line, STR_INI_BOOLYES) == 0) || + (stricmp(Line, STR_INI_BOOLON) == 0) || + (stricmp(Line, STR_INI_BOOLONE) == 0)) + Default = sal_True; + else + if ((stricmp(Line, STR_INI_BOOLNO) == 0) || + (stricmp(Line, STR_INI_BOOLOFF) == 0) || + (stricmp(Line, STR_INI_BOOLZERO) == 0)) + Default = sal_False; + } + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_readProfileBool [ok]\n"); +#endif + + return (Default); +} + + +sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile, + const sal_Char* pszSection, const sal_Char* pszEntry, + sal_uInt32 FirstId, const sal_Char* Strings[], + sal_uInt32 Default) +{ + sal_uInt32 i; + sal_Char Line[256]; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_readProfileIdent\n"); +#endif + + if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), "")) + { + i = 0; + while (Strings[i] != NULL) + { + if (stricmp(Line, Strings[i]) == 0) + { + Default = i + FirstId; + break; + } + i++; + } + } + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_readProfileIdent [ok]\n"); +#endif + return (Default); +} + + +sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile, + const sal_Char* pszSection, const sal_Char* pszEntry, + const sal_Char* pszString) +{ + sal_uInt32 i; + sal_Bool bRet = sal_False; + sal_uInt32 NoEntry; + const sal_Char* pStr; + sal_Char Line[4096]; + osl_TProfileSection* pSec; + osl_TProfileImpl* pProfile = 0; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_writeProfileString\n"); +#endif + + pProfile = acquireProfile(Profile, sal_True); + + if (pProfile == NULL) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n"); +#endif + return (sal_False); + } + + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL) + { + Line[0] = '\0'; + addLine(pProfile, Line); + + Line[0] = '['; + strcpy(&Line[1], pszSection); + Line[1 + strlen(pszSection)] = ']'; + Line[2 + strlen(pszSection)] = '\0'; + + if (((pStr = addLine(pProfile, Line)) == NULL) || + (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection)))) + { + releaseProfile(pProfile); +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_writeProfileString [not added]\n"); +#endif + return (sal_False); + } + + pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1]; + NoEntry = pSec->m_NoEntries; + } + + Line[0] = '\0'; + strcpy(&Line[0], pszEntry); + Line[0 + strlen(pszEntry)] = '='; + strcpy(&Line[1 + strlen(pszEntry)], pszString); + + if (NoEntry >= pSec->m_NoEntries) + { + if (pSec->m_NoEntries > 0) + i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1; + else + i = pSec->m_Line + 1; + + if (((pStr = insertLine(pProfile, Line, i)) == NULL) || + (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry)))) + { + releaseProfile(pProfile); +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_writeProfileString [not inserted]\n"); +#endif + return (sal_False); + } + + pProfile->m_Flags |= FLG_MODIFIED; + } + else + { + i = pSec->m_Entries[NoEntry].m_Line; + free(pProfile->m_Lines[i]); + pProfile->m_Lines[i] = strdup(Line); + setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry)); + + pProfile->m_Flags |= FLG_MODIFIED; + } + } + else + PrfWriteProfileString(pProfile->m_hIni, (PCSZ)pszSection, + (PCSZ)pszEntry, (PCSZ)pszString); + + bRet = releaseProfile(pProfile); +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_writeProfileString [ok]\n"); +#endif + return bRet; +} + + +sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile, + const sal_Char* pszSection, const sal_Char* pszEntry, + sal_Bool Value) +{ + sal_Bool bRet = sal_False; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_writeProfileBool\n"); +#endif + + if (Value) + bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE); + else + bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO); + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_writeProfileBool [ok]\n"); +#endif + + return bRet; +} + + +sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile, + const sal_Char* pszSection, const sal_Char* pszEntry, + sal_uInt32 FirstId, const sal_Char* Strings[], + sal_uInt32 Value) +{ + int i, n; + sal_Bool bRet = sal_False; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_writeProfileIdent\n"); +#endif + + for (n = 0; Strings[n] != NULL; n++); + + if ((i = Value - FirstId) >= n) + bRet=sal_False; + else + bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]); + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_writeProfileIdent\n"); +#endif + return bRet; +} + + +sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile, + const sal_Char *pszSection, const sal_Char *pszEntry) +{ + sal_uInt32 NoEntry; + osl_TProfileSection* pSec; + osl_TProfileImpl* pProfile = 0; + sal_Bool bRet = sal_False; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_removeProfileEntry\n"); +#endif + + pProfile = acquireProfile(Profile, sal_True); + + if (pProfile == NULL) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n"); +#endif + + + return (sal_False); + } + + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) && + (NoEntry < pSec->m_NoEntries)) + { + removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line); + removeEntry(pSec, NoEntry); + if (pSec->m_NoEntries == 0) + { + removeLine(pProfile, pSec->m_Line); + + /* remove any empty separation line */ + if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0')) + removeLine(pProfile, pSec->m_Line - 1); + + removeSection(pProfile, pSec); + } + + pProfile->m_Flags |= FLG_MODIFIED; + } + } + else + PrfWriteProfileString(pProfile->m_hIni, (PCSZ)pszSection, (PCSZ)pszEntry, NULL); + + bRet = releaseProfile(pProfile); +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_removeProfileEntry [ok]\n"); +#endif + return bRet; +} + + +sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection, + sal_Char* pszBuffer, sal_uInt32 MaxLen) +{ + sal_uInt32 i, n = 0; + sal_uInt32 NoEntry; + osl_TProfileSection* pSec; + osl_TProfileImpl* pProfile = 0; + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In osl_getProfileSectionEntries\n"); +#endif + + pProfile = acquireProfile(Profile, sal_False); + + if (pProfile == NULL) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n"); +#endif + + + return (0); + } + + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL) + { + if (MaxLen != 0) + { + for (i = 0; i < pSec->m_NoEntries; i++) + { + if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen) + { + strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line] + [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len); + n += pSec->m_Entries[i].m_Len; + pszBuffer[n++] = '\0'; + } + else + break; + + } + + pszBuffer[n++] = '\0'; + } + else + { + for (i = 0; i < pSec->m_NoEntries; i++) + n += pSec->m_Entries[i].m_Len + 1; + + n += 1; + } + } + else + n = 0; + } + else + n = PrfQueryProfileString(pProfile->m_hIni, (PCSZ)pszSection, NULL, NULL, + pszBuffer, MaxLen ); + + releaseProfile(pProfile); + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n"); +#endif + + return (n); +} + +sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen) +{ + sal_uInt32 i, n = 0; + osl_TProfileSection* pSec; + osl_TProfileImpl* pProfile = acquireProfile(Profile, sal_False); + + if (pProfile == NULL) + return (0); + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if (MaxLen != 0) + { + for (i = 0; i < pProfile->m_NoSections; i++) + { + pSec = &pProfile->m_Sections[i]; + + if ((n + pSec->m_Len + 1) < MaxLen) + { + strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], + pSec->m_Len); + n += pSec->m_Len; + pszBuffer[n++] = '\0'; + } + else + break; + } + + pszBuffer[n++] = '\0'; + } + else + { + for (i = 0; i < pProfile->m_NoSections; i++) + n += pProfile->m_Sections[i].m_Len + 1; + + n += 1; + } + } + else + n = PrfQueryProfileString(pProfile->m_hIni, NULL, NULL, NULL, + pszBuffer, MaxLen ); + + releaseProfile(pProfile); + + return (n); +} + +#if 0 // YD +sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName) +{ + sal_Bool bFailed; + sal_Char File[_MAX_PATH]; + sal_Char Path[_MAX_PATH]; + sal_uInt32 nFileLen; + sal_uInt32 nPathLen = 0; + + rtl_uString * strTmp = NULL; + oslFileError nError; + + /* build file name */ + if (strName && strName->length) + { + if(strName->length >= _MAX_PATH) + return sal_False; + + strcpy(File, (char*)strName->buffer); + nFileLen = strName->length; + + if (rtl_ustr_indexOfChar( File, L'.' ) == -1) + { + if (nFileLen + strlen(STR_INI_EXTENSION) >= _MAX_PATH) + return sal_False; + + /* add default extension */ + strcpy(File + nFileLen, STR_INI_EXTENSION); + nFileLen += strlen(STR_INI_EXTENSION); + } + } + else + { + rtl_uString *strProgName = NULL; + sal_Unicode *pProgName; + sal_Int32 nOffset = 0; + sal_Int32 nLen; + sal_Int32 nPos; + + if (osl_getExecutableFile(&strProgName) != osl_Process_E_None) + return sal_False; + + /* remove path and extension from filename */ + pProgName = strProgName->buffer; + nLen = strProgName->length ; + + if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1) + nOffset = nPos + 1; + else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1) + nOffset = nPos + 1; + + if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 ) + nLen -= 4; + + if ((nFileLen = nLen - nOffset) >= _MAX_PATH) + return sal_False; + + strncpy(File, pProgName + nOffset, nFileLen); + + if (nFileLen + strlen(STR_INI_EXTENSION) >= _MAX_PATH) + return sal_False; + + /* add default extension */ + strcpy(File + nFileLen, STR_INI_EXTENSION); + nFileLen += strlen(STR_INI_EXTENSION); + + rtl_uString_release( strProgName ); + } + + if (File[0] == 0) + return sal_False; + + /* build directory path */ + if (strPath && strPath->length) + { + sal_Unicode *pPath = rtl_uString_getStr(strPath); + sal_Int32 nLen = rtl_uString_getLength(strPath); + + if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) && + ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/'))) + { + rtl_uString * strHome = NULL; + oslSecurity security = osl_getCurrentSecurity(); + + bFailed = ! osl_getHomeDir(security, &strHome); + osl_freeSecurityHandle(security); + + if (bFailed) return (sal_False); + + if (strHome->length >= _MAX_PATH) + return sal_False; + + strcpy( Path, strHome->buffer); + nPathLen = strHome->length; + + if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) + { + pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME); + nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME); + + if (nLen + nPathLen >= _MAX_PATH) + return sal_False; + + strcpy(Path + nPathLen, pPath); + nPathLen += nLen; + } + + rtl_uString_release(strHome); + } + + else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) && + ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/'))) + { + rtl_uString * strConfig = NULL; + oslSecurity security = osl_getCurrentSecurity(); + + bFailed = ! osl_getConfigDir(security, &strConfig); + osl_freeSecurityHandle(security); + + if (bFailed) return (sal_False); + + if (strConfig->length >= _MAX_PATH) + return sal_False; + + strcpy( Path, strConfig->buffer); + nPathLen = strConfig->length; + + if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) + { + pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG); + nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG); + + if (nLen + nPathLen >= _MAX_PATH) + return sal_False; + + strcpy(Path + nPathLen, pPath); + nPathLen += nLen; + } + + rtl_uString_release(strConfig); + } + + else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) && + ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/'))) + { + if (((nPathLen = GetWindowsDirectoryW(Path, _MAX_PATH)) == 0) || (nPathLen >= _MAX_PATH)) + return (sal_False); + + if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) + { + pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS); + nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS); + + if (nLen + nPathLen >= MAX_PATH) + return sal_False; + + strcpy(Path + nPathLen, pPath); + nPathLen += nLen; + } + } + + else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) && + ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') || + (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) ) + { + if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), File, Path)) + return (sal_False); + + nPathLen = strlen(Path); + } + + else if(nLen < MAX_PATH) + { + strcpy(Path, pPath); + nPathLen = strlen(Path); + } + else + return sal_False; + } + else + { + rtl_uString * strConfigDir = NULL; + oslSecurity security = osl_getCurrentSecurity(); + + bFailed = ! osl_getConfigDir(security, &strConfigDir); + osl_freeSecurityHandle(security); + + if (bFailed) return (sal_False); + if (strConfigDir->length >= MAX_PATH) + return sal_False; + + strcpy(Path, strConfigDir->buffer); + nPathLen = strConfigDir->length; + } + + if (nPathLen && (Path[nPathLen - 1] != L'/') && (Path[nPathLen - 1] != L'\\')) + { + Path[nPathLen++] = L'\\'; + Path[nPathLen] = 0; + } + + if (nPathLen + nFileLen >= MAX_PATH) + return sal_False; + + /* append file name */ + strcpy(Path + nPathLen, File); + nPathLen += nFileLen; + + /* copy filename */ + rtl_uString_newFromStr_WithLength(&strTmp, Path, nPathLen); + nError = osl_getFileURLFromSystemPath(strTmp, strProfileName); + rtl_uString_release(strTmp); + + return nError == osl_File_E_None; +} +#endif // 0 // YD + + +/*****************************************************************************/ +/* Static Module Functions */ +/*****************************************************************************/ + +static osl_TStamp getFileStamp(osl_TFile* pFile) +{ + osl_TStamp FileTime; + FILESTATUS3 FileStatus; + sal_uInt32 Bytes; + + Bytes = sizeof( FILESTATUS3 ); + if ( (!pFile->m_Handle) || + DosQueryFileInfo(pFile->m_Handle, FIL_STANDARD, &FileStatus, Bytes)) + memset(&FileTime, 0, sizeof(FileTime)); + else + { + FileTime.m_Date = FileStatus.fdateLastWrite; + FileTime.m_Time = FileStatus.ftimeLastWrite; + } + + return (FileTime); +} + +static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode) +{ + sal_uInt32 status = 1; + FILELOCK Lock; + + if (!pFile->m_Handle) + return (sal_False); + + Lock.lOffset = 0; + Lock.lRange = 0xFFFFFFFF; + + switch (eMode) + { + case un_lock: + status = DosSetFileLocks(pFile->m_Handle, &Lock, NULL, 1000, 0); + break; + + case read_lock: + status = DosSetFileLocks(pFile->m_Handle, NULL, &Lock, 1000, 1); + break; + + case write_lock: + status = DosSetFileLocks(pFile->m_Handle, NULL, &Lock, 1000, 0); + break; + } + + return (status == 0); +} + +//static osl_TFile* openFile(rtl_uString* pszFilename, sal_Bool bWriteable) +static osl_TFile* openFileImpl(rtl_uString *ustrFileName, oslProfileOption ProfileFlags ) +{ + sal_uInt32 action; + APIRET rc; + osl_TFile* pFile = (osl_TFile*)calloc(1, sizeof(osl_TFile)); + + ULONG attributes; + ULONG flags; + ULONG mode; + sal_Bool bWriteable = sal_False; + rtl_String* strFileName=0; + sal_Char* pszFileName=0; + + /* check parameters */ + OSL_ASSERT( ustrFileName ); + + rtl_uString2String( &strFileName, + rtl_uString_getStr(ustrFileName), + rtl_uString_getLength(ustrFileName), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszFileName = rtl_string_getStr(strFileName); + +/* if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE | osl_Profile_READWRITE ) )*/ + if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) ) + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("setting bWriteable to TRUE\n"); +#endif + bWriteable=sal_True; + } + + if (bWriteable) + { + flags = FILE_NORMAL | FILE_ARCHIVED; + attributes = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; + mode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE; + } + else + { + flags = FILE_NORMAL; + attributes = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; + mode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY; + } + + if (rc = DosOpen((PCSZ)pszFileName, &pFile->m_Handle, &action, 0, flags, attributes, mode, NULL)) + { + if (rc == ERROR_TOO_MANY_OPEN_FILES) + { + LONG fhToAdd = 10; + ULONG fhOld = 0; + rc = DosSetRelMaxFH(&fhToAdd, &fhOld); + rc = DosOpen((PCSZ)pszFileName, &pFile->m_Handle, &action, 0, flags, attributes, mode, NULL); + } + } + + if ( (rc != NO_ERROR) && bWriteable) + { + free(pFile); + rtl_string_release(strFileName); + return (NULL); + } + + rtl_string_release(strFileName); + + pFile->m_pWriteBuf=0; + pFile->m_nWriteBufFree=0; + pFile->m_nWriteBufLen=0; + + if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) ) + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("locking '%s' file\n",pszFilename); +#endif + + lockFile(pFile, bWriteable ? write_lock : read_lock); + } + + /* mfe: new WriteBuf obsolete */ +/* pFile->m_pWritePtr = pFile->m_Buf;*/ +/* pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);*/ + + return (pFile); +} + +//static osl_TStamp closeFile(osl_TFile* pFile) +static osl_TStamp closeFileImpl(osl_TFile* pFile) +{ + osl_TStamp stamp = {0, 0}; + + if ( pFile == 0 ) + { + return stamp; + } + + if (pFile->m_Handle) + { + /* mfe: new WriteBuf obsolete */ + /* we just closing the file here, DO NOT write, it has to be handled in higher levels */ + //if (pFile->m_pWritePtr > pFile->m_WriteBuf) + //{ + // sal_uInt32 Bytes; + + // DosWrite(pFile->m_Handle, pFile->m_WriteBuf, + // pFile->m_pWritePtr - pFile->m_WriteBuf, + // &Bytes); + //} + + stamp = getFileStamp(pFile); + + lockFile(pFile, un_lock); + + DosClose(pFile->m_Handle); + } + + if ( pFile->m_pWriteBuf != 0 ) + { + free(pFile->m_pWriteBuf); + } + + free(pFile); + + return(stamp); +} + +static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate) +{ + if (pFile->m_Handle) + { + sal_uInt32 Position; + + /* mfe: new WriteBuf obsolete */ + /* we just closing the file here, DO NOT write, it has to be handled in higher levels */ + /* if (pFile->m_pWritePtr > pFile->m_WriteBuf) + { + sal_uInt32 Bytes; + + DosWrite(pFile->m_Handle, pFile->m_WriteBuf, + pFile->m_pWritePtr - pFile->m_WriteBuf, + &Bytes); + + pFile->m_pWritePtr = pFile->m_WriteBuf; + } */ + + pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf); + + DosSetFilePtr(pFile->m_Handle, 0, FILE_BEGIN, &Position); + + if (bTruncate) + DosSetFileSize(pFile->m_Handle, 0); + } + + return (sal_True); +} + +static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen) +{ + int Free, Bytes; + sal_Char* pChr; + sal_Char* pLine = (sal_Char *)pszLine; + sal_uInt32 Max; + + if (pFile->m_Handle == 0) + return (sal_False); + + MaxLen -= 1; + + do + { + Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf); + + if (Bytes <= 1) + { + /* refill buffer */ + memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes); + pFile->m_pReadPtr = pFile->m_ReadBuf; + + Free = sizeof(pFile->m_ReadBuf) - Bytes; + + if (DosRead(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max)) + { + *pLine = '\0'; + return (sal_False); + } + + if (Max < Free) + { + if ((Max == 0) && (pLine == pszLine)) + { + *pLine = '\0'; + return (sal_False); + } + + pFile->m_ReadBuf[Bytes + Max] = '\0'; + } + } + + for (pChr = pFile->m_pReadPtr; + (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') && + (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1)); + pChr++); + + Max = min(pChr - pFile->m_pReadPtr, MaxLen); + memcpy(pLine, pFile->m_pReadPtr, Max); + MaxLen -= Max; + pLine += Max; + + if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1)) + { + if (*pChr != '\0') + { + if ((pChr[0] == '\r') && (pChr[1] == '\n')) + pChr += 2; + else + pChr += 1; + } + + if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) && + (*pChr == '\0')) + pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf); + + *pLine = '\0'; + + /* setting MaxLen to -1 indicates terminating read loop */ + MaxLen = -1; + } + + pFile->m_pReadPtr = pChr; + } + while (MaxLen > 0); + + return (sal_True); +} + +static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine) +{ + unsigned int Len = strlen(pszLine); + +#ifdef DEBUG_OSL_PROFILE + int strLen=0; +#endif + + if ( pFile == 0 || pFile->m_Handle < 0 ) + { + return (sal_False); + } + + if ( pFile->m_pWriteBuf == 0 ) + { + pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3); + pFile->m_nWriteBufLen = Len+3; + pFile->m_nWriteBufFree = Len+3; + } + else + { + if ( pFile->m_nWriteBufFree <= Len + 3 ) + { + sal_Char* pTmp; + + pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) ); + if ( pTmp == 0 ) + { + return sal_False; + } + pFile->m_pWriteBuf = pTmp; + pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len ); + pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2; + memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree); + } + } + + + + memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1); +#ifdef DEBUG_OSL_PROFILE + strLen = strlen(pFile->m_pWriteBuf); +#endif + pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r'; + pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n'; + pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0'; + + pFile->m_nWriteBufFree-=Len+2; + +#ifdef DEBUG_OSL_PROFILE +/* OSL_TRACE("File Buffer in _putLine '%s' '%i'(%i)\n",pFile->m_pWriteBuf,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/ +#endif + + return (sal_True); +} + +/* platform specific end */ + +static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen) +{ + if ( (pLen != NULL) && ( *pLen != 0 ) ) + { + while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t')) + (*pLen)--; + + while ((*String == ' ') || (*String == '\t')) + { + String++; + (*pLen)--; + } + } + else + while ((*String == ' ') || (*String == '\t')) + String++; + + return (String); +} + +static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line) +{ + if (pProfile->m_NoLines >= pProfile->m_MaxLines) + { + if (pProfile->m_Lines == NULL) + { + pProfile->m_MaxLines = LINES_INI; + pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *)); + } + else + { + pProfile->m_MaxLines += LINES_ADD; + pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines, + pProfile->m_MaxLines * sizeof(sal_Char *)); + } + + if (pProfile->m_Lines == NULL) + { + pProfile->m_NoLines = 0; + pProfile->m_MaxLines = 0; + return (NULL); + } + + } + + pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line); + + return (pProfile->m_Lines[pProfile->m_NoLines - 1]); +} + +static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo) +{ + if (pProfile->m_NoLines >= pProfile->m_MaxLines) + { + if (pProfile->m_Lines == NULL) + { + pProfile->m_MaxLines = LINES_INI; + pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *)); + } + else + { + pProfile->m_MaxLines += LINES_ADD; + pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines, + pProfile->m_MaxLines * sizeof(sal_Char *)); + } + + if (pProfile->m_Lines == NULL) + { + pProfile->m_NoLines = 0; + pProfile->m_MaxLines = 0; + return (NULL); + } + + } + + LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo; + + if (LineNo < pProfile->m_NoLines) + { + sal_uInt32 i, n; + osl_TProfileSection* pSec; + + memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo], + (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *)); + + /* adjust line references */ + for (i = 0; i < pProfile->m_NoSections; i++) + { + pSec = &pProfile->m_Sections[i]; + + if (pSec->m_Line >= LineNo) + pSec->m_Line++; + + for (n = 0; n < pSec->m_NoEntries; n++) + if (pSec->m_Entries[n].m_Line >= LineNo) + pSec->m_Entries[n].m_Line++; + } + } + + pProfile->m_NoLines++; + + pProfile->m_Lines[LineNo] = strdup(Line); + + return (pProfile->m_Lines[LineNo]); +} + +static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo) +{ + if (LineNo < pProfile->m_NoLines) + { + free(pProfile->m_Lines[LineNo]); + if (pProfile->m_NoLines - LineNo > 1) + { + sal_uInt32 i, n; + osl_TProfileSection* pSec; + + memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1], + (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *)); + + /* adjust line references */ + for (i = 0; i < pProfile->m_NoSections; i++) + { + pSec = &pProfile->m_Sections[i]; + + if (pSec->m_Line > LineNo) + pSec->m_Line--; + + for (n = 0; n < pSec->m_NoEntries; n++) + if (pSec->m_Entries[n].m_Line > LineNo) + pSec->m_Entries[n].m_Line--; + } + } + else + { + pProfile->m_Lines[LineNo] = 0; + } + + pProfile->m_NoLines--; + } + + return; +} + +static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection, + sal_uInt32 NoEntry, sal_uInt32 Line, + const sal_Char* Entry, sal_uInt32 Len) +{ + Entry = stripBlanks(Entry, &Len); + pSection->m_Entries[NoEntry].m_Line = Line; + pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line]; + pSection->m_Entries[NoEntry].m_Len = Len; + + return; +} + +static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection, + int Line, const sal_Char* Entry, sal_uInt32 Len) +{ + if (pSection != NULL) + { + if (pSection->m_NoEntries >= pSection->m_MaxEntries) + { + if (pSection->m_Entries == NULL) + { + pSection->m_MaxEntries = ENTRIES_INI; + pSection->m_Entries = (osl_TProfileEntry *)malloc( + pSection->m_MaxEntries * sizeof(osl_TProfileEntry)); + } + else + { + pSection->m_MaxEntries += ENTRIES_ADD; + pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries, + pSection->m_MaxEntries * sizeof(osl_TProfileEntry)); + } + + if (pSection->m_Entries == NULL) + { + pSection->m_NoEntries = 0; + pSection->m_MaxEntries = 0; + return (sal_False); + } + } + + pSection->m_NoEntries++; + + Entry = stripBlanks(Entry, &Len); + setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line, + Entry, Len); + + return (sal_True); + } + + return (sal_False); +} + +static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry) +{ + if (NoEntry < pSection->m_NoEntries) + { + if (pSection->m_NoEntries - NoEntry > 1) + memmove(&pSection->m_Entries[NoEntry], + &pSection->m_Entries[NoEntry + 1], + (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry)); + pSection->m_NoEntries--; + } + + return; +} + +static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len) +{ + if (pProfile->m_NoSections >= pProfile->m_MaxSections) + { + if (pProfile->m_Sections == NULL) + { + pProfile->m_MaxSections = SECTIONS_INI; + pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection)); + } + else + { + pProfile->m_MaxSections += SECTIONS_ADD; + pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections, + pProfile->m_MaxSections * sizeof(osl_TProfileSection)); + } + + if (pProfile->m_Sections == NULL) + { + pProfile->m_NoSections = 0; + pProfile->m_MaxSections = 0; + return (sal_False); + } + } + + pProfile->m_NoSections++; + + pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL; + pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0; + pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0; + + Section = (sal_Char *)stripBlanks(Section, &Len); + pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line; + pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line]; + pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len; + + return (sal_True); +} + +static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection) +{ + sal_uInt32 Section; + + if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections) + { + free (pSection->m_Entries); + if (pProfile->m_NoSections - Section > 1) + { + memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1], + (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection)); + } + else + { + pSection->m_Entries = 0; + } + + pProfile->m_NoSections--; + } + + return; +} + +static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section, + const sal_Char* Entry, sal_uInt32 *pNoEntry) +{ +static sal_uInt32 Sect = 0; + sal_uInt32 i, n; + sal_uInt32 Len; + const sal_Char* pStr; + osl_TProfileSection* pSec; + + Len = strlen(Section); + Section = (sal_Char *)stripBlanks(Section, &Len); + + n = Sect; + + for (i = 0; i < pProfile->m_NoSections; i++) + { + n %= pProfile->m_NoSections; + pSec = &pProfile->m_Sections[n]; + if ((Len == pSec->m_Len) && + (strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len) + == 0)) + break; + n++; + } + + Sect = n; + + if (i < pProfile->m_NoSections) + { + Len = strlen(Entry); + Entry = stripBlanks(Entry, &Len); + + *pNoEntry = pSec->m_NoEntries; + + for (i = 0; i < pSec->m_NoEntries; i++) + { + pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line] + [pSec->m_Entries[i].m_Offset]; + if ((Len == pSec->m_Entries[i].m_Len) && + (strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len) + == 0)) + { + *pNoEntry = i; + break; + } + } + } + else + pSec = NULL; + + return (pSec); +} + +static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile) +{ + sal_uInt32 i; + sal_Char* pStr; + sal_Char* pChar; + sal_Char Line[1024]; + + pProfile->m_NoLines = 0; + pProfile->m_NoSections = 0; + + OSL_VERIFY(rewindFile(pFile, sal_False)); + + while (getLine(pFile, Line, sizeof(Line))) + { + if (! addLine(pProfile, Line)) + return (sal_False); + } + + for (i = 0; i < pProfile->m_NoLines; i++) + { + pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL); + + if ((*pStr == '\0') || (*pStr == ';')) + continue; + + if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) || + ((pChar - pStr) <= 2)) + { + /* insert entry */ + + if (pProfile->m_NoSections < 1) + continue; + + if ((pChar = strchr(pStr, '=')) == NULL) + pChar = pStr + strlen(pStr); + + if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1], + i, pStr, pChar - pStr)) + return (sal_False); + } + else + { + /* new section */ + + if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1)) + return (sal_False); + } + } + + return (sal_True); +} + +static sal_Bool storeProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile, sal_Bool bCleanup) +{ + if (pProfile->m_Lines != NULL) + { + if (pProfile->m_Flags & FLG_MODIFIED) + { + sal_uInt32 i; + + OSL_VERIFY(rewindFile(pFile, sal_True)); + + for (i = 0; i < pProfile->m_NoLines; i++) + OSL_VERIFY(putLine(pFile, pProfile->m_Lines[i])); + + pProfile->m_Flags &= ~FLG_MODIFIED; + } + + if (bCleanup) + { + while (pProfile->m_NoLines > 0) + removeLine(pProfile, pProfile->m_NoLines - 1); + + free(pProfile->m_Lines); + pProfile->m_Lines = NULL; + pProfile->m_MaxLines = 0; + + while (pProfile->m_NoSections > 0) + removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]); + + free(pProfile->m_Sections); + pProfile->m_Sections = NULL; + pProfile->m_MaxSections = 0; + } + } + + return (sal_True); +} + +static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable) +{ + osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile; + oslProfileOption PFlags=0; + + + if ( bWriteable ) + { +/* PFlags = osl_Profile_DEFAULT | osl_Profile_READWRITE; */ + PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK; + } + else + { + PFlags = osl_Profile_DEFAULT; + } + + + if (pProfile == NULL) + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("AUTOOPEN MODE\n"); +#endif + + if ((pProfile = (osl_TProfileImpl*)osl_openProfile(NULL, PFlags)) != NULL ) + { + pProfile->m_Flags |= FLG_AUTOOPEN; + } + } + else + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("try to acquire\n"); +#endif + + + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if (! (pProfile->m_Flags & (osl_Profile_READLOCK | + osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE))) + { + osl_TStamp Stamp; +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("DEFAULT MODE\n"); +#endif + if (! (pProfile->m_pFile = openFileImpl(pProfile->m_strFileName, pProfile->m_Flags | PFlags))) + return NULL; + + Stamp = getFileStamp(pProfile->m_pFile); + + if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp))) + { + pProfile->m_Stamp = Stamp; + + loadProfile(pProfile->m_pFile, pProfile); + } + } + else + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("READ/WRITELOCK MODE\n"); +#endif + + + /* A readlock file could not be written */ + if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable) + { + return (NULL); + } + } + } + else + { + sal_Bool bWriteable = sal_False; + char pszFilename[PATH_MAX] = ""; + + if ( pProfile->m_strFileName != 0 && pProfile->m_strFileName->buffer[0] != 0 ) + FileURLToPath( pszFilename, PATH_MAX, pProfile->m_strFileName ); + /* hack: usualy you have a specific HAB, but NULL works here... */ + pProfile->m_hIni = PrfOpenProfile(NULL, (PCSZ)pszFilename); + if (! pProfile->m_hIni) + return (NULL); + } + } + + return (pProfile); +} + +static sal_Bool releaseProfile(osl_TProfileImpl* pProfile) +{ +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("In releaseProfile\n"); +#endif + + if ( pProfile == 0 ) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out releaseProfile [profile==0]\n"); +#endif + return sal_False; + } + + if (! (pProfile->m_Flags & osl_Profile_SYSTEM)) + { + if (pProfile->m_Flags & FLG_AUTOOPEN) + { +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out releaseProfile [AUTOOPEN]\n"); +#endif + return (osl_closeProfile((oslProfile)pProfile)); + } + else + { +#ifdef DEBUG_OSL_PROFILE + OSL_TRACE("DEFAULT MODE\n"); +#endif + if (! (pProfile->m_Flags & (osl_Profile_READLOCK | + osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE))) + { + if (pProfile->m_Flags & FLG_MODIFIED) + storeProfile(pProfile->m_pFile, pProfile, sal_False); + + closeFileImpl(pProfile->m_pFile); + pProfile->m_pFile = NULL; + } + } + } + else + PrfCloseProfile(pProfile->m_hIni); + +#ifdef TRACE_OSL_PROFILE + OSL_TRACE("Out releaseProfile [ok]\n"); +#endif + return (sal_True); +} + +#if 0 // YD + +static sal_Bool lookupProfile(const sal_Char *pszPath, const sal_Char *pszFile, sal_Char *pPath) +{ + sal_Char *pChr, *pStr; + sal_Char Path[_MAX_PATH] = ""; + sal_Char Product[132] = ""; + sal_Char Buffer[1024]; + + if (*pszPath == '"') + { + int i = 0; + + pszPath++; + + while ((*pszPath != '"') && (*pszPath != '\0')) + Product[i++] = *pszPath++; + + Product[i] = '\0'; + + if (*pszPath == '"') + pszPath++; + + if ( (*pszPath == '/') || (*pszPath == '\\') ) + { + pszPath++; + } + } + else + { + /* if we have not product identfication, do a special handling for soffice.ini */ + if (stricmp(SVERSION_PROFILE, pszFile) == 0) + { + sal_Char Profile[_MAX_PATH]; + sal_Char Dir[_MAX_PATH]; + oslProfile hProfile; + + /* open sversion.ini in the system directory, and try to locate the entry + with the highest version for StarOffice */ + if ((osl_getProfileName(SVERSION_FALLBACK, SVERSION_NAME, Profile, sizeof(Profile))) && + (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK))) + { + osl_getProfileSectionEntries(hProfile, SVERSION_SECTION, + Buffer, sizeof(Buffer)); + + for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1) + { + if ((strnicmp(pChr, SVERSION_SOFFICE, sizeof(SVERSION_SOFFICE) - 1) == 0) && + (stricmp(Product, pChr) < 0)) + { + osl_readProfileString(hProfile, SVERSION_SECTION, pChr, + Dir, sizeof(Dir), ""); + + /* check for existence of path */ + if (access(Dir, 0) >= 0) + strcpy(Product, pChr); + } + } + + osl_closeProfile(hProfile); + } + + /* open sversion.ini in the users directory, and try to locate the entry + with the highest version for StarOffice */ + if ((strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0) && + (osl_getProfileName(SVERSION_LOCATION, SVERSION_NAME, Profile, sizeof(Profile))) && + (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK))) + { + osl_getProfileSectionEntries(hProfile, SVERSION_SECTION, + Buffer, sizeof(Buffer)); + + for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1) + { + if ((strnicmp(pChr, SVERSION_SOFFICE, sizeof(SVERSION_SOFFICE) - 1) == 0) && + (stricmp(Product, pChr) < 0)) + { + osl_readProfileString(hProfile, SVERSION_SECTION, pChr, + Dir, sizeof(Dir), ""); + + /* check for existence of path */ + if (access(Dir, 0) >= 0) + strcpy(Product, pChr); + } + } + + osl_closeProfile(hProfile); + } + + /* remove any trailing build number */ + if ((pChr = strrchr(Product, '/')) != NULL) + *pChr = '\0'; + } + } + + + /* if we have an userid option eg. "-userid:rh[/usr/home/rh/staroffice]", + this will supercede all other locations */ + if (osl_getCommandArgs(Buffer, sizeof(Buffer)) == osl_Process_E_None) + { + sal_Char *pStart, *pEnd; + + for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1) + if (((*pChr == '-') || (*pChr == '+')) && + (strnicmp(pChr + 1, SVERSION_OPTION, sizeof(SVERSION_OPTION) - 1) == 0)) + { + if (((pStart = strchr(pChr + sizeof(SVERSION_OPTION), '[')) != NULL) && + ((pEnd = strchr(pStart + 1, ']')) != NULL)) + { + strncpy(Path, pStart + 1, pEnd - (pStart + 1)); + Path[pEnd - (pStart + 1)] = '\0'; + + /* build full path */ + if ((Path[strlen(Path) - 1] != '/') && (Path[strlen(Path) - 1] != '\\')) + { + strcat(Path, "\\"); + } + + pChr =&Path[strlen(Path)]; + if ( strlen(pszPath) <= 0 ) + { + strcat(Path,SVERSION_USER); + + if ( access(Path, 0) < 0 ) + { + *pChr='\0'; + } + } + else + { + strcat(Path, pszPath); + } + + break; + } + } + } + + if (strlen(Path) <= 0) + { + /* try to find the file in the directory of the executbale */ + if (osl_getExecutableFile(Path, sizeof(Path)) != osl_Process_E_None) + return (sal_False); + + /* seperate path from filename */ + if ((pChr = strrchr(Path, '\\')) == NULL) + if ((pChr = strrchr(Path, ':')) == NULL) + return (sal_False); + else + *pChr = '\0'; + else + *pChr = '\0'; + + /* if we have no product identification use the executable file name */ + if (strlen(Product) <= 0) + { + strcpy(Product, pChr + 1); + + /* remove extension */ + if ((pChr = strrchr(Product, '.')) != NULL) + *pChr = '\0'; + } + + /* remember last subdir */ + pStr = strrchr(Path, '\\'); + + strcat(Path, "\\"); + + if ( strlen(pszPath) <= 0 ) + { + strcat(Path, pszPath); + } + else + { + strcat(Path,pszPath); + } + + /* if file not exists, remove any specified subdirectories + like "bin" or "program" */ + if (((access(Path, 0) < 0) && (pStr != NULL)) || (strlen(pszPath) <= 0)) + { + static sal_Char *SubDirs[] = SVERSION_DIRS; + + int i = 0; + + for (i = 0; i < (sizeof(SubDirs) / sizeof(SubDirs[0])); i++) + if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0) + { + if ( strlen(pszPath) <= 0) + { + strcpy(pStr + 1,SVERSION_USER); + if ( access(Path, 0) < 0 ) + { + *(pStr+1)='\0'; + } + } + else + { + strcpy(pStr + 1, pszPath); + } + + break; + } + } + + pChr = &Path[strlen(Path)]; + if ((Path[strlen(Path) - 1] != '/') && (Path[strlen(Path) - 1] != '\\')) + strcat(Path, "\\"); + strcat(Path, pszFile); + + if ((access(Path, 0) < 0) && (strlen(Product) > 0)) + { + sal_Char Profile[_MAX_PATH]; + oslProfile hProfile; + + /* remove appended filename */ + *pChr = '\0'; + + /* open sversion.ini in the system directory, and try to locate the entry + with the highest version for StarOffice */ + if ((osl_getProfileName(SVERSION_LOCATION, SVERSION_NAME, Profile, sizeof(Profile))) && + (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK))) + { + pChr = &Product[strlen(Product)]; + + /* append build number */ + strcat(Product, "/"); + strcat(Product, BUILD_STR(SUPD)); + + osl_readProfileString(hProfile, SVERSION_SECTION, Product, + Buffer, sizeof(Buffer), ""); + + /* if not found, try it without build number */ + if (strlen(Buffer) <= 0) + { + *pChr = '\0'; + + osl_readProfileString(hProfile, SVERSION_SECTION, Product, + Buffer, sizeof(Buffer), ""); + + osl_closeProfile(hProfile); + + /* if not found, try the fallback */ + if ((strlen(Buffer) <= 0) && (strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0)) + { + if ((osl_getProfileName(SVERSION_FALLBACK, SVERSION_NAME, Profile, sizeof(Profile))) && + (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK))) + { + /* prepare build number */ + *pChr = '/'; + + osl_readProfileString(hProfile, SVERSION_SECTION, Product, + Buffer, sizeof(Buffer), ""); + + /* if not found, try it without build number */ + if (strlen(Buffer) <= 0) + { + *pChr = '\0'; + + osl_readProfileString(hProfile, SVERSION_SECTION, Product, + Buffer, sizeof(Buffer), ""); + } + + osl_closeProfile(hProfile); + } + } + } + else + osl_closeProfile(hProfile); + + if (strlen(Buffer) > 0) + { + strcpy(Path, Buffer); + + /* build full path */ + if ((Path[strlen(Path) - 1] != '/') && (Path[strlen(Path) - 1] != '\\')) + { + if ((*pszPath != '/') && (*pszPath != '\\')) + strcat(Path, "\\"); + } + + pChr=&Path[strlen(pszPath)]; + if ( strlen(pszPath) > 0 ) + { + strcat(Path, pszPath); + } + else + { + strcat(Path,SVERSION_USER); + if ( access(Path, 0) < 0 ) + { + *pChr='\0'; + } + } + } + } + } + else + /* remove appended filename */ + *pChr = '\0'; + } + + strcpy(pPath, Path); + + return (sal_True); +} + +#endif // 0 // YD + diff --git a/sal/osl/os2/salinit.cxx b/sal/osl/os2/salinit.cxx new file mode 100644 index 000000000000..43130c18e6f4 --- /dev/null +++ b/sal/osl/os2/salinit.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salinit.cxx,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define INCL_DOS +#include <os2.h> + +#include "precompiled_sal.hxx" +#include "sal/config.h" + +#include "osl/process.h" +#include "sal/main.h" +#include "sal/types.h" + +// for exception logging +#include <stdio.h> +#include <string.h> +#include <setjmp.h> +#include "helpers/except.h" + +extern "C" { + +/*----------------------------------------------------------------------------*/ + +static CHAR szOOoExe[CCHMAXPATH]; + +static FILE* APIENTRY _oslExceptOpenLogFile(VOID) +{ + FILE *file; + DATETIME DT; + PPIB pib; + PSZ slash; + + // get executable fullpath + DosGetInfoBlocks(NULL, &pib); + DosQueryModuleName(pib->pib_hmte, sizeof(szOOoExe), szOOoExe); + // truncate to exe name + slash = (PSZ)strrchr( szOOoExe, '.'); + *slash = '\0'; + // make log path + strcat( szOOoExe, ".log"); + + file = fopen( szOOoExe, "a"); + if (!file) { // e.g. readonly drive + // try again, usually C exist and is writable + file = fopen( "c:\\OOo.log", "a"); + } + if (file) { + DosGetDateTime(&DT); + fprintf(file, "\nTrap message -- Date: %04d-%02d-%02d, Time: %02d:%02d:%02d\n", + DT.year, DT.month, DT.day, + DT.hours, DT.minutes, DT.seconds); + fprintf(file, "-------------------------------------------------------\n" + "\nAn internal error occurred (Built " __DATE__ "-" __TIME__ ").\n"); + + } + + // ok, return handle + return (file); +} + +/*----------------------------------------------------------------------------*/ + +static EXCEPTSTRUCT g_excptstruct = {0}; + +void SAL_CALL sal_detail_initialize(int argc, char ** argv) +{ + APIRET rc = -1; + +#if OSL_DEBUG_LEVEL == 0 + excRegisterHooks(_oslExceptOpenLogFile, NULL, NULL, FALSE); + + g_excptstruct.RegRec2.pfnHandler = (PFN)excHandlerLoud; + g_excptstruct.arc = DosSetExceptionHandler( + (PEXCEPTIONREGISTRATIONRECORD)&(g_excptstruct.RegRec2)); + + if (g_excptstruct.arc) + if (G_pfnExcHookError) + G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, g_excptstruct.arc); + else + DosBeep(1000, 1000); + g_excptstruct.ulExcpt = setjmp(g_excptstruct.RegRec2.jmpThread); +#endif + + osl_setCommandArgs(argc, argv); +} + +void SAL_CALL sal_detail_deinitialize() +{ + APIRET rc = -1; + +#if OSL_DEBUG_LEVEL == 0 + rc = DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&(g_excptstruct.RegRec2)); +#endif +} + +} diff --git a/sal/osl/os2/secimpl.h b/sal/osl/os2/secimpl.h new file mode 100644 index 000000000000..3c9d07e1a606 --- /dev/null +++ b/sal/osl/os2/secimpl.h @@ -0,0 +1,53 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: secimpl.h,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _OSL_SECURITYIMPL_H_ +#define _OSL_SECURITYIMPL_H_ + +#include <osl/security.h> + +#define PASSWD_BUFFER_SIZE 1024 /* recommended, see 'man getpwnam_r' */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _oslSecurityImpl { + int m_isValid; + struct passwd m_pPasswd; + sal_Char m_buffer[PASSWD_BUFFER_SIZE]; +} oslSecurityImpl; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sal/osl/os2/security.c b/sal/osl/os2/security.c new file mode 100644 index 000000000000..a5a37e625b89 --- /dev/null +++ b/sal/osl/os2/security.c @@ -0,0 +1,320 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: security.c,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "system.h" + +#include <osl/security.h> +#include <osl/diagnose.h> +#include <osl/module.h> + +#include "osl/thread.h" +#include "osl/file.h" + +#ifdef SOLARIS +#include <crypt.h> +#endif + +#include "secimpl.h" + +#ifndef PAM_BINARY_MSG +#define PAM_BINARY_MSG 6 +#endif + +extern oslModule SAL_CALL osl_psz_loadModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode); +extern void* SAL_CALL osl_psz_getSymbol(oslModule hModule, const sal_Char* pszSymbolName); +extern oslSecurityError SAL_CALL +osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd, + oslSecurity* pSecurity); +sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax); +sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax); +sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax); +sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax); + + + +oslSecurity SAL_CALL osl_getCurrentSecurity() +{ + + oslSecurityImpl *pSecImpl = (oslSecurityImpl*) malloc(sizeof(oslSecurityImpl)); + struct passwd *pPasswd = getpwuid(getuid()); + + if (pPasswd) + { + memcpy(&pSecImpl->m_pPasswd, pPasswd, sizeof(pSecImpl->m_pPasswd)); + pSecImpl->m_isValid = sal_True; + } + else + { + /* Some UNIX-OS don't implement getpwuid, e.g. NC OS (special NetBSD) 1.2.1 */ + /* so we have to catch this in this else branch */ + pSecImpl->m_pPasswd.pw_name = getenv("USER"); + pSecImpl->m_pPasswd.pw_dir = getenv("HOME"); + if (pSecImpl->m_pPasswd.pw_name && pSecImpl->m_pPasswd.pw_dir) + pSecImpl->m_isValid = sal_True; + else + { + pSecImpl->m_pPasswd.pw_name = "unknown"; + pSecImpl->m_pPasswd.pw_dir = "/tmp"; + pSecImpl->m_isValid = sal_False; + } + pSecImpl->m_pPasswd.pw_passwd = NULL; + pSecImpl->m_pPasswd.pw_uid = getuid(); + pSecImpl->m_pPasswd.pw_gid = getgid(); + pSecImpl->m_pPasswd.pw_gecos = "unknown"; + pSecImpl->m_pPasswd.pw_shell = "unknown"; + } + + + return ((oslSecurity)pSecImpl); +} + + +oslSecurityError SAL_CALL osl_loginUser( + rtl_uString *ustrUserName, + rtl_uString *ustrPassword, + oslSecurity *pSecurity + ) +{ + oslSecurityError ret; + + *pSecurity = osl_getCurrentSecurity(); + ret = osl_Security_E_None; + + return ret; +} + + + +oslSecurityError SAL_CALL osl_loginUserOnFileServer( + rtl_uString *strUserName, + rtl_uString *strPasswd, + rtl_uString *strFileServer, + oslSecurity *pSecurity + ) +{ + oslSecurityError erg; + return erg = osl_Security_E_UserUnknown; +} + + +oslSecurityError SAL_CALL osl_psz_loginUserOnFileServer( const sal_Char* pszUserName, + const sal_Char* pszPasswd, + const sal_Char* pszFileServer, + oslSecurity* pSecurity ) +{ + oslSecurityError erg; + return erg = osl_Security_E_UserUnknown; +} + +sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent) +{ + sal_Bool bRet=sal_False; + sal_Char pszIdent[1024]; + + pszIdent[0] = '\0'; + + bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent)); + + rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*ustrIdent != NULL); + + return bRet; +} + + +sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax) +{ + sal_Char buffer[32]; + sal_Int32 nChr; + + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid); + if ( nChr < 0 || nChr >= sizeof(buffer) || nChr >= nMax ) + return sal_False; /* leave *pszIdent unmodified in case of failure */ + + memcpy(pszIdent, buffer, nChr+1); + return sal_True; +} + +sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName) +{ + sal_Bool bRet=sal_False; + sal_Char pszName[1024]; + + pszName[0] = '\0'; + + bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName)); + + rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*ustrName != NULL); + + return bRet; +} + + + +sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax) +{ + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if ((pSecImpl == NULL) || (! pSecImpl->m_isValid)) + return sal_False; + + strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax); + + return sal_True; +} + +sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory) +{ + sal_Bool bRet=sal_False; + sal_Char pszDirectory[PATH_MAX]; + + pszDirectory[0] = '\0'; + + bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory)); + + if ( bRet == sal_True ) + { + rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*pustrDirectory != NULL); + osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory ); + } + + return bRet; +} + + +sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax) +{ + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + /* if current user, check also environment for HOME */ + if (getuid() == pSecImpl->m_pPasswd.pw_uid) + { + sal_Char *pStr = NULL; +#ifdef SOLARIS + char buffer[8192]; + + struct passwd pwd; + struct passwd *ppwd; + +#ifdef _POSIX_PTHREAD_SEMANTICS + if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) ) + ppwd = NULL; +#else + ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) ); +#endif + + if ( ppwd ) + pStr = ppwd->pw_dir; +#else + pStr = getenv("HOME"); +#endif + + if ((pStr != NULL) && (strlen(pStr) > 0) && + (access(pStr, 0) == 0)) + strncpy(pszDirectory, pStr, nMax); + else + if (pSecImpl->m_isValid) + strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax); + else + return sal_False; + } + else + strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax); + + return sal_True; +} + +sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory) +{ + sal_Bool bRet = sal_False; + sal_Char pszDirectory[PATH_MAX]; + + pszDirectory[0] = '\0'; + + bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory)); + + if ( bRet == sal_True ) + { + rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*pustrDirectory != NULL); + osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory ); + } + + return bRet; +} + + +sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax) +{ + return (osl_psz_getHomeDir(Security, pszDirectory, nMax)); +} + +sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security) +{ + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + if (pSecImpl->m_pPasswd.pw_uid != 0) + return (sal_False); + + return (sal_True); +} + +void SAL_CALL osl_freeSecurityHandle(oslSecurity Security) +{ + if (Security) + free ((oslSecurityImpl*)Security); +} + + +sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security) +{ + return sal_False; +} + +void SAL_CALL osl_unloadUserProfile(oslSecurity Security) +{ + return; +} + + diff --git a/sal/osl/os2/semaphor.c b/sal/osl/os2/semaphor.c new file mode 100644 index 000000000000..dbb8ff472b73 --- /dev/null +++ b/sal/osl/os2/semaphor.c @@ -0,0 +1,193 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: semaphor.c,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "system.h" + +#include <osl/diagnose.h> +#include <osl/semaphor.h> + +/* + Implemetation notes: + The void* represented by oslSemaphore is used + to store a OS/2 HANDLE. +*/ + +typedef struct _oslSemaphoreImpl +{ + HEV hevReachedZero; + int nCount; +} oslSemaphoreImpl; + +// static mutex to control access to private members of oslMutexImpl +static HMTX MutexLock = NULL; + +/*****************************************************************************/ +/* osl_createSemaphore */ +/*****************************************************************************/ + +/* +- Erzeugen der Semaphore +- Z„hler auf initialCount setzen +*/ +oslSemaphore SAL_CALL osl_createSemaphore(sal_uInt32 initialCount) +{ + APIRET rc; + oslSemaphoreImpl * pSemaphoreImpl; + + /* alloc mem. for our internal data structure */ + pSemaphoreImpl = (oslSemaphoreImpl *) malloc(sizeof(oslSemaphoreImpl)); + if( pSemaphoreImpl == NULL ) + return NULL; + + /* create semaphore */ + rc = DosCreateEventSem( NULL, + &pSemaphoreImpl->hevReachedZero, + DC_SEM_SHARED, + FALSE ); + if( rc != NO_ERROR ) + { + free( pSemaphoreImpl ); + return NULL; + } + + pSemaphoreImpl->nCount = initialCount; + + // create static mutex for private members + if (MutexLock == NULL) + DosCreateMutexSem( NULL, &MutexLock, 0, FALSE ); + + return (oslSemaphore) pSemaphoreImpl; +} + +/*****************************************************************************/ +/* osl_destroySemaphore */ +/*****************************************************************************/ + +/* +- Semaphore l”schen +*/ + +void SAL_CALL osl_destroySemaphore(oslSemaphore Semaphore) +{ + oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore; + OSL_ASSERT(Semaphore != 0); + + DosCloseEventSem( pSemaphoreImpl->hevReachedZero ); + + free( pSemaphoreImpl ); +} + +/*****************************************************************************/ +/* osl_acquireSemaphore */ +/*****************************************************************************/ +/* +- Z„hler -1 +- wenn Z„hler < 0: blockieren +*/ + +sal_Bool SAL_CALL osl_acquireSemaphore(oslSemaphore Semaphore) +{ + APIRET rc; + oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore; + int nCount; + OSL_ASSERT(Semaphore != 0); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + while( pSemaphoreImpl->nCount < 1 ) + { + sal_uInt32 nPostCount; + + DosReleaseMutexSem( MutexLock); + + rc = DosWaitEventSem(pSemaphoreImpl->hevReachedZero, SEM_INDEFINITE_WAIT ); + DosResetEventSem(pSemaphoreImpl->hevReachedZero, &nPostCount); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + } + + pSemaphoreImpl->nCount--; + DosReleaseMutexSem( MutexLock); + + return( rc == NO_ERROR ); +} + +/*****************************************************************************/ +/* osl_tryToAcquireSemaphore */ +/*****************************************************************************/ +/* +- Z„hler -1, wenn vorher > 0 +- wenn Z„hler < 0: mit FALSE zurueck +*/ +sal_Bool SAL_CALL osl_tryToAcquireSemaphore(oslSemaphore Semaphore) +{ + APIRET rc; + oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore; + int nCount; + OSL_ASSERT(Semaphore != 0); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + nCount = pSemaphoreImpl->nCount; + if( pSemaphoreImpl->nCount > 0 ) + pSemaphoreImpl->nCount--; + + DosReleaseMutexSem( MutexLock); + + return( nCount > 0 ); +} + +/*****************************************************************************/ +/* osl_releaseSemaphore */ +/*****************************************************************************/ +/* +- Z„hler +1 +*/ +sal_Bool SAL_CALL osl_releaseSemaphore(oslSemaphore Semaphore) +{ + APIRET rc; + oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore; + int nCount; + OSL_ASSERT(Semaphore != 0); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + nCount = pSemaphoreImpl->nCount; + pSemaphoreImpl->nCount++; + + DosReleaseMutexSem( MutexLock); + + if( nCount == 0 ) + DosPostEventSem(pSemaphoreImpl->hevReachedZero); + + return( rc == NO_ERROR ); +} + + diff --git a/sal/osl/os2/signal.c b/sal/osl/os2/signal.c new file mode 100644 index 000000000000..a79e50b3a1e1 --- /dev/null +++ b/sal/osl/os2/signal.c @@ -0,0 +1,252 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: signal.c,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +/* system headers */ +#include "system.h" + +#include <osl/diagnose.h> +#include <osl/mutex.h> +#include <osl/signal.h> + +typedef struct _oslSignalHandlerImpl +{ + oslSignalHandlerFunction Handler; + void* pData; + struct _oslSignalHandlerImpl* pNext; +} oslSignalHandlerImpl; + +static sal_Bool bErrorReportingEnabled = sal_True; +static sal_Bool bInitSignal = sal_False; +static oslMutex SignalListMutex; +static oslSignalHandlerImpl* SignalList; + +/*static*//* ULONG _Export APIENTRY SignalHandlerFunction(PEXCEPTIONREPORTRECORD pERepRec, + PEXCEPTIONREGISTRATIONRECORD, + PCONTEXTRECORD, PVOID); +*/ +/*static*/ ULONG __declspec(dllexport) APIENTRY SignalHandlerFunction(PEXCEPTIONREPORTRECORD pERepRec, + PEXCEPTIONREGISTRATIONRECORD, + PCONTEXTRECORD, PVOID); +static EXCEPTIONREGISTRATIONRECORD ExcptHandler = { 0, SignalHandlerFunction }; + +static sal_Bool InitSignal( void ) +{ + SignalListMutex = osl_createMutex(); + + ExcptHandler.ExceptionHandler = (_ERR *) &SignalHandlerFunction; + /* DosSetExceptionHandler(&ExcptHandler); */ + + return sal_True; +} + +static sal_Bool DeInitSignal( void ) +{ + /* DosUnsetExceptionHandler(&ExcptHandler); */ + + osl_destroyMutex(SignalListMutex); + + return sal_False; +} + +static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo) +{ + oslSignalHandlerImpl* pHandler = SignalList; + oslSignalAction Action = osl_Signal_ActCallNextHdl; + + while (pHandler != NULL) + { + if ((Action = pHandler->Handler(pHandler->pData, pInfo)) != osl_Signal_ActCallNextHdl) + break; + + pHandler = pHandler->pNext; + } + + return Action; +} + +/*****************************************************************************/ +/* SignalHandlerFunction */ +/*****************************************************************************/ +/*static*/ ULONG __declspec(dllexport) APIENTRY SignalHandlerFunction(PEXCEPTIONREPORTRECORD pERepRec, + PEXCEPTIONREGISTRATIONRECORD pERegRec, + PCONTEXTRECORD pConRec, PVOID pReserved) +{ + oslSignalInfo Info; + + Info.UserSignal = pERepRec->ExceptionNum; + Info.UserData = NULL; + + switch (pERepRec->ExceptionNum) + { + case XCPT_ACCESS_VIOLATION: + Info.Signal = osl_Signal_AccessViolation; + break; + + case XCPT_INTEGER_DIVIDE_BY_ZERO: + Info.Signal = osl_Signal_IntegerDivideByZero; + break; + + case XCPT_BREAKPOINT: + Info.Signal = osl_Signal_DebugBreak; + break; + + default: + Info.Signal = osl_Signal_System; + break; + } + + switch (CallSignalHandler(&Info)) + { + case osl_Signal_ActCallNextHdl: + return (XCPT_CONTINUE_SEARCH); + + case osl_Signal_ActAbortApp: + return (XCPT_CONTINUE_SEARCH); + + case osl_Signal_ActKillApp: + exit(255); + break; + } + + return (XCPT_CONTINUE_SEARCH); +} + +/*****************************************************************************/ +/* osl_addSignalHandler */ +/*****************************************************************************/ +oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData) +{ + oslSignalHandlerImpl* pHandler; + + OSL_ASSERT(Handler != NULL); + + if (! bInitSignal) + bInitSignal = InitSignal(); + + pHandler = (oslSignalHandlerImpl*) calloc(1, sizeof(oslSignalHandlerImpl)); + + if (pHandler != NULL) + { + pHandler->Handler = Handler; + pHandler->pData = pData; + + osl_acquireMutex(SignalListMutex); + + pHandler->pNext = SignalList; + SignalList = pHandler; + + osl_releaseMutex(SignalListMutex); + + return (pHandler); + } + + return (NULL); +} + +/*****************************************************************************/ +/* osl_removeSignalHandler */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler) +{ + oslSignalHandlerImpl *pHandler, *pPrevious = NULL; + + OSL_ASSERT(Handler != NULL); + + if (! bInitSignal) + bInitSignal = InitSignal(); + + osl_acquireMutex(SignalListMutex); + + pHandler = SignalList; + + while (pHandler != NULL) + { + if (pHandler == Handler) + { + if (pPrevious) + pPrevious->pNext = pHandler->pNext; + else + SignalList = pHandler->pNext; + + osl_releaseMutex(SignalListMutex); + + if (SignalList == NULL ) + bInitSignal = DeInitSignal(); + + free(pHandler); + + return (sal_True); + } + + pPrevious = pHandler; + pHandler = pHandler->pNext; + } + + osl_releaseMutex(SignalListMutex); + + return (sal_False); +} + +/*****************************************************************************/ +/* osl_raiseSignal */ +/*****************************************************************************/ +oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData) +{ + oslSignalInfo Info; + oslSignalAction Action; + + if (! bInitSignal) + bInitSignal = InitSignal(); + + osl_acquireMutex(SignalListMutex); + + Info.Signal = osl_Signal_User; + Info.UserSignal = UserSignal; + Info.UserData = UserData; + + Action = CallSignalHandler(&Info); + + osl_releaseMutex(SignalListMutex); + + return (Action); +} + +/*****************************************************************************/ +/* osl_setErrorReporting */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable ) +{ + sal_Bool bOld = bErrorReportingEnabled; + bErrorReportingEnabled = bEnable; + + return bOld; +} + diff --git a/sal/osl/os2/socket.c b/sal/osl/os2/socket.c new file mode 100644 index 000000000000..de70e5b8885a --- /dev/null +++ b/sal/osl/os2/socket.c @@ -0,0 +1,3100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: socket.c,v $ + * $Revision: 1.5.60.1 $ + * + * 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 (IRIX) || defined(NETBSD) || defined ( FREEBSD ) || defined (MACOSX) +#include <sys/poll.h> +#define HAVE_POLL_H +#endif /* HAVE_POLL_H */ + +#if defined(SOLARIS) +#include <poll.h> +#define HAVE_POLL_H +#endif /* SOLARIS */ + +#ifndef HAVE_POLL_H +#define POLLIN 0x0001 +#define POLLOUT 0x0002 +#define POLLPRI 0x0004 +#endif /* HAVE_POLL_H */ + + +/* defines for shutdown */ +#define SD_RECEIVE 0 +#define SD_SEND 1 +#define SD_BOTH 2 + + +/* + oslSocketAddr is a pointer to a Berkeley struct sockaddr. + I refrained from using sockaddr_in because of possible further + extensions of this socket-interface (IP-NG?). + The intention was to hide all Berkeley data-structures from + direct access past the osl-interface. + + The current implementation is internet (IP) centered. All + the constructor-functions (osl_create...) take parameters + that will probably make sense only in the IP-environment + (e.g. because of using the dotted-address-format). + + If the interface will be extended to host other protocol- + families, I expect no externally visible changes in the + existing functions. You'll probably need only new + constructor-functions who take the different address + formats into consideration (maybe a long dotted address + or whatever). +*/ + +/* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */ +/* are the same! I don't like it very much but see no other easy way to */ +/* conceal the struct sockaddr from the eyes of the user. */ + + +#define OSL_INVALID_SOCKET -1 +#define OSL_SOCKET_ERROR -1 + + +/* Buffer size for gethostbyname */ +#define MAX_HOSTBUFFER_SIZE 2048 + +/*****************************************************************************/ +/* enum oslAddrFamily */ +/*****************************************************************************/ + +/* map */ +static unsigned long FamilyMap[]= { + AF_INET, /* osl_Socket_FamilyInet */ + AF_IPX, /* osl_Socket_FamilyIpx */ + 0 /* osl_Socket_FamilyInvalid */ +}; + +/* reverse map */ +static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType) +{ + oslAddrFamily i= (oslAddrFamily)0; + + while(i != osl_Socket_FamilyInvalid) + { + if(FamilyMap[i] == nativeType) + return i; + i = (oslAddrFamily) ( i + 1 ); + } + + return i; +} + +/* macros */ +#define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y) +#define FAMILY_TO_NATIVE(x) (short)FamilyMap[x] + +/*****************************************************************************/ +/* enum oslProtocol */ +/*****************************************************************************/ + +/* map */ +static sal_uInt32 ProtocolMap[]= { + 0, /* osl_Socket_ProtocolIp */ + NSPROTO_IPX, /* osl_Socket_ProtocolIpx */ + NSPROTO_SPX, /* osl_Socket_ProtocolSpx */ + NSPROTO_SPXII, /* osl_Socket_ProtocolSpxII */ + 0 /* osl_Socket_ProtocolInvalid */ +}; + +/* reverse map */ +/* mfe: NOT USED +static oslProtocol osl_ProtocolFromNative(sal_uInt32 nativeType) +{ + oslProtocol i= (oslProtocol)0; + + while(i != osl_Socket_ProtocolInvalid) + { + if(ProtocolMap[i] == nativeType) + return i; + i = (oslProtocol) ( i + 1); + } + + return i; +} +*/ + +/* macros */ +#define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y) +#define PROTOCOL_TO_NATIVE(x) ProtocolMap[x] + + +/*****************************************************************************/ +/* enum oslSocketType */ +/*****************************************************************************/ + +/* map */ +static sal_uInt32 TypeMap[]= { + SOCK_STREAM, /* osl_Socket_TypeStream */ + SOCK_DGRAM, /* osl_Socket_TypeDgram */ + SOCK_RAW, /* osl_Socket_TypeRaw */ + SOCK_RDM, /* osl_Socket_TypeRdm */ + SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */ + 0 /* osl_Socket_TypeInvalid */ +}; + +/* reverse map */ +static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType) +{ + oslSocketType i= (oslSocketType)0; + + while(i != osl_Socket_TypeInvalid) + { + if(TypeMap[i] == nativeType) + return i; + i = (oslSocketType)(i + 1); + } + + return i; +} + +/* macros */ +#define TYPE_TO_NATIVE(x) TypeMap[x] +#define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y) + + +/*****************************************************************************/ +/* enum oslSocketOption */ +/*****************************************************************************/ + +/* map */ +static sal_uInt32 OptionMap[]= { + SO_DEBUG, /* osl_Socket_OptionDebug */ + SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */ + SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */ + SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */ + SO_DONTROUTE, /* osl_Socket_OptionDontRoute */ + SO_BROADCAST, /* osl_Socket_OptionBroadcast */ + SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */ + SO_LINGER, /* osl_Socket_OptionLinger */ + SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */ + SO_SNDBUF, /* osl_Socket_OptionSndBuf */ + SO_RCVBUF, /* osl_Socket_OptionRcvBuf */ + SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */ + SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */ + SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */ + SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */ + SO_ERROR, /* osl_Socket_OptionError */ + SO_TYPE, /* osl_Socket_OptionType */ + TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */ + 0 /* osl_Socket_OptionInvalid */ +}; + +/* reverse map */ +/* mfe: NOT USED +static oslSocketOption osl_SocketOptionFromNative(sal_uInt32 nativeType) +{ + oslSocketOption i= (oslSocketOption)0; + + while(i != osl_Socket_OptionInvalid) + { + if(OptionMap[i] == nativeType) + return i; + i = (oslSocketOption) ( i + 1 ); + } + + return i; +} +*/ +/* macros */ +#define OPTION_TO_NATIVE(x) OptionMap[x] +#define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y) + + +/*****************************************************************************/ +/* enum oslSocketOptionLevel */ +/*****************************************************************************/ + +static sal_uInt32 OptionLevelMap[]= { + SOL_SOCKET, /* osl_Socket_LevelSocket */ + IPPROTO_TCP, /* osl_Socket_LevelTcp */ + 0 /* osl_Socket_LevelInvalid */ +}; + +/* reverse map */ +/* mfe: NOT USED +static oslSocketOptionLevel osl_SocketOptionLevelFromNative(sal_uInt32 nativeType) +{ + oslSocketOptionLevel i= (oslSocketOptionLevel)0; + + while(i != osl_Socket_LevelInvalid) + { + if(OptionLevelMap[i] == nativeType) + return i; + i = (oslSocketOptionLevel) ( i + 1 ); + } + + return i; +} +*/ +/* macros */ +#define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x] +#define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y) + +/*****************************************************************************/ +/* enum oslSocketMsgFlag */ +/*****************************************************************************/ + +static sal_uInt32 SocketMsgFlagMap[]= { + 0, /* osl_Socket_MsgNormal */ + MSG_OOB, /* osl_Socket_MsgOOB */ + MSG_PEEK, /* osl_Socket_MsgPeek */ + MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */ + MSG_MAXIOVLEN, /* osl_Socket_MsgMaxIOVLen */ + 0 /* osl_Socket_MsgInvalid */ +}; + +/* reverse map */ +/* mfe: NOT USED +static oslSocketMsgFlag osl_SocketMsgFlagFromNative(sal_uInt32 nativeType) +{ + oslSocketMsgFlag i= (oslSocketMsgFlag)0; + + while(i != osl_Socket_MsgInvalid) + { + if(SocketMsgFlagMap[i] == nativeType) + return i; + i = (oslSocketMsgFlag) ( i + 1 ); + } + + return i; +} +*/ + +/* macros */ +#define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x] +#define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y) + + +/*****************************************************************************/ +/* enum oslSocketDirection */ +/*****************************************************************************/ + +static sal_uInt32 SocketDirection[]= { + SD_RECEIVE, /* osl_Socket_DirRead */ + SD_SEND, /* osl_Socket_DirWrite */ + SD_BOTH, /* osl_Socket_DirReadWrite */ + 0 /* osl_Socket_DirInvalid */ +}; + +/* reverse map */ +/* mfe: NOT USED +static oslSocketDirection osl_SocketDirectionFromNative(sal_uInt32 nativeType) +{ + oslSocketDirection i= (oslSocketDirection)0; + + while(i != osl_Socket_DirInvalid) + { + if(SocketDirection[i] == nativeType) + return i; + i = (oslSocketDirection) ( i + 1 ); + } + + return i; +} +*/ + +/* macros */ +#define DIRECTION_TO_NATIVE(x) SocketDirection[x] +#define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y) + +/*****************************************************************************/ +/* enum oslSocketError */ +/*****************************************************************************/ + +static struct +{ + int errcode; + oslSocketError error; +} SocketError[]= { + { 0, osl_Socket_E_None }, /* no error */ + { ENOTSOCK, osl_Socket_E_NotSocket }, /* Socket operation on non-socket */ + { EDESTADDRREQ, osl_Socket_E_DestAddrReq }, /* Destination address required */ + { EMSGSIZE, osl_Socket_E_MsgSize }, /* Message too long */ + { EPROTOTYPE, osl_Socket_E_Prototype }, /* Protocol wrong type for socket */ + { ENOPROTOOPT, osl_Socket_E_NoProtocol }, /* Protocol not available */ + { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */ + { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport }, /* Socket type not supported */ + { EOPNOTSUPP, osl_Socket_E_OpNotSupport }, /* Operation not supported on socket */ + { EPFNOSUPPORT, osl_Socket_E_PfNoSupport }, /* Protocol family not supported */ + { EAFNOSUPPORT, osl_Socket_E_AfNoSupport }, /* Address family not supported by */ + /* protocol family */ + { EADDRINUSE, osl_Socket_E_AddrInUse }, /* Address already in use */ + { EADDRNOTAVAIL, osl_Socket_E_AddrNotAvail }, /* Can't assign requested address */ + { ENETDOWN, osl_Socket_E_NetDown }, /* Network is down */ + { ENETUNREACH, osl_Socket_E_NetUnreachable }, /* Network is unreachable */ + { ENETRESET, osl_Socket_E_NetReset }, /* Network dropped connection because */ + /* of reset */ + { ECONNABORTED, osl_Socket_E_ConnAborted }, /* Software caused connection abort */ + { ECONNRESET, osl_Socket_E_ConnReset }, /* Connection reset by peer */ + { ENOBUFS, osl_Socket_E_NoBufferSpace }, /* No buffer space available */ + { EISCONN, osl_Socket_E_IsConnected }, /* Socket is already connected */ + { ENOTCONN, osl_Socket_E_NotConnected }, /* Socket is not connected */ + { ESHUTDOWN, osl_Socket_E_Shutdown }, /* Can't send after socket shutdown */ + { ETOOMANYREFS, osl_Socket_E_TooManyRefs }, /* Too many references: can't splice */ + { ETIMEDOUT, osl_Socket_E_TimedOut }, /* Connection timed out */ + { ECONNREFUSED, osl_Socket_E_ConnRefused }, /* Connection refused */ + { EHOSTDOWN, osl_Socket_E_HostDown }, /* Host is down */ + { EHOSTUNREACH, osl_Socket_E_HostUnreachable }, /* No route to host */ + { EWOULDBLOCK, osl_Socket_E_WouldBlock }, /* call would block on non-blocking socket */ + { EALREADY, osl_Socket_E_Already }, /* operation already in progress */ + { EINPROGRESS, osl_Socket_E_InProgress }, /* operation now in progress */ + { EAGAIN, osl_Socket_E_WouldBlock }, /* same as EWOULDBLOCK */ + { -1, osl_Socket_E_InvalidError } +}; + +/* map */ +/* mfe: NOT USED +static int osl_NativeFromSocketError(oslSocketError errorCode) +{ + int i = 0; + + while ((SocketError[i].error != osl_Socket_E_InvalidError) && + (SocketError[i].error != errorCode)) i++; + + return SocketError[i].errcode; +} +*/ + +/* reverse map */ +static oslSocketError osl_SocketErrorFromNative(int nativeType) +{ + int i = 0; + + while ((SocketError[i].error != osl_Socket_E_InvalidError) && + (SocketError[i].errcode != nativeType)) i++; + + return SocketError[i].error; +} + +/* macros */ +#define ERROR_TO_NATIVE(x) osl_NativeFromSocketError(x) +#define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y) + +/*****************************************************************************/ +/* local function prototypes */ +/*****************************************************************************/ + +oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr ( + const sal_Char* pszDottedAddr, sal_Int32 Port); + +oslSocketAddr SAL_CALL osl_psz_createIpxSocketAddr ( + const sal_Char NetNumber[4], + const sal_Char NodeNumber[6], + sal_uInt32 SocketNumber); + +oslHostAddr SAL_CALL osl_psz_createHostAddr ( + const sal_Char *pszHostname, const oslSocketAddr Addr); + +oslHostAddr SAL_CALL osl_psz_createHostAddrByName ( + const sal_Char *pszHostname); + +const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr ( + const oslHostAddr Addr); + +oslSocketResult SAL_CALL osl_psz_getLocalHostname ( + sal_Char *pBuffer, sal_uInt32 nBufLen); + +oslSocketAddr SAL_CALL osl_psz_resolveHostname ( + const sal_Char* pszHostname); + +sal_Int32 SAL_CALL osl_psz_getServicePort ( + const sal_Char* pszServicename, const sal_Char* pszProtocol); + +oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr ( + oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize); + +oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr ( + oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize); + +void SAL_CALL osl_psz_getLastSocketErrorDescription ( + oslSocket Socket, sal_Char* pBuffer, sal_uInt32 BufferSize); + +/*****************************************************************************/ +/* osl_create/destroy-SocketImpl */ +/*****************************************************************************/ + +#if OSL_DEBUG_LEVEL > 1 +static sal_uInt32 g_nSocketImpl = 0; +static sal_uInt32 g_nSocketAddr = 0; + +/* sorry, must be implemented otherwise */ +#if 0 +struct LeakWarning +{ + ~LeakWarning() + { + if( g_nSocketImpl ) + OSL_TRACE( "sal_socket: %d socket instances leak\n" , g_nSocketImpl ); + if( g_nSocketAddr ) + OSL_TRACE( "sal_socket: %d socket address instances leak\n" , g_nSocketAddr ); + } +}; +LeakWarning socketWarning; +#endif + +#endif /* OSL_DEBUG_LEVEL */ + + +oslSocket __osl_createSocketImpl(int Socket) +{ + oslSocket pSocket; + + pSocket = (oslSocket)calloc(1, sizeof(struct oslSocketImpl)); + + pSocket->m_Socket = Socket; + pSocket->m_nLastError = 0; + pSocket->m_CloseCallback = 0; + pSocket->m_CallbackArg = 0; + pSocket->m_nRefCount = 1; + +#if defined(LINUX) + pSocket->m_bIsAccepting = sal_False; +#endif + +#if OSL_DEBUG_LEVEL > 1 + g_nSocketImpl ++; +#endif + return pSocket; +} + +void __osl_destroySocketImpl(oslSocket Socket) +{ + if ( Socket != NULL) + free((struct oslSocketImpl *) Socket); +#if OSL_DEBUG_LEVEL > 1 + g_nSocketImpl --; +#endif +} + +static oslSocketAddr __osl_createSocketAddr( ) +{ + oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl )); +#if OSL_DEBUG_LEVEL > 1 + g_nSocketAddr ++; +#endif + return pAddr; +} + +static oslSocketAddr __osl_createSocketAddrWithFamily( + oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr ) +{ + oslSocketAddr pAddr; + + OSL_ASSERT( family == osl_Socket_FamilyInet ); + + pAddr = __osl_createSocketAddr(); + switch( family ) + { + case osl_Socket_FamilyInet: + { + struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr); + + pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet); + pInetAddr->sin_addr.s_addr = nAddr; + pInetAddr->sin_port = (sal_uInt16)(port&0xffff); + break; + } + default: + pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family); + } + return pAddr; +} + +static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr ) +{ + oslSocketAddr pAddr = __osl_createSocketAddr(); + memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) ); + return pAddr; +} + +static void __osl_destroySocketAddr( oslSocketAddr addr ) +{ +#if OSL_DEBUG_LEVEL > 1 + g_nSocketAddr --; +#endif + rtl_freeMemory( addr ); +} + +/*****************************************************************************/ +/* osl_createEmptySocketAddr */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family) +{ + oslSocketAddr pAddr = 0; + + /* is it an internet-Addr? */ + if (Family == osl_Socket_FamilyInet) + { + pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) ); + } + else + { + pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 ); + } + + return pAddr; +} + +/*****************************************************************************/ +/* osl_copySocketAddr */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr) +{ + oslSocketAddr pCopy = 0; + if (Addr) + { + pCopy = __osl_createSocketAddr(); + + if (pCopy) + memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr)); + } + return pCopy; +} + +/*****************************************************************************/ +/* osl_isEqualSocketAddr */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isEqualSocketAddr ( + oslSocketAddr Addr1, + oslSocketAddr Addr2) +{ + struct sockaddr* pAddr1= &(Addr1->m_sockaddr); + struct sockaddr* pAddr2= &(Addr2->m_sockaddr); + + OSL_ASSERT(pAddr1); + OSL_ASSERT(pAddr2); + + if (pAddr1->sa_family == pAddr2->sa_family) + { + switch (pAddr1->sa_family) + { + case AF_INET: + { + struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1; + struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2; + + if ((pInetAddr1->sin_family == pInetAddr2->sin_family) && + (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) && + (pInetAddr1->sin_port == pInetAddr2->sin_port)) + return (sal_True); + } + + default: + { + return (memcmp(pAddr1, Addr2, sizeof(struct sockaddr)) == 0); + } + } + } + + return (sal_False); +} + +/*****************************************************************************/ +/* osl_createInetBroadcastAddr */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_createInetBroadcastAddr ( + rtl_uString *strDottedAddr, + sal_Int32 Port) +{ + sal_uInt32 nAddr = OSL_INADDR_NONE; + oslSocketAddr pAddr; + + if (strDottedAddr && strDottedAddr->length) + { + /* Dotted host address for limited broadcast */ + rtl_String *pDottedAddr = NULL; + + rtl_uString2String ( + &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length, + RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); + + nAddr = inet_addr (pDottedAddr->buffer); + rtl_string_release (pDottedAddr); + } + + if (nAddr != OSL_INADDR_NONE) + { + /* Limited broadcast */ + nAddr = ntohl(nAddr); + if (IN_CLASSA(nAddr)) + { + nAddr &= IN_CLASSA_NET; + nAddr |= IN_CLASSA_HOST; + } + else if (IN_CLASSB(nAddr)) + { + nAddr &= IN_CLASSB_NET; + nAddr |= IN_CLASSB_HOST; + } + else if (IN_CLASSC(nAddr)) + { + nAddr &= IN_CLASSC_NET; + nAddr |= IN_CLASSC_HOST; + } + else + { + /* No broadcast in class D */ + return ((oslSocketAddr)NULL); + } + nAddr = htonl(nAddr); + } + + pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr ); + return pAddr; +} + +/*****************************************************************************/ +/* osl_createInetSocketAddr */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_createInetSocketAddr ( + rtl_uString *ustrDottedAddr, + sal_Int32 Port) +{ + rtl_String* strDottedAddr=0; + oslSocketAddr Addr; + sal_Char* pszDottedAddr=0; + + if ( ustrDottedAddr != 0 ) + { + rtl_uString2String( &strDottedAddr, + rtl_uString_getStr(ustrDottedAddr), + rtl_uString_getLength(ustrDottedAddr), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS); + pszDottedAddr = rtl_string_getStr(strDottedAddr); + } + + + Addr = osl_psz_createInetSocketAddr(pszDottedAddr, Port); + + if ( strDottedAddr != 0 ) + { + rtl_string_release(strDottedAddr); + } + + return Addr; +} + +oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr ( + const sal_Char* pszDottedAddr, + sal_Int32 Port) +{ + oslSocketAddr pAddr = 0; + sal_Int32 Addr = inet_addr(pszDottedAddr); + if(Addr != -1) + { + /* valid dotted addr */ + pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , Addr ); + } + return pAddr; +} + +/*****************************************************************************/ +/* osl_setAddrOfSocketAddr */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq ) +{ + oslSocketResult res = osl_Socket_Error; + + OSL_ASSERT( pAddr ); + OSL_ASSERT( pByteSeq ); + + if( pAddr && pByteSeq ) + { + struct sockaddr_in * pSystemInetAddr; + + OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) ); + OSL_ASSERT( pByteSeq->nElements == 4 ); + + pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr); + memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 ); + res = osl_Socket_Ok; + } + return res; +} + +/*****************************************************************************/ +/* osl_getAddrOfSocketAddr */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq ) +{ + oslSocketResult res = osl_Socket_Error; + + OSL_ASSERT( pAddr ); + OSL_ASSERT( ppByteSeq ); + + if( pAddr && ppByteSeq ) + { + struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr); + rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4); + res = osl_Socket_Ok; + } + return res; +} + + +/*****************************************************************************/ +/* _osl_getFullQualifiedDomainName */ +/*****************************************************************************/ + +/** try to figure out a full-qualified hostname, by adding the current domain + as given by the domainname program to the given hostname. + This function MUST NOT call gethostbyname since pHostName allready points + to data returned by gethostname and would be garbled: use gethostname_r + instead! + */ + +/* wrap around different interfaces to reentrant gethostbyname */ +static struct hostent* _osl_gethostbyname_r ( + const char *name, struct hostent *result, + char *buffer, int buflen, int *h_errnop) +{ + +#ifdef LINUX + struct hostent *__result; /* will be the same as result */ + int __error; + __error = gethostbyname_r (name, result, buffer, buflen, + &__result, h_errnop); + return __error ? NULL : __result ; +#elif defined OS2 + // YD FIXME!!! + return 0; +#else + return gethostbyname_r( name, result, buffer, buflen, h_errnop); +#endif +} + +static sal_Bool _osl_getDomainName (sal_Char *buffer, sal_Int32 bufsiz) +{ + sal_Bool result; + int p[2]; + + result = sal_False; + +#if 0 // YD 17/04/06 libc panic for fork() from thread!=1 + + if (pipe (p) == 0) + { + pid_t pid; + int nStatus; + + pid = fork(); + if (pid == 0) + { + char *argv[] = + { + "/bin/domainname", + NULL + }; + + close (p[0]); + dup2 (p[1], 1); + close (p[1]); + + execv ("/bin/domainname", argv); + // arriving here means exec failed + _exit(-1); + } + else if (pid > 0) + { + sal_Int32 k = 0, n = bufsiz; + + close (p[1]); + if ((k = read (p[0], buffer, n - 1)) > 0) + { + buffer[k] = 0; + if (buffer[k - 1] == '\n') + buffer[k - 1] = 0; + result = sal_True; + } + close (p[0]); + waitpid (pid, &nStatus, 0); + } + else + { + close (p[0]); + close (p[1]); + } + } +#endif // 0 + + return (result); +} + +static sal_Char* _osl_getFullQualifiedDomainName (const sal_Char *pHostName) +{ +# define DOMAINNAME_LENGTH 512 + sal_uInt32 nLengthOfHostName; + static sal_uInt32 nLengthOfDomainName = 0; + static sal_Char *pDomainName = NULL; + + sal_Char *pFullQualifiedName; +#if 0 /* OBSOLETE */ + FILE *pPipeToDomainnameExe; +#endif /* OBSOLETE */ + + /* get a '\0' terminated domainname */ + + /* read default domainname default from environment */ + if (nLengthOfDomainName == 0) + { + sal_Char *pEnvDomain; + + pEnvDomain = getenv ("STAR_OVERRIDE_DOMAINNAME"); + if (pEnvDomain) + { + pDomainName = strdup (pEnvDomain); + nLengthOfDomainName = strlen (pDomainName); + } + } + +#if 1 /* NEW */ + if (nLengthOfDomainName == 0) + { + sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ]; + + pDomainNameBuffer[0] = '\0'; + + if (_osl_getDomainName (pDomainNameBuffer, DOMAINNAME_LENGTH)) + { + pDomainName = strdup (pDomainNameBuffer); + nLengthOfDomainName = strlen (pDomainName); + } + } + +#endif /* NEW */ +#if 0 /* OBSOLETE */ +#ifdef SCO + + /* call 'domainname > /usr/tmp/some-tmp-file', since + popen read pclose do block or core-dump, + (even the pipe-stuff that comes with pthreads) */ + if (nLengthOfDomainName == 0) + { + sal_Char tmp_name[ L_tmpnam ]; + FILE *tmp_file; + sal_Char domain_call [ L_tmpnam + 16 ] = "domainname > "; + + tmp_name[0] = '\0'; + + tmpnam ( tmp_name ); + strcat ( domain_call, tmp_name ); + if ( (system ( domain_call ) == 0) + && ((tmp_file = fopen( tmp_name, "r" )) != NULL ) ) + { + sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ]; + + pDomainNameBuffer[0] = '\0'; + + if ( fgets ( pDomainNameBuffer, DOMAINNAME_LENGTH, tmp_file ) ) + { + pDomainName = strdup( pDomainNameBuffer ); + nLengthOfDomainName = strlen( pDomainName ); + if ( ( nLengthOfDomainName > 0 ) + && ( pDomainName[ nLengthOfDomainName - 1] == '\n' ) ) + pDomainName[ --nLengthOfDomainName ] = '\0'; + } + fclose ( tmp_file ); + } + unlink( tmp_name ); + } + +#else /* !SCO */ + + /* read the domainname from pipe to the program domainname */ + if ( (nLengthOfDomainName == 0) + && (pPipeToDomainnameExe = popen( "domainname", "r")) ) + { + sal_Char c; + sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ]; + sal_Char *pDomainNamePointer; + + pDomainNameBuffer[0] = '\0'; + + pDomainNamePointer = pDomainNameBuffer; + while ( ((c = getc( pPipeToDomainnameExe )) != EOF) + && (nLengthOfDomainName < (DOMAINNAME_LENGTH - 1)) ) + { + if (! isspace(c)) + { + nLengthOfDomainName++ ; + *pDomainNamePointer++ = (sal_Char)c; + } + } + *pDomainNamePointer = '\0'; + pDomainName = strdup( pDomainNameBuffer ); + + pclose( pPipeToDomainnameExe ); + } + +#endif /* !SCO */ +#endif /* OBSOLETE */ + + /* compose hostname and domainname */ + nLengthOfHostName = strlen( pHostName ); + pFullQualifiedName = (sal_Char*) malloc( (nLengthOfHostName + 1 + + nLengthOfDomainName + 1) * sizeof(sal_Char) ); + memcpy( pFullQualifiedName, pHostName, + (nLengthOfHostName + 1) * sizeof(sal_Char) ); + + if ( nLengthOfDomainName > 0 ) + { + /* fqdn = hostname + '.' + domainname + '\0' */ + pFullQualifiedName[ nLengthOfHostName ] = '.'; + memcpy( pFullQualifiedName + nLengthOfHostName + 1, pDomainName, + nLengthOfDomainName + 1 ); + } + + /* check whether full-qualified name and hostname point to the same host + * should almost always be true */ + if ( nLengthOfDomainName > 0 ) + { + struct hostent *pQualifiedHostByName; + struct hostent *pHostByName; + sal_Bool bHostsAreEqual; + + /* buffer for calls to reentrant version of gethostbyname */ + struct hostent aHostByName, aQualifiedHostByName; + sal_Char pHostBuffer[ MAX_HOSTBUFFER_SIZE ]; + sal_Char pQualifiedHostBuffer[ MAX_HOSTBUFFER_SIZE ]; + int nErrorNo; + + pHostBuffer[0] = '\0'; + pQualifiedHostBuffer[0] = '\0'; + + /* get list of addresses */ + pQualifiedHostByName = _osl_gethostbyname_r ( + pFullQualifiedName, + &aQualifiedHostByName, pQualifiedHostBuffer, + sizeof(pQualifiedHostBuffer), &nErrorNo ); + pHostByName = _osl_gethostbyname_r ( + pHostName, + &aHostByName, pHostBuffer, + sizeof(pHostBuffer), &nErrorNo ); + + /* compare addresses */ + bHostsAreEqual = sal_False; + if ( pQualifiedHostByName && pHostByName ) + { + sal_Char **p, **q; + struct in_addr in; + + /* lists are expected to be (very) short */ + for ( p = pQualifiedHostByName->h_addr_list; *p != NULL; p++ ) + { + for ( q = pHostByName->h_addr_list; *q != NULL; q++ ) + { + /* in.s_addr may be in_addr_t or uint32_t or heaven knows */ + if ( memcmp( *p, *q, sizeof(in.s_addr) ) == 0 ) + { + bHostsAreEqual = sal_True; + break; + } + } + if ( bHostsAreEqual ) + break; + } + } + + /* very strange case, but have to believe it: reduce the + * full qualified name to the unqualified host name */ + if ( !bHostsAreEqual ) + { + OSL_TRACE("_osl_getFullQualifiedDomainName: " + "suspect FQDN: %s\n", pFullQualifiedName); + + pFullQualifiedName[ nLengthOfHostName ] = '\0'; + pFullQualifiedName = (sal_Char*)realloc ( pFullQualifiedName, + (nLengthOfHostName + 1) * sizeof( sal_Char )); + } + } + + /* always return a hostname looked up as carefully as possible + * this string must be freed by the caller */ + return pFullQualifiedName; +} + +/*****************************************************************************/ +/* _osl_isFullQualifiedDomainName */ +/*****************************************************************************/ +static sal_Bool _osl_isFullQualifiedDomainName (const sal_Char *pHostName) +{ + /* a FQDN (aka 'hostname.domain.top_level_domain' ) + * is a name which contains a dot '.' in it ( would + * match as well for 'hostname.' but is good enough + * for now )*/ + return (sal_Bool)( strchr( pHostName, (int)'.' ) != NULL ); +} + +/*****************************************************************************/ +/* oslHostAddr */ +/*****************************************************************************/ +struct oslHostAddrImpl +{ + sal_Char *pHostName; + oslSocketAddr pSockAddr; +}; + +static oslHostAddr _osl_hostentToHostAddr (const struct hostent *he) +{ + oslHostAddr pAddr= NULL; + oslSocketAddr pSockAddr = 0; + + + if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL)) + return ((oslHostAddr)NULL); + + //YD 18/06/2006 win32 does this with unicode, see socket.cxx + sal_Char *cn; + cn= (sal_Char *)malloc(strlen (he->h_name) + 1); + OSL_ASSERT(cn); + if (cn == NULL) + return ((oslHostAddr)NULL); + + strcpy(cn, he->h_name); + +#if 0 // YD 17/04/06 win32 doesn't it. + if (_osl_isFullQualifiedDomainName(he->h_name)) + { + cn= (sal_Char *)malloc(strlen (he->h_name) + 1); + OSL_ASSERT(cn); + if (cn == NULL) + return ((oslHostAddr)NULL); + + strcpy(cn, he->h_name); + } + else + { + cn =_osl_getFullQualifiedDomainName (he->h_name); + OSL_ASSERT(cn); + if (cn == NULL) + return ((oslHostAddr)NULL); + } +#endif + + pSockAddr = __osl_createSocketAddr(); + OSL_ASSERT(pSockAddr); + if (pSockAddr == NULL) + { + free(cn); + return ((oslHostAddr)NULL); + } + + pSockAddr->m_sockaddr.sa_family= he->h_addrtype; + if (pSockAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) + { + struct sockaddr_in *sin= (struct sockaddr_in *)&(pSockAddr->m_sockaddr); + memcpy ( + &(sin->sin_addr.s_addr), + he->h_addr_list[0], + he->h_length); + } + else + { + /* unknown address family */ + /* future extensions for new families might be implemented here */ + + OSL_TRACE("_osl_hostentToHostAddr: unknown address family.\n"); + OSL_ASSERT(sal_False); + + __osl_destroySocketAddr( pSockAddr ); + free (cn); + return ((oslHostAddr)NULL); + } + + pAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl)); + OSL_ASSERT(pAddr); + if (pAddr == NULL) + { + __osl_destroySocketAddr( pSockAddr ); + free (cn); + return ((oslHostAddr)NULL); + } + + pAddr->pHostName= cn; + pAddr->pSockAddr= pSockAddr; + + return pAddr; +} + +/*****************************************************************************/ +/* osl_createHostAddr */ +/*****************************************************************************/ +oslHostAddr SAL_CALL osl_createHostAddr ( + rtl_uString *ustrHostname, + const oslSocketAddr Addr) +{ + oslHostAddr HostAddr; + rtl_String* strHostname=0; + sal_Char* pszHostName=0; + + if ( ustrHostname != 0 ) + { + rtl_uString2String( &strHostname, + rtl_uString_getStr(ustrHostname), + rtl_uString_getLength(ustrHostname), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszHostName = rtl_string_getStr(strHostname); + } + + HostAddr = osl_psz_createHostAddr(pszHostName,Addr); + + if ( strHostname != 0 ) + { + rtl_string_release(strHostname); + } + + + return HostAddr; +} + +oslHostAddr SAL_CALL osl_psz_createHostAddr ( + const sal_Char *pszHostname, + const oslSocketAddr pAddr) +{ + oslHostAddr pHostAddr; + sal_Char *cn; + + OSL_ASSERT(pszHostname && pAddr); + if ((pszHostname == NULL) || (pAddr == NULL)) + return ((oslHostAddr)NULL); + + cn = (sal_Char *)malloc(strlen (pszHostname) + 1); + OSL_ASSERT(cn); + if (cn == NULL) + return ((oslHostAddr)NULL); + + strcpy (cn, pszHostname); + + pHostAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl)); + OSL_ASSERT(pHostAddr); + if (pAddr == NULL) + { + free (cn); + return ((oslHostAddr)NULL); + } + + pHostAddr->pHostName= cn; + pHostAddr->pSockAddr= osl_copySocketAddr( pAddr ); + + return pHostAddr; +} + +/*****************************************************************************/ +/* osl_createHostAddrByName */ +/*****************************************************************************/ +oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname) +{ + oslHostAddr HostAddr; + rtl_String* strHostname=0; + sal_Char* pszHostName=0; + + if ( ustrHostname != 0 ) + { + rtl_uString2String( &strHostname, + rtl_uString_getStr(ustrHostname), + rtl_uString_getLength(ustrHostname), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszHostName=rtl_string_getStr(strHostname); + } + + HostAddr = osl_psz_createHostAddrByName(pszHostName); + + if ( strHostname != 0 ) + { + rtl_string_release(strHostname); + } + + return HostAddr; +} + +oslHostAddr SAL_CALL osl_psz_createHostAddrByName (const sal_Char *pszHostname) +{ + struct hostent *he; + oslHostAddr addr; + + static oslMutex mutex = NULL; + + if (mutex == NULL) + mutex = osl_createMutex(); + + osl_acquireMutex(mutex); + + he = gethostbyname((sal_Char *)pszHostname); + addr = _osl_hostentToHostAddr (he); + + osl_releaseMutex(mutex); + + return addr; +} + +/*****************************************************************************/ +/* osl_createHostAddrByAddr */ +/*****************************************************************************/ +oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr) +{ + OSL_ASSERT(pAddr); + + if (pAddr == NULL) + return ((oslHostAddr)NULL); + + if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) + { + const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr); + struct hostent *he; + + if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) + return ((oslHostAddr)NULL); + + he= gethostbyaddr((sal_Char *)&(sin->sin_addr), + sizeof (sin->sin_addr), + sin->sin_family); + return _osl_hostentToHostAddr (he); + } + + return ((oslHostAddr)NULL); +} + +/*****************************************************************************/ +/* osl_copyHostAddr */ +/*****************************************************************************/ +oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr) +{ + OSL_ASSERT(pAddr); + + if (pAddr) + return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr); + else + return ((oslHostAddr)NULL); +} + +/*****************************************************************************/ +/* osl_getHostnameOfHostAddr */ +/*****************************************************************************/ +void SAL_CALL osl_getHostnameOfHostAddr ( + const oslHostAddr Addr, + rtl_uString **ustrHostname) +{ + const sal_Char* pHostname=0; + + pHostname = osl_psz_getHostnameOfHostAddr(Addr); + + rtl_uString_newFromAscii (ustrHostname, pHostname); + + return; +} + +const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr) +{ + OSL_ASSERT(pAddr); + + if (pAddr) + return pAddr->pHostName; + else + return NULL; +} + +/*****************************************************************************/ +/* osl_getSocketAddrOfHostAddr */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr) +{ + OSL_ASSERT(pAddr); + + if (pAddr) + return ((oslSocketAddr)(pAddr->pSockAddr)); + else + return NULL; +} + +/*****************************************************************************/ +/* osl_destroyHostAddr */ +/*****************************************************************************/ +void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr) +{ + if (pAddr) + { + if (pAddr->pHostName) + free (pAddr->pHostName); + if (pAddr->pSockAddr) + osl_destroySocketAddr (pAddr->pSockAddr); + free (pAddr); + } +} + +/*****************************************************************************/ +/* osl_getLocalHostname */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname) +{ + oslSocketResult Result; + sal_Char pszHostname[1024]; + + pszHostname[0] = '\0'; + + Result = osl_psz_getLocalHostname(pszHostname,sizeof(pszHostname)); + + rtl_uString_newFromAscii(ustrLocalHostname,pszHostname); + + return Result; +} + +oslSocketResult SAL_CALL osl_psz_getLocalHostname ( + sal_Char *pBuffer, sal_uInt32 nBufLen) +{ + static sal_Char LocalHostname[256] = ""; + + if (strlen(LocalHostname) == 0) + { + const sal_Char *pStr; + +#ifdef SYSV + struct utsname uts; + + if (uname(&uts) < 0) + return osl_Socket_Error; + + if ((strlen(uts.nodename) + 1) > nBufLen) + return osl_Socket_Error; + + strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname )); +#else /* BSD compatible */ + + if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0) + return osl_Socket_Error; + LocalHostname[sizeof(LocalHostname)-1] = 0; +#endif /* SYSV */ + + /* check if we have an FQDN */ + if (strchr(LocalHostname, '.') == NULL) + { + oslHostAddr Addr; + + /* no, determine it via dns */ + Addr = osl_psz_createHostAddrByName(LocalHostname); + + if (Addr && (pStr = osl_psz_getHostnameOfHostAddr(Addr)) != NULL) + { +#if 0 /* OBSOLETE */ + sal_Char* pChr; +#endif /* OBSOLETE */ + strcpy(LocalHostname, pStr); + +#if 0 /* OBSOLETE */ + /* already done by _osl_getFullQualifiedDomainName() with + much better heuristics, so this may be contraproductive */ + + /* no FQDN, last try append domain name */ + if ((pChr = strchr(LocalHostname, '.')) == NULL) + { + FILE *fp; + + pChr = &LocalHostname[strlen(LocalHostname)]; + + if ( (fp = popen("domainname", "r")) != 0 ) + { + int c; + + *pChr++ = '.'; + + while ((c = getc(fp)) != EOF) + { + if (! isspace(c)) + *pChr++ = (sal_Char)c; + } + + *pChr = '\0'; + + fclose(fp); + } + else + LocalHostname[0] = '\0'; + } +#endif /* OBSOLETE */ + + } + if (Addr) + osl_destroyHostAddr(Addr); + } + } + + if (strlen(LocalHostname) > 0) + { + strncpy(pBuffer, LocalHostname, nBufLen); + pBuffer[nBufLen - 1] = '\0'; + + return osl_Socket_Ok; + } + + return osl_Socket_Error; +} + +/*****************************************************************************/ +/* osl_resolveHostname */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname) +{ + oslSocketAddr Addr; + rtl_String* strHostname=0; + sal_Char* pszHostName=0; + + if ( ustrHostname != 0 ) + { + rtl_uString2String( &strHostname, + rtl_uString_getStr(ustrHostname), + rtl_uString_getLength(ustrHostname), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszHostName = rtl_string_getStr(strHostname); + } + + + Addr = osl_psz_resolveHostname(pszHostName); + + if ( strHostname != 0 ) + { + rtl_string_release(strHostname); + } + + + return Addr; +} + + +oslSocketAddr SAL_CALL osl_psz_resolveHostname(const sal_Char* pszHostname) +{ + struct oslHostAddrImpl *pAddr = (oslHostAddr)osl_psz_createHostAddrByName(pszHostname); + + if (pAddr) + { + oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr); + + osl_destroyHostAddr(pAddr); + + return (SockAddr); + } + + return ((oslSocketAddr)NULL); +} + +/*****************************************************************************/ +/* osl_getServicePort */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol) +{ + sal_Int32 nPort; + rtl_String* strServicename=0; + rtl_String* strProtocol=0; + sal_Char* pszServiceName=0; + sal_Char* pszProtocol=0; + + if ( ustrServicename != 0 ) + { + rtl_uString2String( &strServicename, + rtl_uString_getStr(ustrServicename), + rtl_uString_getLength(ustrServicename), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszServiceName = rtl_string_getStr(strServicename); + } + + if ( ustrProtocol != 0 ) + { + rtl_uString2String( &strProtocol, + rtl_uString_getStr(ustrProtocol), + rtl_uString_getLength(ustrProtocol), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszProtocol = rtl_string_getStr(strProtocol); + } + + nPort = osl_psz_getServicePort(pszServiceName,pszProtocol); + + if ( strServicename != 0 ) + { + rtl_string_release(strServicename); + } + + if ( strProtocol != 0 ) + { + rtl_string_release(strProtocol); + } + + + return nPort; +} + + +sal_Int32 SAL_CALL osl_psz_getServicePort(const sal_Char* pszServicename, + const sal_Char* pszProtocol) +{ + struct servent* ps; + + ps= getservbyname(pszServicename, pszProtocol); + + if (ps != 0) + return ntohs(ps->s_port); + + return OSL_INVALID_PORT; +} + +/*****************************************************************************/ +/* osl_destroySocketAddr */ +/*****************************************************************************/ +void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr) +{ + __osl_destroySocketAddr( pAddr ); +} + +/*****************************************************************************/ +/* osl_getFamilyOfSocketAddr */ +/*****************************************************************************/ +oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr) +{ + OSL_ASSERT(pAddr); + + if (pAddr) + return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family); + else + return osl_Socket_FamilyInvalid; +} + +/*****************************************************************************/ +/* osl_getInetPortOfSocketAddr */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr) +{ + OSL_ASSERT(pAddr); + if( pAddr ) + { + struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr); + + if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) + return ntohs(pSystemInetAddr->sin_port); + } + return OSL_INVALID_PORT; +} + +/*****************************************************************************/ +/* osl_setInetPortOfSocketAddr */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port) +{ + OSL_ASSERT(pAddr); + if( pAddr ) + { + struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr); + if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) + { + pSystemInetAddr->sin_port= htons((short)Port); + return sal_True; + } + } + + /* this is not a inet-addr => can't set port */ + return sal_False; +} + +/*****************************************************************************/ +/* osl_getHostnameOfSocketAddr */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname) +{ + oslSocketResult Result; + sal_Char pszHostname[1024]; + + pszHostname[0] = '\0'; + + Result = osl_psz_getHostnameOfSocketAddr(Addr,pszHostname,sizeof(pszHostname)); + + rtl_uString_newFromAscii(ustrHostname,pszHostname); + + return Result; +} + + +oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr, + sal_Char *pBuffer, sal_uInt32 BufferSize) +{ + oslHostAddr pHostAddr= (oslHostAddr )osl_createHostAddrByAddr(pAddr); + + if (pHostAddr) + { + strncpy(pBuffer, pHostAddr->pHostName, BufferSize); + + pBuffer[BufferSize - 1] = '\0'; + + osl_destroyHostAddr(pHostAddr); + + return osl_Socket_Ok; + } + + return osl_Socket_Error; +} + +/*****************************************************************************/ +/* osl_getDottedInetAddrOfSocketAddr */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr) +{ + oslSocketResult Result; + sal_Char pszDottedInetAddr[1024]; + + pszDottedInetAddr[0] = '\0'; + + Result = osl_psz_getDottedInetAddrOfSocketAddr(Addr,pszDottedInetAddr,sizeof(pszDottedInetAddr)); + + rtl_uString_newFromAscii(ustrDottedInetAddr,pszDottedInetAddr); + + return Result; + +} + +oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr, + sal_Char *pBuffer, sal_uInt32 BufferSize) +{ + OSL_ASSERT(pAddr); + + if( pAddr ) + { + struct sockaddr_in* pSystemInetAddr = ( struct sockaddr_in * ) &(pAddr->m_sockaddr); + + if (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) + { + strncpy(pBuffer, inet_ntoa(pSystemInetAddr->sin_addr), BufferSize); + pBuffer[BufferSize - 1] = '\0'; + + return osl_Socket_Ok; + } + } + + return osl_Socket_Error; +} + +#if 0 /* OBSOLETE */ +/*****************************************************************************/ +/* osl_getIpxNetNumber */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_getIpxNetNumber(oslSocketAddr Addr, + oslSocketIpxNetNumber NetNumber) + +{ + struct sockaddr_ipx* pAddr; + + pAddr= (struct sockaddr_ipx*)Addr; + + OSL_ASSERT(pAddr); + + if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx))) + { + memcpy(NetNumber, pAddr->sa_netnum, sizeof(NetNumber)); + + return osl_Socket_Ok; + } + else + return osl_Socket_Error; +} + + +/*****************************************************************************/ +/* osl_getIpxNodeNumber */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_getIpxNodeNumber(oslSocketAddr Addr, + oslSocketIpxNodeNumber NodeNumber) + +{ + struct sockaddr_ipx* pAddr; + + pAddr= (struct sockaddr_ipx*)Addr; + + OSL_ASSERT(pAddr); + + if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx))) + { + memcpy(NodeNumber, pAddr->sa_nodenum, sizeof(NodeNumber)); + + return osl_Socket_Ok; + } + else + return osl_Socket_Error; +} + + +/*****************************************************************************/ +/* osl_getIpxSocketNumber */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_getIpxSocketNumber(oslSocketAddr Addr) +{ + struct sockaddr_ipx* pAddr= (struct sockaddr_ipx*)Addr; + OSL_ASSERT(pAddr); + + if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx))) + return pAddr->sa_socket; + else + return OSL_INVALID_IPX_SOCKET_NO; +} + +#endif /* OBSOLETE */ + +/*****************************************************************************/ +/* osl_createSocket */ +/*****************************************************************************/ +oslSocket SAL_CALL osl_createSocket(oslAddrFamily Family, + oslSocketType Type, + oslProtocol Protocol) +{ + int Flags; + oslSocket pSocket; + + /* alloc memory */ + pSocket= __osl_createSocketImpl(OSL_INVALID_SOCKET); + + /* create socket */ + pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family), + TYPE_TO_NATIVE(Type), + PROTOCOL_TO_NATIVE(Protocol)); + + /* creation failed => free memory */ + if(pSocket->m_Socket == OSL_INVALID_SOCKET) + { + OSL_TRACE("osl_createSocket failed. Errno: %d; %s\n", + errno, + strerror(errno)); + + __osl_destroySocketImpl((pSocket)); + pSocket= 0; + } + else + { + /* set close-on-exec flag */ + if ((Flags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1) + { + Flags |= FD_CLOEXEC; + if (fcntl(pSocket->m_Socket, F_SETFD, Flags) == -1) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_createSocket failed changing socket flags. Errno: %d; %s\n", + errno, + strerror(errno)); + } + } + else + { + pSocket->m_nLastError=errno; + } + + + pSocket->m_CloseCallback = NULL; + pSocket->m_CallbackArg = NULL; + } + + return pSocket; +} + +void SAL_CALL osl_acquireSocket(oslSocket pSocket) +{ + osl_incrementInterlockedCount( &(pSocket->m_nRefCount ) ); +} + +void SAL_CALL osl_releaseSocket( oslSocket pSocket ) +{ + if( pSocket && 0 == osl_decrementInterlockedCount( &(pSocket->m_nRefCount) ) ) + { +#if defined(LINUX) + if ( pSocket->m_bIsAccepting == sal_True ) + { + OSL_ENSURE(0, "osl_destroySocket : attempt to destroy socket while accepting\n"); + return; + } +#endif /* LINUX */ + osl_closeSocket( pSocket ); + __osl_destroySocketImpl( pSocket ); + } +} + + + +/*****************************************************************************/ +/* osl_closeSocket */ +/*****************************************************************************/ +void SAL_CALL osl_closeSocket(oslSocket pSocket) +{ + int nRet; + int nFD; + + /* socket already invalid */ + if(pSocket==0) + return; + + pSocket->m_nLastError=0; + nFD = pSocket->m_Socket; + + pSocket->m_Socket = OSL_INVALID_SOCKET; + +#if defined(LINUX) + pSocket->m_bIsInShutdown = sal_True; + + if ( pSocket->m_bIsAccepting == sal_True ) + { + int nConnFD; + struct sockaddr aSockAddr; + socklen_t nSockLen = sizeof(aSockAddr); + + nRet = getsockname(nFD, &aSockAddr, &nSockLen); +#if OSL_DEBUG_LEVEL > 1 + if ( nRet < 0 ) + { + perror("getsockname"); + } +#endif /* OSL_DEBUG_LEVEL */ + + if ( aSockAddr.sa_family == AF_INET ) + { + struct sockaddr_in* pSockAddrIn = (struct sockaddr_in*) &aSockAddr; + + if ( pSockAddrIn->sin_addr.s_addr == htonl(INADDR_ANY) ) + { + pSockAddrIn->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + + nConnFD = socket(AF_INET, SOCK_STREAM, 0); +#if OSL_DEBUG_LEVEL > 1 + if ( nConnFD < 0 ) + { + perror("socket"); + } +#endif /* OSL_DEBUG_LEVEL */ + + nRet = connect(nConnFD, &aSockAddr, sizeof(aSockAddr)); +#if OSL_DEBUG_LEVEL > 1 + if ( nRet < 0 ) + { + perror("connect"); + } +#endif /* OSL_DEBUG_LEVEL */ + close(nConnFD); + } + } +#endif /* LINUX */ + + /* registrierten Callback ausfuehren */ + if (pSocket->m_CloseCallback != NULL) + { + pSocket->m_CloseCallback(pSocket->m_CallbackArg); + } + + nRet=close(nFD); + if ( nRet != 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("closeSocket close error '%s'\n",strerror(errno)); + } + + pSocket->m_Socket = OSL_INVALID_SOCKET; +} + +/*****************************************************************************/ +/* osl_getLocalAddrOfSocket */ +/* Note that I rely on the fact that oslSocketAddr and struct sockaddr */ +/* are the same! I don't like it very much but see no other easy way to conceal */ +/* the struct sockaddr from the eyes of the user. */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket) +{ +#if defined(LINUX) || defined(FREEBSD) + socklen_t AddrLen; +#else + /* mfe: Solaris 'cc +w' means Addrlen should be signed! */ + /* it's really defined as 'int*' in /usr/include/sys/socket.h! */ + /* the man page says it expects a 'size_t' */ + int AddrLen; +#endif + struct sockaddr Addr; + oslSocketAddr pAddr; + + if (pSocket == NULL) /* ENOTSOCK */ + return ((oslSocketAddr)NULL); + + AddrLen= sizeof(struct sockaddr); + + if (getsockname(pSocket->m_Socket, &Addr, PTR_SIZE_T(AddrLen)) == OSL_SOCKET_ERROR) + return ((oslSocketAddr)NULL); + + pAddr = __osl_createSocketAddrFromSystem( &Addr ); + return pAddr; +} + +/*****************************************************************************/ +/* osl_getPeerAddrOfSocket */ +/*****************************************************************************/ +oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket) +{ + sal_uInt32 AddrLen; + struct sockaddr Addr; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return 0; + } + + pSocket->m_nLastError=0; + AddrLen= sizeof(struct sockaddr); + + if(getpeername(pSocket->m_Socket, &Addr, (int*)PTR_SIZE_T(AddrLen)) == OSL_SOCKET_ERROR) + { + pSocket->m_nLastError=errno; + return 0; + } + return __osl_createSocketAddrFromSystem( &Addr ); +} + +/*****************************************************************************/ +/* osl_bindAddrToSocket */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket, + oslSocketAddr pAddr) +{ + int nRet; + + OSL_ASSERT(pSocket && pAddr ); + if ( pSocket == 0 || pAddr == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr)); + + if ( nRet == OSL_SOCKET_ERROR) + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + + +/*****************************************************************************/ +/* osl_listenOnSocket */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket, + sal_Int32 MaxPendingConnections) +{ + int nRet; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + nRet = listen(pSocket->m_Socket, + MaxPendingConnections == -1 ? + SOMAXCONN : + MaxPendingConnections); + if ( nRet == OSL_SOCKET_ERROR) + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + + +/*****************************************************************************/ +/* osl_connectSocketTo */ +/*****************************************************************************/ +oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket, + oslSocketAddr pAddr, + const TimeValue* pTimeout) +{ + fd_set WriteSet; + fd_set ExcptSet; + int ReadyHandles; + struct timeval tv; + oslSocketResult Result= osl_Socket_Ok; + + OSL_PRECOND(pSocket, "osl_connectSocketTo(): need a valid socket!\n"); + + if ( pSocket == 0 ) + { + return osl_Socket_Error; + } + + pSocket->m_nLastError=0; + + if (osl_isNonBlockingMode(pSocket)) + { + if (connect(pSocket->m_Socket, + &(pAddr->m_sockaddr), + sizeof(struct sockaddr)) != OSL_SOCKET_ERROR) + return osl_Socket_Ok; + else + if (errno == EWOULDBLOCK || errno == EINPROGRESS) + { + pSocket->m_nLastError=EINPROGRESS; + return osl_Socket_InProgress; + } + + + pSocket->m_nLastError=errno; + OSL_TRACE("can't connect : '%s'",strerror(errno)); + return osl_Socket_Error; + } + + /* set socket temporarily to non-blocking */ + OSL_VERIFY(osl_enableNonBlockingMode(pSocket, sal_True)); + + /* initiate connect */ + if(connect(pSocket->m_Socket, + &(pAddr->m_sockaddr), + sizeof(struct sockaddr)) != OSL_SOCKET_ERROR) + { + /* immediate connection */ + osl_enableNonBlockingMode(pSocket, sal_False); + + return osl_Socket_Ok; + } + else + { + /* really an error or just delayed? */ + if (errno != EINPROGRESS) + { + pSocket->m_nLastError=errno; + OSL_TRACE( + "osl_connectSocketTo(): connect failed: errno: %d (%s)\n", + errno, strerror(errno)); + + osl_enableNonBlockingMode(pSocket, sal_False); + return osl_Socket_Error; + } + } + + + /* prepare select set for socket */ + FD_ZERO(&WriteSet); + FD_ZERO(&ExcptSet); + FD_SET(pSocket->m_Socket, &WriteSet); + FD_SET(pSocket->m_Socket, &ExcptSet); + + /* prepare timeout */ + if (pTimeout) + { + /* divide milliseconds into seconds and microseconds */ + tv.tv_sec= pTimeout->Seconds; + tv.tv_usec= pTimeout->Nanosec / 1000L; + } + + /* select */ + ReadyHandles= select(pSocket->m_Socket+1, + 0, + PTR_FD_SET(WriteSet), + PTR_FD_SET(ExcptSet), + (pTimeout) ? &tv : 0); + + if (ReadyHandles > 0) /* connected */ + { + if ( FD_ISSET(pSocket->m_Socket, &WriteSet ) ) + { + int nErrorCode = 0; +#ifdef SOLARIS +/* mfe: Solaris 'cc +w' means 5th argument should be a 'int*'! + it's really defined as 'int*' in /usr/include/sys/socket.h! + the man page says it expects a 'size_t*' +*/ + int nErrorSize = sizeof( nErrorCode ); +#else + size_t nErrorSize = sizeof( nErrorCode ); +#endif + + int nSockOpt; + + nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR, +#ifdef SOLARIS +/* mfe: Solaris 'cc +w' means 4th argument should be a 'char*'! + it's really defined as 'char*' in /usr/include/sys/socket.h! + the man page says it expects a 'void*' +*/ + (char*) +#endif + &nErrorCode, (int*)&nErrorSize ); + if ( (nSockOpt == 0) && (nErrorCode == 0)) + Result = osl_Socket_Ok; + else + Result = osl_Socket_Error; + } + else + { + Result= osl_Socket_Error; + } + } + else if (ReadyHandles < 0) /* error */ + { + if (errno == EBADF) /* most probably interrupted by close() */ + { + /* do not access pSockImpl because it is about to be or */ + /* already destroyed */ + return osl_Socket_Interrupted; + } + else + { + pSocket->m_nLastError=errno; + Result= osl_Socket_Error; + } + } + else /* timeout */ + { + pSocket->m_nLastError=errno; + Result= osl_Socket_TimedOut; + } + + osl_enableNonBlockingMode(pSocket, sal_False); + + return Result; +} + + +/*****************************************************************************/ +/* osl_acceptConnectionOnSocket */ +/*****************************************************************************/ +oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket, + oslSocketAddr* ppAddr) +{ + struct sockaddr Addr; + int Connection, Flags; + sal_uInt32 AddrLen = sizeof(struct sockaddr); + oslSocket pConnectionSockImpl; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return 0; + } + + pSocket->m_nLastError=0; +#if defined(LINUX) + pSocket->m_bIsAccepting = sal_True; +#endif /* LINUX */ + + if( ppAddr && *ppAddr ) + { + osl_destroySocketAddr( *ppAddr ); + *ppAddr = 0; + } + + /* prevent Linux EINTR behaviour */ + do + { + Connection = accept(pSocket->m_Socket, &Addr, (int*)PTR_SIZE_T(AddrLen)); + } while (Connection == -1 && errno == EINTR); + + + /* accept failed? */ + if( Connection == OSL_SOCKET_ERROR ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_acceptConnectionOnSocket : accept error '%s'\n",strerror(errno)); + +#if defined(LINUX) + pSocket->m_bIsAccepting = sal_False; +#endif /* LINUX */ + return 0; + } + + OSL_ASSERT(AddrLen == sizeof(struct sockaddr)); + + +#if defined(LINUX) + if ( pSocket->m_bIsInShutdown == sal_True ) + { + close(Connection); + OSL_TRACE("osl_acceptConnectionOnSocket : close while accept\n"); + return 0; + } +#endif /* LINUX */ + + + if(ppAddr) + { + *ppAddr= __osl_createSocketAddrFromSystem(&Addr); + } + + /* alloc memory */ + pConnectionSockImpl= __osl_createSocketImpl(OSL_INVALID_SOCKET); + + /* set close-on-exec flag */ + if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1) + { + Flags |= FD_CLOEXEC; + if (fcntl(Connection, F_SETFD, Flags) == -1) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_acceptConnectionOnSocket failed changing socket flags. Errno: %d (%s)\n", + errno, + strerror(errno)); + } + + } + + pConnectionSockImpl->m_Socket = Connection; + pConnectionSockImpl->m_nLastError = 0; + pConnectionSockImpl->m_CloseCallback = NULL; + pConnectionSockImpl->m_CallbackArg = NULL; +#if defined(LINUX) + pConnectionSockImpl->m_bIsAccepting = sal_False; + + pSocket->m_bIsAccepting = sal_False; +#endif /* LINUX */ + return pConnectionSockImpl; +} + +/*****************************************************************************/ +/* osl_receiveSocket */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket, + void* pBuffer, + sal_uInt32 BytesToRead, + oslSocketMsgFlag Flag) +{ + int nRead; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + OSL_TRACE("osl_receiveSocket : Invalid socket"); + return -1; + } + + pSocket->m_nLastError=0; + + do + { + nRead = recv(pSocket->m_Socket, + (sal_Char*)pBuffer, + BytesToRead, + MSG_FLAG_TO_NATIVE(Flag)); + } while ( nRead < 0 && errno == EINTR ); + + if ( nRead < 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,strerror(errno)); + } + else if ( nRead == 0 ) + { + OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL"); + } + + return nRead; +} + + +/*****************************************************************************/ +/* osl_receiveFromSocket */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket, + oslSocketAddr pSenderAddr, + void* pBuffer, + sal_uInt32 BufferSize, + oslSocketMsgFlag Flag) +{ + int nRead; + struct sockaddr *pSystemSockAddr = 0; + int AddrLen = 0; + if( pSenderAddr ) + { + AddrLen = sizeof( struct sockaddr ); + pSystemSockAddr = &(pSenderAddr->m_sockaddr); + } + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + OSL_TRACE("osl_receiveFromSocket : Invalid socket"); + return -1; + } + + pSocket->m_nLastError=0; + + nRead = recvfrom(pSocket->m_Socket, + (sal_Char*)pBuffer, + BufferSize, + MSG_FLAG_TO_NATIVE(Flag), + pSystemSockAddr, + PTR_SIZE_T(AddrLen)); + + if ( nRead < 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_receiveFromSocket failed : %i '%s'",nRead,strerror(errno)); + } + else if ( nRead == 0 ) + { + OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL"); + } + + return nRead; +} + + +/*****************************************************************************/ +/* osl_sendSocket */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket, + const void* pBuffer, + sal_uInt32 BytesToSend, + oslSocketMsgFlag Flag) +{ + int nWritten; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + OSL_TRACE("osl_sendSocket : Invalid socket"); + return -1; + } + + pSocket->m_nLastError=0; + + do + { + nWritten = send(pSocket->m_Socket, + (sal_Char*)pBuffer, + BytesToSend, + MSG_FLAG_TO_NATIVE(Flag)); + } while ( nWritten < 0 && errno == EINTR ); + + + if ( nWritten < 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,strerror(errno)); + } + else if ( nWritten == 0 ) + { + OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,"EOL"); + } + + return nWritten; +} + +/*****************************************************************************/ +/* osl_sendToSocket */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket, + oslSocketAddr ReceiverAddr, + const void* pBuffer, + sal_uInt32 BytesToSend, + oslSocketMsgFlag Flag) +{ + int nWritten; + + struct sockaddr *pSystemSockAddr = 0; + int AddrLen = 0; + if( ReceiverAddr ) + { + pSystemSockAddr = &(ReceiverAddr->m_sockaddr); + AddrLen = sizeof( struct sockaddr ); + } + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + OSL_TRACE("osl_sendToSocket : Invalid socket"); + return -1; + } + + pSocket->m_nLastError=0; + + /* ReceiverAddr might be 0 when used on a connected socket. */ + /* Then sendto should behave like send. */ + + nWritten = sendto(pSocket->m_Socket, + (sal_Char*)pBuffer, + BytesToSend, + MSG_FLAG_TO_NATIVE(Flag), + pSystemSockAddr, + AddrLen); + + if ( nWritten < 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,strerror(errno)); + } + else if ( nWritten == 0 ) + { + OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,"EOL"); + } + + return nWritten; +} + +/*****************************************************************************/ +/* osl_readSocket */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_readSocket ( + oslSocket pSocket, void *pBuffer, sal_Int32 n ) +{ + sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer; + sal_uInt32 BytesRead= 0; + sal_uInt32 BytesToRead= n; + + OSL_ASSERT( pSocket); + + /* loop until all desired bytes were read or an error occured */ + while (BytesToRead > 0) + { + sal_Int32 RetVal; + RetVal= osl_receiveSocket(pSocket, + Ptr, + BytesToRead, + osl_Socket_MsgNormal); + + /* error occured? */ + if(RetVal <= 0) + { + break; + } + + BytesToRead -= RetVal; + BytesRead += RetVal; + Ptr += RetVal; + } + + return BytesRead; +} + +/*****************************************************************************/ +/* osl_writeSocket */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_writeSocket( + oslSocket pSocket, const void *pBuffer, sal_Int32 n ) +{ + /* loop until all desired bytes were send or an error occured */ + sal_uInt32 BytesSend= 0; + sal_uInt32 BytesToSend= n; + sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer; + + OSL_ASSERT( pSocket ); + + while (BytesToSend > 0) + { + sal_Int32 RetVal; + + RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal); + + /* error occured? */ + if(RetVal <= 0) + { + break; + } + + BytesToSend -= RetVal; + BytesSend += RetVal; + Ptr += RetVal; + + } + return BytesSend; +} + +/*****************************************************************************/ +/* __osl_socket_poll */ +/*****************************************************************************/ + +#ifdef HAVE_POLL_H /* poll() */ + +sal_Bool __osl_socket_poll ( + oslSocket pSocket, + const TimeValue* pTimeout, + short nEvent) +{ + struct pollfd fds; + int timeout; + int result; + + OSL_ASSERT(pSocket); + pSocket->m_nLastError = 0; + + fds.fd = pSocket->m_Socket; + fds.events = nEvent; + fds.revents = 0; + + timeout = -1; + if (pTimeout) + { + /* Convert to [ms] */ + timeout = pTimeout->Seconds * 1000; + timeout += pTimeout->Nanosec / (1000 * 1000); + } + + result = poll (&fds, 1, timeout); + if (result < 0) + { + pSocket->m_nLastError = errno; + OSL_TRACE("__osl_socket_poll(): poll error: %d (%s)", + errno, strerror(errno)); + return sal_False; + } + if (result == 0) + { + /* Timeout */ + return sal_False; + } + + return ((fds.revents & nEvent) == nEvent); +} + +#else /* select() */ + +sal_Bool __osl_socket_poll ( + oslSocket pSocket, + const TimeValue* pTimeout, + short nEvent) +{ + fd_set fds; + struct timeval tv; + int result; + + OSL_ASSERT(pSocket); + pSocket->m_nLastError = 0; + + FD_ZERO(&fds); + FD_SET(pSocket->m_Socket, &fds); + + if (pTimeout) + { + /* Convert to 'timeval' */ + tv.tv_sec = pTimeout->Seconds; + tv.tv_usec = pTimeout->Nanosec / 1000; + } + + result = select ( + pSocket->m_Socket + 1, + (nEvent == POLLIN ) ? PTR_FD_SET(fds) : NULL, + (nEvent == POLLOUT) ? PTR_FD_SET(fds) : NULL, + (nEvent == POLLPRI) ? PTR_FD_SET(fds) : NULL, + (pTimeout) ? &tv : NULL); + + if (result < 0) + { + pSocket->m_nLastError = errno; + OSL_TRACE("__osl_socket_poll(): select error: %d (%s)", + errno, strerror(errno)); + return sal_False; + } + if (result == 0) + { + /* Timeout */ + return sal_False; + } + + return (FD_ISSET(pSocket->m_Socket, &fds) ? sal_True : sal_False); +} + +#endif /* HAVE_POLL_H */ + +/*****************************************************************************/ +/* osl_isReceiveReady */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isReceiveReady ( + oslSocket pSocket, const TimeValue* pTimeout) +{ + OSL_ASSERT(pSocket); + if (pSocket == NULL) + { + /* ENOTSOCK */ + return sal_False; + } + + return __osl_socket_poll (pSocket, pTimeout, POLLIN); +} + +/*****************************************************************************/ +/* osl_isSendReady */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isSendReady ( + oslSocket pSocket, const TimeValue* pTimeout) +{ + OSL_ASSERT(pSocket); + if (pSocket == NULL) + { + /* ENOTSOCK */ + return sal_False; + } + + return __osl_socket_poll (pSocket, pTimeout, POLLOUT); +} + +/*****************************************************************************/ +/* osl_isExceptionPending */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isExceptionPending ( + oslSocket pSocket, const TimeValue* pTimeout) +{ + OSL_ASSERT(pSocket); + if (pSocket == NULL) + { + /* ENOTSOCK */ + return sal_False; + } + + return __osl_socket_poll (pSocket, pTimeout, POLLPRI); +} + +/*****************************************************************************/ +/* osl_shutdownSocket */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket, + oslSocketDirection Direction) +{ + int nRet; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction)); + if (nRet != 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("shutdown error '%s'\n",strerror(errno)); + } + return (nRet==0); +} + + +/*****************************************************************************/ +/* osl_getSocketOption */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket, + oslSocketOptionLevel Level, + oslSocketOption Option, + void* pBuffer, + sal_uInt32 BufferLen) +{ + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return -1; + } + + pSocket->m_nLastError=0; + + if(getsockopt(pSocket->m_Socket, + OPTION_LEVEL_TO_NATIVE(Level), + OPTION_TO_NATIVE(Option), + (sal_Char*)pBuffer, + (int*)PTR_SIZE_T(BufferLen)) == -1) + { + pSocket->m_nLastError=errno; + return -1; + } + + return BufferLen; +} + +/*****************************************************************************/ +/* osl_setSocketOption */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket, + oslSocketOptionLevel Level, + oslSocketOption Option, + void* pBuffer, + sal_uInt32 BufferLen) +{ + int nRet; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + nRet = setsockopt(pSocket->m_Socket, + OPTION_LEVEL_TO_NATIVE(Level), + OPTION_TO_NATIVE(Option), + (sal_Char*)pBuffer, + BufferLen); + + if ( nRet < 0 ) + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + +/*****************************************************************************/ +/* osl_enableNonBlockingMode */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket, + sal_Bool On) +{ + int flags; + int nRet; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + flags = fcntl(pSocket->m_Socket, F_GETFL, 0); + + if (On) + flags |= O_NONBLOCK; + else + flags &= ~(O_NONBLOCK); + + nRet = fcntl(pSocket->m_Socket, F_SETFL, flags); + + if ( nRet < 0 ) + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + +/*****************************************************************************/ +/* osl_isNonBlockingMode */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket) +{ + int flags; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + flags = fcntl(pSocket->m_Socket, F_GETFL, 0); + + if (flags == -1 || !(flags & O_NONBLOCK)) + return sal_False; + else + return sal_True; +} + +/*****************************************************************************/ +/* osl_getSocketType */ +/*****************************************************************************/ +oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket) +{ + int Type=0; + sal_uInt32 TypeSize= sizeof(Type); + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return osl_Socket_TypeInvalid; + } + + pSocket->m_nLastError=0; + + if(getsockopt(pSocket->m_Socket, + OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket), + OPTION_TO_NATIVE(osl_Socket_OptionType), + (sal_Char*)&Type, + (int*)PTR_SIZE_T(TypeSize)) == -1) + { + /* error */ + pSocket->m_nLastError=errno; + return osl_Socket_TypeInvalid; + } + + return TYPE_FROM_NATIVE(Type); + +} + +/*****************************************************************************/ +/* osl_getLastSocketErrorDescription */ +/*****************************************************************************/ +void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError) +{ + sal_Char pszError[1024]; + + pszError[0] = '\0'; + + osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError)); + + rtl_uString_newFromAscii(ustrError,pszError); + + return; +} + + +void SAL_CALL osl_psz_getLastSocketErrorDescription(oslSocket pSocket, sal_Char* pBuffer, sal_uInt32 BufferSize) +{ + /* make shure pBuffer will be a zero-terminated string even when strncpy has to cut */ + pBuffer[BufferSize-1]= '\0'; + + if ( pSocket == 0 ) + { + strncpy(pBuffer, strerror(EINVAL), BufferSize-1); + return; + } + + strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1); + return; +} + +/*****************************************************************************/ +/* osl_getLastSocketError */ +/*****************************************************************************/ +oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket) +{ + if ( pSocket == 0 ) + { + return ERROR_FROM_NATIVE(EINVAL); + } + + return ERROR_FROM_NATIVE(pSocket->m_nLastError); +} + +/*****************************************************************************/ +/* SocketSet */ +/*****************************************************************************/ +typedef struct _TSocketSetImpl +{ + int m_MaxHandle; /* for select(), the largest descriptor in the set */ + fd_set m_Set; /* the set of descriptors */ + +} TSocketSetImpl; + +/*****************************************************************************/ +/* osl_createSocketSet */ +/*****************************************************************************/ +oslSocketSet SAL_CALL osl_createSocketSet() +{ + TSocketSetImpl* pSet; + + pSet= (TSocketSetImpl*)malloc(sizeof(TSocketSetImpl)); + + OSL_ASSERT(pSet); + + if(pSet) + { + pSet->m_MaxHandle= 0; + FD_ZERO(&pSet->m_Set); + } + + return (oslSocketSet)pSet; +} + +/*****************************************************************************/ +/* osl_destroySocketSet */ +/*****************************************************************************/ +void SAL_CALL osl_destroySocketSet(oslSocketSet Set) +{ + if(Set) + free(Set); +} + +/*****************************************************************************/ +/* osl_clearSocketSet */ +/*****************************************************************************/ +void SAL_CALL osl_clearSocketSet(oslSocketSet Set) +{ + TSocketSetImpl* pSet; + OSL_ASSERT(Set); + if ( Set == 0 ) + { + return; + } + + pSet= (TSocketSetImpl*)Set; + pSet->m_MaxHandle= 0; + + FD_ZERO(&pSet->m_Set); +} + +/*****************************************************************************/ +/* osl_addToSocketSet */ +/*****************************************************************************/ +void SAL_CALL osl_addToSocketSet(oslSocketSet Set, oslSocket pSocket) +{ + TSocketSetImpl* pSet; + + OSL_ASSERT(Set); + OSL_ASSERT(pSocket); + + if ( Set == 0 || pSocket == 0) + { + return; + } + + pSet= (TSocketSetImpl*)Set; + + /* correct max handle */ + if(pSocket->m_Socket > pSet->m_MaxHandle) + pSet->m_MaxHandle= pSocket->m_Socket; + FD_SET(pSocket->m_Socket, &pSet->m_Set); + +} + +/*****************************************************************************/ +/* osl_removeFromSocketSet */ +/*****************************************************************************/ +void SAL_CALL osl_removeFromSocketSet(oslSocketSet Set, oslSocket pSocket) +{ + TSocketSetImpl* pSet; + + OSL_ASSERT(Set); + OSL_ASSERT(pSocket); + + if ( Set == 0 || pSocket == 0) + { + return; + } + + pSet= (TSocketSetImpl*)Set; + + /* correct max handle */ + if(pSocket->m_Socket == pSet->m_MaxHandle) + { + /* not optimal, since the next used descriptor might be */ + /* much smaller than m_Socket-1, but it will do */ + pSet->m_MaxHandle--; + if(pSet->m_MaxHandle < 0) + { + pSet->m_MaxHandle= 0; /* avoid underflow */ + } + } + + FD_CLR(pSocket->m_Socket, &pSet->m_Set); +} + +/*****************************************************************************/ +/* osl_isInSocketSet */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isInSocketSet(oslSocketSet Set, oslSocket pSocket) +{ + TSocketSetImpl* pSet; + + OSL_ASSERT(Set); + OSL_ASSERT(pSocket); + if ( Set == 0 || pSocket == 0 ) + { + return sal_False; + } + + pSet= (TSocketSetImpl*)Set; + + return (FD_ISSET(pSocket->m_Socket, &pSet->m_Set) != 0); +} + +/*****************************************************************************/ +/* osl_demultiplexSocketEvents */ +/*****************************************************************************/ +sal_Int32 SAL_CALL osl_demultiplexSocketEvents(oslSocketSet IncomingSet, + oslSocketSet OutgoingSet, + oslSocketSet OutOfBandSet, + const TimeValue* pTimeout) +{ + int MaxHandle= 0; + struct timeval tv; + TSocketSetImpl* pInSet; + TSocketSetImpl* pOutSet; + TSocketSetImpl* pOOBSet; + + if (pTimeout) + { + /* non-blocking call */ + tv.tv_sec = pTimeout->Seconds; + tv.tv_usec = pTimeout->Nanosec / 1000L; + } + + /* map opaque data to impl-types */ + pInSet= (TSocketSetImpl*)IncomingSet; + pOutSet= (TSocketSetImpl*)OutgoingSet; + pOOBSet= (TSocketSetImpl*)OutOfBandSet; + + /* get max handle from all sets */ + if (pInSet) + MaxHandle= pInSet->m_MaxHandle; + + if (pOutSet && (pOutSet->m_MaxHandle > MaxHandle)) + MaxHandle= pOutSet->m_MaxHandle; + + if (pOOBSet && (pOOBSet->m_MaxHandle > MaxHandle)) + MaxHandle= pOOBSet->m_MaxHandle; + + return select(MaxHandle+1, + pInSet ? PTR_FD_SET(pInSet->m_Set) : 0, + pOutSet ? PTR_FD_SET(pOutSet->m_Set) : 0, + pOOBSet ? PTR_FD_SET(pOOBSet->m_Set) : 0, + pTimeout ? &tv : 0); +} + diff --git a/sal/osl/os2/sockimpl.h b/sal/osl/os2/sockimpl.h new file mode 100644 index 000000000000..3ce16e425fde --- /dev/null +++ b/sal/osl/os2/sockimpl.h @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sockimpl.h,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _OSL_SOCKETIMPL_H_ +#define _OSL_SOCKETIMPL_H_ + +#include <osl/pipe.h> +#include <osl/socket.h> +#include <osl/interlck.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* (*oslCloseCallback) (void*); + +struct oslSocketImpl { + int m_Socket; + int m_nLastError; + oslCloseCallback m_CloseCallback; + void* m_CallbackArg; + oslInterlockedCount m_nRefCount; +#if defined(LINUX) + sal_Bool m_bIsAccepting; + sal_Bool m_bIsInShutdown; +#endif +}; + +struct oslSocketAddrImpl +{ + sal_Int32 m_nRefCount; + struct sockaddr m_sockaddr; +}; + +/* +struct oslPipeImpl { + int m_Socket; + sal_Char m_Name[PATH_MAX + 1]; + oslInterlockedCount m_nRefCount; + sal_Bool m_bClosed; +#if defined(LINUX) + sal_Bool m_bIsAccepting; + sal_Bool m_bIsInShutdown; +#endif +}; +*/ + +oslSocket __osl_createSocketImpl(int Socket); +void __osl_destroySocketImpl(oslSocket pImpl); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sal/osl/os2/system.h b/sal/osl/os2/system.h new file mode 100644 index 000000000000..565dfe3ea9c6 --- /dev/null +++ b/sal/osl/os2/system.h @@ -0,0 +1,547 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: system.h,v $ + * $Revision: 1.5.60.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __OSL_SYSTEM_H__ +#define __OSL_SYSTEM_H__ + +#define PTHREAD_NONE + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> + +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <signal.h> +#include <utime.h> + +#include <pwd.h> + +#include <netdb.h> + +#include <sys/stat.h> +#include <sys/wait.h> + +#include <sys/types.h> + +/* OS/2 API header */ +#define INCL_WINPROGRAMLIST +#define INCL_WINSHELLDATA +#define INCL_BASE +#define INCL_DOSSIGNALS +#define INCL_DOSSEMAPHORES +#define INCL_DOSMODULEMGR +#define INCL_DOSERRORS +#define INCL_DOSSESMGR +#define INCL_DOSPROCESS +#define INCL_DOSNMPIPES +#define INCL_DOSMISC +#include <os2.h> + +typedef ULONG HANDLE; +#define _MAX_ENV 2048 +#define _MAX_CMD 2048 + +#ifdef __cplusplus +extern "C" +#endif +int debug_printf(const char *f, ...); + +/* Make sockets of type AF_UNIX use underlying FS rights */ +#ifdef SOLARIS +# define _XOPEN_SOURCE 500 +# include <sys/socket.h> +# undef _XOPEN_SOURCE +#else +# include <sys/socket.h> +#endif + +#include <netinet/in.h> +#include <arpa/inet.h> + +#define max(a, b) ((a) < (b) ? (b) : (a)) +#define min(a, b) ((a) > (b) ? (b) : (a)) +#ifndef abs +#define abs(x) ((x) >= 0 ? (x) : -(x)) +#endif + +#ifdef SYSV +# include <sys/utsname.h> +#endif + +#ifdef LINUX +# ifndef __USE_GNU +# define __USE_GNU +# endif + +#if GLIBC >= 2 +# include <shadow.h> +# if ! (defined(SPARC) || defined(X86_64)) +# include <asm/sigcontext.h> +# endif +# include <pthread.h> +# include <sys/file.h> +# include <sys/ioctl.h> +# include <sys/uio.h> +# include <sys/un.h> +# include <netinet/tcp.h> +# include <dlfcn.h> +# include <endian.h> +# include <sys/time.h> +# include <semaphore.h> +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define _LITTLE_ENDIAN +# elif __BYTE_ORDER == __BIG_ENDIAN +# define _BIG_ENDIAN +# elif __BYTE_ORDER == __PDP_ENDIAN +# define _PDP_ENDIAN +# endif +# define PTR_SIZE_T(s) ((size_t *)&(s)) +# define IORESOURCE_TRANSFER_BSD +# define IOCHANNEL_TRANSFER_BSD_RENO +# define pthread_testcancel() +# define NO_PTHREAD_PRIORITY +# define PTHREAD_SIGACTION pthread_sigaction +#else +# include <shadow.h> +# include <asm/sigcontext.h> +# include <pthread.h> +# include <sys/file.h> +# include <sys/ioctl.h> +# include <linux/net.h> +# include <sys/un.h> +# include <netinet/tcp.h> +# include <linux/elfcore.h> +# include <dlfcn.h> +# include <endian.h> +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define _LITTLE_ENDIAN +# elif __BYTE_ORDER == __BIG_ENDIAN +# define _BIG_ENDIAN +# elif __BYTE_ORDER == __PDP_ENDIAN +# define _PDP_ENDIAN +# endif +# define IORESOURCE_TRANSFER_BSD +# define IOCHANNEL_TRANSFER_BSD_RENO +# define pthread_testcancel() +# define NO_PTHREAD_RTL +# define NO_PTHREAD_PRIORITY +# define PTHREAD_SIGACTION pthread_sigaction +#endif +#endif + +#ifdef NETBSD +# define ETIME ETIMEDOUT +# define _POSIX_THREAD_SYSCALL_SOFT 1 +# include <pthread.h> +# include <netdb.h> +# include <sys/sem.h> +# include <sys/exec.h> +# include <sys/filio.h> +# include <sys/ioctl.h> +# include <sys/time.h> +# include <sys/un.h> +# include <netinet/tcp.h> +# include <dlfcn.h> +# include <machine/endian.h> +# if BYTE_ORDER == LITTLE_ENDIAN +# define _LITTLE_ENDIAN_OO +# elif BYTE_ORDER == BIG_ENDIAN +# define _BIG_ENDIAN_OO +# elif BYTE_ORDER == PDP_ENDIAN +# define _PDP_ENDIAN_OO +# endif +# define PTR_SIZE_T(s) ((size_t *)&(s)) +# define IORESOURCE_TRANSFER_BSD +# define IOCHANNEL_TRANSFER_BSD_RENO +# define pthread_testcancel() +# define NO_PTHREAD_PRIORITY +# define NO_PTHREAD_SEMAPHORES +# define NO_PTHREAD_RTL +# define PTHREAD_SIGACTION pthread_sigaction +#endif + +#ifdef FREEBSD +# define ETIME ETIMEDOUT +# include <pthread.h> +# include <sys/sem.h> +# include <semaphore.h> +# include <dlfcn.h> +# include <sys/filio.h> +# include <sys/ioctl.h> +# include <sys/param.h> +# include <sys/time.h> +# include <sys/uio.h> +# include <sys/exec.h> +# include <vm/vm.h> +# include <vm/vm_param.h> +# include <vm/pmap.h> +# include <vm/swap_pager.h> +# include <sys/un.h> +# include <netinet/tcp.h> +# define IORESOURCE_TRANSFER_BSD +# include <machine/endian.h> +#if __FreeBSD_version < 500000 +# if BYTE_ORDER == LITTLE_ENDIAN +# define _LITTLE_ENDIAN +# elif BYTE_ORDER == BIG_ENDIAN +# define _BIG_ENDIAN +# elif BYTE_ORDER == PDP_ENDIAN +# define _PDP_ENDIAN +# endif +#endif +# define NO_PTHREAD_RTL +#endif + +#ifdef SCO +# define AF_IPX -1 +# include <strings.h> +# include <pthread.h> +# include <shadow.h> +# include <netdb.h> +# include <sys/un.h> +# include <sys/netinet/tcp.h> +# include <sys/types.h> +# include <sys/byteorder.h> +# include <dlfcn.h> +# if BYTE_ORDER == LITTLE_ENDIAN +# define _LITTLE_ENDIAN +# elif BYTE_ORDER == BIG_ENDIAN +# define _BIG_ENDIAN +# elif BYTE_ORDER == PDP_ENDIAN +# define _PDP_ENDIAN +# endif +# define sched_yield() pthread_yield() +# define pthread_testcancel() +# define NO_PTHREAD_RTL +# define NO_PTHREAD_PRIORITY +extern int pthread_cancel(pthread_t); +extern unsigned int nanosleep(unsigned int); +# define SLEEP_TIMESPEC(timespec) (timespec .tv_sec > 0) ? sleep(timespec .tv_sec), nanosleep(timespec .tv_nsec) : nanosleep(timespec .tv_nsec) +# define PATH_MAX _POSIX_PATH_MAX +# define S_ISSOCK S_ISFIFO +# define PTHREAD_SIGACTION pthread_sigaction +# define STAT_PARENT stat +#endif + +#ifdef AIX +# define AF_IPX -1 +# include <strings.h> +# include <pthread.h> +# include <sys/time.h> +# include <sys/un.h> +# include <netinet/tcp.h> +# include <sys/machine.h> +# if BYTE_ORDER == LITTLE_ENDIAN +# define _LITTLE_ENDIAN +# elif BYTE_ORDER == BIG_ENDIAN +# define _BIG_ENDIAN +# elif BYTE_ORDER == PDP_ENDIAN +# define _PDP_ENDIAN +# endif +# define sched_yield() pthread_yield() +# define SLEEP_TIMESPEC(timespec) nsleep(×pec, 0) +# define LIBPATH "LIBPATH" +# define PTR_SIZE_T(s) ((size_t *)&(s)) +# define NO_PTHREAD_SEMAPHORES +# define NO_DL_FUNCTIONS +#endif + +#ifdef HPUX +# define AF_IPX -1 +# undef howmany +# undef MAXINT +# include <pthread.h> +# include <sys/un.h> +# include <sys/sched.h> +# include <sys/xti.h> +# include <sys/pstat.h> +# include <shadow.h> +# include <crypt.h> +# include <machine/param.h> +# define LIBPATH "SHLIB_PATH" +# define PTR_SIZE_T(s) ((int *)&(s)) +# define PTR_FD_SET(s) ((int *)&(s)) +# define PTHREAD_VALUE(t) ((t).field2) +# define PTHREAD_NONE_INIT { 0, -1 } +# define PTHREAD_ATTR_DEFAULT pthread_attr_default +# define PTHREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default +# define PTHREAD_CONDATTR_DEFAULT pthread_condattr_default +# define pthread_detach(t) pthread_detach(&(t)) +# define NO_PTHREAD_PRIORITY +# define NO_PTHREAD_SEMAPHORES +# define NO_DL_FUNCTIONS +# undef sigaction +# define PTHREAD_SIGACTION cma_sigaction +#endif + +#ifdef IRIX +# define AF_IPX -1 +# include <pthread.h> +# include <semaphore.h> +# include <sched.h> +# include <sys/socket.h> +# include <sys/un.h> +# include <sys/stropts.h> +# include <netinet/tcp.h> +# include <procfs/procfs.h> +# include <sys/endian.h> +# if BYTE_ORDER == LITTLE_ENDIAN +# undef _BIG_ENDIAN +# undef _PDP_ENDIAN +# elif BYTE_ORDER == BIG_ENDIAN +# undef _LITTLE_ENDIAN +# undef _PDP_ENDIAN +# elif BYTE_ORDER == PDP_ENDIAN +# undef _LITTLE_ENDIAN +# undef _BIG_ENDIAN +# endif +# define SA_FAMILY_DECL \ + union { struct { short sa_family2; } sa_generic; } sa_union +# define PTR_SIZE_T(s) ((int *)&(s)) +# define NO_PTHREAD_PRIORITY +# include <dlfcn.h> +# define IOCHANNEL_TRANSFER_BSD +extern char *strdup(const char *); +#endif + +#ifdef SOLARIS +# include <shadow.h> +# include <sys/procfs.h> +# include <sys/un.h> +# include <stropts.h> +# include <pthread.h> +# include <semaphore.h> +# include <netinet/tcp.h> +# include <sys/filio.h> +# include <dlfcn.h> +# include <sys/isa_defs.h> +# define IORESOURCE_TRANSFER_SYSV +# define IOCHANNEL_TRANSFER_BSD +# define LIBPATH "LD_LIBRARY_PATH" +# define PTR_SIZE_T(s) ((int *)&(s)) +#endif + +#ifdef MACOSX +# define ETIME ETIMEDOUT +# include <pthread.h> +# include <sys/file.h> +# include <sys/ioctl.h> +# include <sys/uio.h> +# include <sys/un.h> +# include <netinet/tcp.h> +# include <machine/endian.h> +# include <sys/time.h> +# include <sys/semaphore.h> +/* fixme are premac and postmac still needed here? */ +# include <premac.h> +# include <mach-o/dyld.h> +# include <postmac.h> +# if BYTE_ORDER == LITTLE_ENDIAN +# define _LITTLE_ENDIAN +# elif BYTE_ORDER == BIG_ENDIAN +# define _BIG_ENDIAN +# elif BYTE_ORDER == PDP_ENDIAN +# define _PDP_ENDIAN +# endif +# define IOCHANNEL_TRANSFER_BSD_RENO +# define NO_PTHREAD_RTL +/* for NSGetArgc/Argv/Environ */ +# include <crt_externs.h> +char *macxp_tempnam( const char *tmpdir, const char *prefix ); +#endif + +#ifdef OS2 +# include <netinet/tcp.h> +#endif + +#if !defined(_WIN32) && !defined(_WIN16) && !defined(OS2) && \ + !defined(LINUX) && !defined(NETBSD) && !defined(FREEBSD) && !defined(SCO) && \ + !defined(AIX) && !defined(HPUX) && \ + !defined(SOLARIS) && !defined(IRIX) && !defined(MAC) && \ + !defined(MACOSX) +# error "Target plattform not specified !" +#endif + +#if defined(NETBSD) +#if defined _LITTLE_ENDIAN_OO +# define _OSL_BIGENDIAN +#elif defined _BIG_ENDIAN_OO +# define _OSL_LITENDIAN +#else +# error undetermined endianess +#endif +#else +#if defined _LITTLE_ENDIAN +# define _OSL_BIGENDIAN +#elif defined _BIG_ENDIAN +# define _OSL_LITENDIAN +#else +# error undetermined endianess +#endif +#endif + +#ifndef PTR_SIZE_T +# define PTR_SIZE_T(s) (&(s)) +#endif + +#ifndef PTR_FD_SET +# define PTR_FD_SET(s) (&(s)) +#endif + +#ifndef NORMALIZE_TIMESPEC +# define NORMALIZE_TIMESPEC(timespec) \ + timespec . tv_sec += timespec . tv_nsec / 1000000000; \ + timespec . tv_nsec %= 1000000000; +#endif + +#ifndef SET_TIMESPEC +# define SET_TIMESPEC(timespec, sec, nsec) \ + timespec . tv_sec = (sec); \ + timespec . tv_nsec = (nsec); \ + NORMALIZE_TIMESPEC(timespec); +#endif + +#ifndef SLEEP_TIMESPEC +# define SLEEP_TIMESPEC(timespec) nanosleep(×pec, 0) +#endif + +#ifndef INIT_GROUPS +# define INIT_GROUPS(name, gid) ((setgid((gid)) == 0) && (initgroups((name), (gid)) == 0)) +#endif + +#ifndef PTHREAD_VALUE +# define PTHREAD_VALUE(t) (t) +#endif +#ifndef PTHREAD_NONE +extern pthread_t _pthread_none_; +# define PTHREAD_NONE _pthread_none_ +# ifndef PTHREAD_NONE_INIT +# define PTHREAD_NONE_INIT ((pthread_t)-1) +# endif +#endif + +#ifndef PTHREAD_ATTR_DEFAULT +# define PTHREAD_ATTR_DEFAULT NULL +#endif +#ifndef PTHREAD_MUTEXATTR_DEFAULT +# define PTHREAD_MUTEXATTR_DEFAULT NULL +#endif +#ifndef PTHREAD_CONDATTR_DEFAULT +# define PTHREAD_CONDATTR_DEFAULT NULL +#endif + +#ifndef PTHREAD_SIGACTION +# define PTHREAD_SIGACTION sigaction +#endif + +#ifndef STAT_PARENT +# define STAT_PARENT lstat +#endif + +/* socket options which might not be defined on all unx flavors */ +#ifndef SO_ACCEPTCONN +# define SO_ACCEPTCONN 0 +#endif +#ifndef SO_SNDLOWAT +# define SO_SNDLOWAT 0 +#endif +#ifndef SO_RCVLOWAT +# define SO_RCVLOWAT 0 +#endif +#ifndef SO_SNDTIMEO +# define SO_SNDTIMEO 0 +#endif +#ifndef SO_RCVTIMEO +# define SO_RCVTIMEO 0 +#endif +#ifndef SO_USELOOPBACK +# define SO_USELOOPBACK 0 +#endif +#ifndef MSG_MAXIOVLEN +# define MSG_MAXIOVLEN 0 +#endif + +/* BEGIN HACK */ +/* dummy define and declarations for IPX should be replaced by */ +/* original ipx headers when these are available for this platform */ + +#ifndef SA_FAMILY_DECL +# define SA_FAMILY_DECL short sa_family +#endif + +typedef struct sockaddr_ipx { + SA_FAMILY_DECL; + char sa_netnum[4]; + char sa_nodenum[6]; + unsigned short sa_socket; +} SOCKADDR_IPX; + +#define NSPROTO_IPX 1000 +#define NSPROTO_SPX 1256 +#define NSPROTO_SPXII 1257 + +/* END HACK */ + +#ifdef NO_PTHREAD_SEMAPHORES + +typedef struct +{ + pthread_mutex_t mutex; + pthread_cond_t increased; + int value; +} sem_t; +extern int sem_init(sem_t* sem, int pshared, unsigned int value); +extern int sem_destroy(sem_t* sem); +extern int sem_wait(sem_t* sem); +extern int sem_trywait(sem_t* sem); +extern int sem_post(sem_t* sem); + +#endif + +#ifdef NO_PTHREAD_RTL +#if !defined FREEBSD || (__FreeBSD_version < 500112) +struct passwd *getpwent_r(struct passwd *pwd, char *buffer, int buflen); +extern struct spwd *getspnam_r(const char *name, struct spwd *result, + char *buffer, int buflen); + +struct tm *localtime_r(const time_t *timep, struct tm *buffer); +struct tm *gmtime_r(const time_t *timep, struct tm *buffer); +#endif /* !defined FREEBSD || (__FreeBSD_version < 500112) */ +struct hostent *gethostbyname_r(const char *name, struct hostent *result, + char *buffer, int buflen, int *h_errnop); +#endif + +#endif /* __OSL_SYSTEM_H__ */ + diff --git a/sal/osl/os2/tempfile.c b/sal/osl/os2/tempfile.c new file mode 100644 index 000000000000..f6f80f79e69a --- /dev/null +++ b/sal/osl/os2/tempfile.c @@ -0,0 +1,362 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tempfile.c,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/*****************************************************************/ +/* Includes */ +/*****************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "system.h" +#include <osl/file.h> +#include <osl/thread.h> +#include <rtl/ustrbuf.h> +#include <osl/diagnose.h> + +#ifndef _FILE_URL_H_ +#include "file_url.h" +#endif + +/*****************************************************************/ +/* osl_getTempFirURL */ +/*****************************************************************/ + +oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir ) +{ + const char *pValue = getenv( "TEMP" ); + + if ( !pValue ) + { + pValue = getenv( "TMP" ); +#if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD) || defined (MACOSX) + if ( !pValue ) + pValue = P_tmpdir; +#endif + } + + if ( pValue ) + { + oslFileError error; + rtl_uString *ustrTempPath = NULL; + + rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(ustrTempPath != NULL); + error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir ); + rtl_uString_release( ustrTempPath ); + + return error; + } + else + return osl_File_E_NOENT; +} + +/****************************************************************** + * Generates a random unique file name. We're using the scheme + * from the standard c-lib function mkstemp to generate a more + * or less random unique file name + * + * @param rand_name + * receives the random name + ******************************************************************/ + +static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; +static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1; + +#define RAND_NAME_LENGTH 6 + +static void osl_gen_random_name_impl_(rtl_uString** rand_name) +{ + static uint64_t value; + + char buffer[RAND_NAME_LENGTH]; + struct timeval tv; + uint64_t v; + int i; + + gettimeofday(&tv, NULL); + + value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid(); + + v = value; + + for (i = 0; i < RAND_NAME_LENGTH; i++) + { + buffer[i] = LETTERS[v % COUNT_OF_LETTERS]; + v /= COUNT_OF_LETTERS; + } + + rtl_string2UString( + rand_name, + buffer, + RAND_NAME_LENGTH, + RTL_TEXTENCODING_ASCII_US, + OSTRING_TO_OUSTRING_CVTFLAGS); + OSL_ASSERT(*rand_name != NULL); +} + +/***************************************************************** + * Helper function + * Either use the directory provided or the result of + * osl_getTempDirUrl and return it as system path and file url + ****************************************************************/ + +static oslFileError osl_setup_base_directory_impl_( + rtl_uString* pustrDirectoryURL, + rtl_uString** ppustr_base_dir) +{ + rtl_uString* dir_url = 0; + rtl_uString* dir = 0; + oslFileError error = osl_File_E_None; + + if (pustrDirectoryURL) + rtl_uString_assign(&dir_url, pustrDirectoryURL); + else + error = osl_getTempDirURL(&dir_url); + + if (osl_File_E_None == error) + { + error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE); + rtl_uString_release(dir_url); + } + + if (osl_File_E_None == error) + { + rtl_uString_assign(ppustr_base_dir, dir); + rtl_uString_release(dir); + } + + return error; +} + +/***************************************************************** + * osl_setup_createTempFile_impl + * validate input parameter, setup variables + ****************************************************************/ + + static oslFileError osl_setup_createTempFile_impl_( + rtl_uString* pustrDirectoryURL, + oslFileHandle* pHandle, + rtl_uString** ppustrTempFileURL, + rtl_uString** ppustr_base_dir, + sal_Bool* b_delete_on_close) + { + oslFileError osl_error; + + OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!"); + + if ((0 == pHandle) && (0 == ppustrTempFileURL)) + { + osl_error = osl_File_E_INVAL; + } + else + { + osl_error = osl_setup_base_directory_impl_( + pustrDirectoryURL, ppustr_base_dir); + + *b_delete_on_close = (0 == ppustrTempFileURL); + } + + return osl_error; + } + +/***************************************************************** + * Create a unique file in the specified directory and return + * it's name + ****************************************************************/ + +static oslFileError osl_create_temp_file_impl_( + const rtl_uString* pustr_base_directory, + oslFileHandle* file_handle, + rtl_uString** ppustr_temp_file_name) +{ + rtl_uString* rand_name = 0; + sal_uInt32 len_base_dir = 0; + rtl_uString* tmp_file_path = 0; + rtl_uString* tmp_file_url = 0; + sal_Int32 capacity = 0; + oslFileError osl_error = osl_File_E_None; + sal_Int32 offset_file_name; + const sal_Unicode* puchr; + + OSL_PRECOND(pustr_base_directory, "Invalid Parameter"); + OSL_PRECOND(file_handle, "Invalid Parameter"); + OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter"); + + len_base_dir = rtl_uString_getLength(pustr_base_directory); + + rtl_uStringbuffer_newFromStr_WithLength( + &tmp_file_path, + rtl_uString_getStr((rtl_uString*)pustr_base_directory), + len_base_dir); + + rtl_uStringbuffer_ensureCapacity( + &tmp_file_path, + &capacity, + (len_base_dir + 1 + RAND_NAME_LENGTH)); + + offset_file_name = len_base_dir; + + puchr = rtl_uString_getStr(tmp_file_path); + + /* ensure that the last character is a '\' */ + + if ((sal_Unicode)'\\' != puchr[len_base_dir - 1]) + { + rtl_uStringbuffer_insert_ascii( + &tmp_file_path, + &capacity, + len_base_dir, + "\\", + 1); + + offset_file_name++; + } + + while(1) /* try until success */ + { + osl_gen_random_name_impl_(&rand_name); + + rtl_uStringbuffer_insert( + &tmp_file_path, + &capacity, + offset_file_name, + rtl_uString_getStr(rand_name), + rtl_uString_getLength(rand_name)); + + osl_error = osl_getFileURLFromSystemPath( + tmp_file_path, &tmp_file_url); + + if (osl_File_E_None == osl_error) + { + /* RW permission for the user only! */ + mode_t old_mode = umask(077); + + osl_error = osl_openFile( + tmp_file_url, + file_handle, + osl_File_OpenFlag_Read | + osl_File_OpenFlag_Write | + osl_File_OpenFlag_Create); + + umask(old_mode); + } + + /* in case of error osl_File_E_EXIST we simply try again else we give up */ + + if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST)) + { + if (rand_name) + rtl_uString_release(rand_name); + + if (tmp_file_url) + rtl_uString_release(tmp_file_url); + + break; + } + } /* while(1) */ + + if (osl_File_E_None == osl_error) + rtl_uString_assign(ppustr_temp_file_name, tmp_file_path); + + if (tmp_file_path) + rtl_uString_release(tmp_file_path); + + return osl_error; +} + +/***************************************************************** + * osl_createTempFile + *****************************************************************/ + +oslFileError SAL_CALL osl_createTempFile( + rtl_uString* pustrDirectoryURL, + oslFileHandle* pHandle, + rtl_uString** ppustrTempFileURL) +{ + rtl_uString* base_directory = 0; + rtl_uString* temp_file_name = 0; + oslFileHandle temp_file_handle; + sal_Bool b_delete_on_close; + oslFileError osl_error; + + osl_error = osl_setup_createTempFile_impl_( + pustrDirectoryURL, + pHandle, + ppustrTempFileURL, + &base_directory, + &b_delete_on_close); + + if (osl_File_E_None != osl_error) + return osl_error; + + osl_error = osl_create_temp_file_impl_( + base_directory, &temp_file_handle, &temp_file_name); + + if (osl_File_E_None == osl_error) + { + rtl_uString* temp_file_url = 0; + + /* assuming this works */ + osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url); + + if (b_delete_on_close) + { + osl_error = osl_removeFile(temp_file_url); + + if (osl_File_E_None == osl_error) + *pHandle = temp_file_handle; + else + osl_closeFile(temp_file_handle); + } + else + { + if (pHandle) + *pHandle = temp_file_handle; + else + osl_closeFile(temp_file_handle); + + rtl_uString_assign(ppustrTempFileURL, temp_file_url); + } + + if (temp_file_url) + rtl_uString_release(temp_file_url); + + if (temp_file_name) + rtl_uString_release(temp_file_name); + } + + if (base_directory) + rtl_uString_release(base_directory); + + return osl_error; +} diff --git a/sal/osl/os2/thread.c b/sal/osl/os2/thread.c new file mode 100644 index 000000000000..d84c09326d9b --- /dev/null +++ b/sal/osl/os2/thread.c @@ -0,0 +1,775 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: thread.c,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "system.h" + +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <osl/time.h> +#include <rtl/alloc.h> +#include <rtl/tencinfo.h> + +/* + Thread-data structure hidden behind oslThread: +*/ +typedef struct _osl_TThreadImpl +{ + + TID m_ThreadId; /* identifier for this thread */ + sal_Int32 m_Flags; + HEV m_hEvent; + sal_uInt32 m_Timeout; + oslWorkerFunction m_WorkerFunction; + void* m_pData; + sal_Bool m_StartSuspended; + HAB m_hab; + HMQ m_hmq; + +} osl_TThreadImpl; + +#define THREADIMPL_FLAGS_TERMINATE 0x0001 +#define THREADIMPL_FLAGS_SLEEP 0x0002 + + +// static mutex to control access to private members of oslMutexImpl +static HMTX MutexLock = NULL; + +/*****************************************************************************/ + +HAB osl_getPMinternal_HAB(oslThread hThread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)hThread; + + if(pThreadImpl == NULL) /* valid ptr? */ + { + return NULL; + } + else + { + return pThreadImpl->m_hab; + } +} + +HMQ osl_getPMinternal_HMQ(oslThread hThread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)hThread; + + if(pThreadImpl == NULL) /* valid ptr? */ + { + return NULL; + } + else + { + return pThreadImpl->m_hmq; + } +} + + +/*****************************************************************************/ +/* oslWorkerWrapperFunction */ +/*****************************************************************************/ +static void oslWorkerWrapperFunction(void* pData) +{ + BOOL rc; + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)pData; + +#if OSL_DEBUG_LEVEL>0 +printf("oslWorkerWrapperFunction pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl, pThreadImpl->m_ThreadId); +#endif + /* Inizialize PM for this thread */ + pThreadImpl->m_hab = WinInitialize( 0 ); +#if OSL_DEBUG_LEVEL>0 +printf("pThreadImpl->m_ThreadId %d, pThreadImpl->m_hab %x\n", pThreadImpl->m_ThreadId,pThreadImpl->m_hab); +#endif + pThreadImpl->m_hmq = WinCreateMsgQueue( pThreadImpl->m_hab, 0 ); +#if OSL_DEBUG_LEVEL>0 +printf("pThreadImpl->m_ThreadId %d, pThreadImpl->m_hmq %x\n", pThreadImpl->m_ThreadId,pThreadImpl->m_hmq); +#endif + + /* call worker-function with data */ + pThreadImpl->m_WorkerFunction( pThreadImpl->m_pData ); + + /* Free all PM-resources for this thread */ +#if OSL_DEBUG_LEVEL>0 +printf("pThreadImpl->m_ThreadId %d, about to destroy queue\n", pThreadImpl->m_ThreadId); +#endif + rc = WinDestroyMsgQueue( pThreadImpl->m_hmq ); +#if OSL_DEBUG_LEVEL>0 +printf("pThreadImpl->m_ThreadId %d, WinDestroyMsgQueue rc=%d (should be 1)\n", pThreadImpl->m_ThreadId, rc); +printf("pThreadImpl->m_ThreadId %d, about to terminate hab\n", pThreadImpl->m_ThreadId); +#endif + rc = WinTerminate( pThreadImpl->m_hab ); +#if OSL_DEBUG_LEVEL>0 +printf("pThreadImpl->m_ThreadId %d, WinTerminate rc=%d (should be 1)\n", pThreadImpl->m_ThreadId, rc); +#endif +} + + +/*****************************************************************************/ +/* oslCreateThread */ +/*****************************************************************************/ +static oslThread oslCreateThread(oslWorkerFunction pWorker, + void* pThreadData, + sal_Bool nFlags) +{ + osl_TThreadImpl* pThreadImpl; + + /* alloc mem. for our internal data structure */ + pThreadImpl = (osl_TThreadImpl*)malloc(sizeof(osl_TThreadImpl)); + + OSL_ASSERT(pThreadImpl); + + pThreadImpl->m_WorkerFunction= pWorker; + pThreadImpl->m_pData= pThreadData; + + pThreadImpl->m_Flags = 0; + pThreadImpl->m_hEvent = 0; + pThreadImpl->m_Timeout = 0; + pThreadImpl->m_StartSuspended = nFlags; + pThreadImpl->m_hab = 0; + pThreadImpl->m_hmq = 0; + + if ( nFlags == sal_True ) + { + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + } + + pThreadImpl->m_ThreadId = (TID) _beginthread( oslWorkerWrapperFunction, /* worker-function */ + NULL, /* unused parameter */ + 1024*1024, /* max. Stacksize */ + pThreadImpl ); + if ( nFlags == sal_True ) + { + if( pThreadImpl->m_ThreadId != -1 ) + DosSuspendThread( pThreadImpl->m_ThreadId ); + DosReleaseMutexSem( MutexLock); + } +#if OSL_DEBUG_LEVEL>0 +printf("oslCreateThread pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl, pThreadImpl->m_ThreadId); +#endif + if(pThreadImpl->m_ThreadId == -1) + { + /* create failed */ + if (pThreadImpl->m_hEvent != 0) + DosCloseEventSem(pThreadImpl->m_hEvent); + + free(pThreadImpl); + return 0; + } + + pThreadImpl->m_hEvent= 0; + + return pThreadImpl; + +} + +/*****************************************************************************/ +/* osl_createThread */ +/*****************************************************************************/ +oslThread SAL_CALL osl_createThread(oslWorkerFunction pWorker, + void* pThreadData) +{ + return oslCreateThread(pWorker,pThreadData,sal_False); +} + +/*****************************************************************************/ +/* osl_createSuspendedThread */ +/*****************************************************************************/ +oslThread SAL_CALL osl_createSuspendedThread(oslWorkerFunction pWorker, + void* pThreadData) +{ + return oslCreateThread(pWorker,pThreadData,sal_True); +} + +/*****************************************************************************/ +/* osl_getThreadIdentifier */ +/*****************************************************************************/ +oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + if (pThreadImpl != NULL) + return ((oslThreadIdentifier)pThreadImpl->m_ThreadId); + else + { + PTIB pptib = NULL; + PPIB pppib = NULL; + + DosGetInfoBlocks( &pptib, &pppib ); + return ((oslThreadIdentifier) pptib->tib_ptib2->tib2_ultid ); + } +} + +/*****************************************************************************/ +/* osl_destroyThread */ +/*****************************************************************************/ +void SAL_CALL osl_destroyThread(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + if(Thread == 0) /* valid ptr? */ + { + /* thread already destroyed or not created */ + return; + } + + if(pThreadImpl->m_ThreadId != -1) /* valid handle ? */ + { + /* cancel thread */ + DosKillThread( pThreadImpl->m_ThreadId ); + } +} + +/*****************************************************************************/ +/* osl_freeThreadHandle */ +/*****************************************************************************/ +void SAL_CALL osl_freeThreadHandle(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + if(Thread == 0) /* valid ptr? */ + { + /* thread already destroyed or not created */ + return; + } + + if (pThreadImpl->m_hEvent != 0) + DosCloseEventSem(pThreadImpl->m_hEvent); + + /* free memory */ + free(Thread); +} + +/*****************************************************************************/ +/* osl_resumeThread */ +/*****************************************************************************/ +void SAL_CALL osl_resumeThread(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + OSL_ASSERT(pThreadImpl); /* valid ptr? */ + + DosResumeThread( pThreadImpl->m_ThreadId ); +} + +/*****************************************************************************/ +/* osl_suspendThread */ +/*****************************************************************************/ +void SAL_CALL osl_suspendThread(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + OSL_ASSERT(pThreadImpl); /* valid ptr? */ + + DosSuspendThread( pThreadImpl->m_ThreadId ); +} + +/*****************************************************************************/ +/* osl_setThreadPriority */ +/*****************************************************************************/ +void SAL_CALL osl_setThreadPriority(oslThread Thread, + oslThreadPriority Priority) +{ + ULONG nOs2PriorityClass; + ULONG nOs2PriorityDelta; + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + OSL_ASSERT(pThreadImpl); /* valid ptr? */ + + switch(Priority) { + + case osl_Thread_PriorityHighest: + + nOs2PriorityClass = PRTYC_REGULAR; + nOs2PriorityDelta = PRTYD_MAXIMUM; + break; + + case osl_Thread_PriorityAboveNormal: + + nOs2PriorityClass = PRTYC_REGULAR; + nOs2PriorityDelta = 16; + break; + + case osl_Thread_PriorityNormal: + + nOs2PriorityClass = PRTYC_REGULAR; + nOs2PriorityDelta = 0; + break; + + case osl_Thread_PriorityBelowNormal: + + nOs2PriorityClass = PRTYC_REGULAR; + nOs2PriorityDelta = -16; + break; + + case osl_Thread_PriorityLowest: + + nOs2PriorityClass = PRTYC_REGULAR; + nOs2PriorityDelta = PRTYD_MINIMUM; + break; + + case osl_Thread_PriorityUnknown: + OSL_ASSERT(FALSE); /* only fools try this...*/ + + /* let release-version behave friendly */ + return; + + default: + OSL_ASSERT(FALSE); /* enum expanded, but forgotten here...*/ + + /* let release-version behave friendly */ + return; + } + + DosSetPriority( PRTYS_THREAD, + nOs2PriorityClass, nOs2PriorityDelta, + pThreadImpl->m_ThreadId ); + +} + +/*****************************************************************************/ +/* osl_getThreadPriority */ +/*****************************************************************************/ + +#define BYTE1FROMULONG(ul) ((UCHAR) (ul)) +#define BYTE2FROMULONG(ul) ((UCHAR) ((ULONG) ul >> 8)) + +oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread) +{ + ULONG nOs2PriorityClass; + ULONG nOs2PriorityDelta; + + oslThreadPriority Priority; + + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + /* invalid arguments ?*/ + if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1) + { + return osl_Thread_PriorityUnknown; + } + + /* get current priorities */ + { + PTIB pptib = NULL; + PPIB pppib = NULL; + + DosGetInfoBlocks( &pptib, &pppib ); + nOs2PriorityClass = BYTE1FROMULONG( pptib->tib_ptib2->tib2_ulpri ); + nOs2PriorityDelta = BYTE2FROMULONG( pptib->tib_ptib2->tib2_ulpri ); + } + + /* map OS2 priority to enum */ + switch(nOs2PriorityClass) + { + case PRTYC_TIMECRITICAL: + Priority= osl_Thread_PriorityHighest; + break; + + case PRTYC_REGULAR: + + if( nOs2PriorityDelta == 0 ) + { + Priority= osl_Thread_PriorityNormal; + break; + } + + if( nOs2PriorityDelta < -16 ) + { + Priority= osl_Thread_PriorityLowest; + break; + } + + if( nOs2PriorityDelta < 0 ) + { + Priority= osl_Thread_PriorityBelowNormal; + break; + } + + if( nOs2PriorityDelta > 0 ) + { + Priority= osl_Thread_PriorityAboveNormal; + break; + } + + Priority= osl_Thread_PriorityHighest; + break; + + case PRTYC_IDLETIME: + Priority= osl_Thread_PriorityLowest; + break; + + default: + OSL_ASSERT(FALSE); /* OS/2 API changed, incorporate new prio-level! */ + + /* release-version behaves friendly */ + Priority= osl_Thread_PriorityUnknown; + } + + return Priority; +} + +/*****************************************************************************/ +/* osl_isThreadRunning */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + APIRET rc; + + /* invalid arguments ?*/ + if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1) + { + return sal_False; + } + + if( osl_getThreadIdentifier( 0 ) == osl_getThreadIdentifier( Thread ) ) + return sal_True; + + rc = DosWaitThread( &pThreadImpl->m_ThreadId, DCWW_NOWAIT ); + + return( rc != ERROR_INVALID_THREADID ); +} + +/*****************************************************************************/ +/* osl_joinWithThread */ +/*****************************************************************************/ +void SAL_CALL osl_joinWithThread(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + /* invalid arguments?*/ + if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1) + { + /* assume thread is not running */ + return; + } + + DosWaitThread( &pThreadImpl->m_ThreadId, DCWW_WAIT ); +} + +/*****************************************************************************/ +/* osl_waitThread */ +/*****************************************************************************/ +void SAL_CALL osl_waitThread(const TimeValue* pDelay) +{ + int millisecs; + + OSL_ASSERT(pDelay); + + millisecs = pDelay->Seconds * 1000 + pDelay->Nanosec / 1000000; + + DosSleep(millisecs); +} + +/*****************************************************************************/ +/* osl_terminateThread */ +/*****************************************************************************/ +void SAL_CALL osl_terminateThread(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + /* invalid arguments?*/ + if (pThreadImpl==0 || pThreadImpl->m_ThreadId==-1) + { + /* assume thread is not running */ + return; + } + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + pThreadImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE; + DosReleaseMutexSem( MutexLock); +} + + +/*****************************************************************************/ +/* osl_scheduleThread */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread) +{ + osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread; + + osl_yieldThread(); + + /* invalid arguments?*/ + if (pThreadImpl==0 || pThreadImpl->m_ThreadId==-1) + { + /* assume thread is not running */ + return sal_False; + } + + if (pThreadImpl->m_Flags & THREADIMPL_FLAGS_SLEEP) + { + OSL_ASSERT (pThreadImpl->m_hEvent != 0); + + DosWaitEventSem(pThreadImpl->m_hEvent, pThreadImpl->m_Timeout); + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + pThreadImpl->m_Timeout = 0; + + pThreadImpl->m_Flags &= ~THREADIMPL_FLAGS_SLEEP; + + DosReleaseMutexSem( MutexLock); + } + + return ((pThreadImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) == 0); +} + +/*****************************************************************************/ +/* osl_yieldThread */ +/*****************************************************************************/ +void SAL_CALL osl_yieldThread() +{ + DosSleep(0); +} + +typedef struct _TLS +{ + PULONG pulPtr; + oslThreadKeyCallbackFunction pfnCallback; + struct _TLS *pNext, *pPrev; +} TLS, *PTLS; + +static PTLS g_pThreadKeyList = NULL; + +static void AddKeyToList( PTLS pTls ) +{ + if ( pTls ) + { + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + + pTls->pNext = g_pThreadKeyList; + pTls->pPrev = 0; + + if ( g_pThreadKeyList ) + g_pThreadKeyList->pPrev = pTls; + + g_pThreadKeyList = pTls; + + DosReleaseMutexSem( MutexLock); + } +} + +static void RemoveKeyFromList( PTLS pTls ) +{ + if ( pTls ) + { + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + if ( pTls->pPrev ) + pTls->pPrev->pNext = pTls->pNext; + else + { + OSL_ASSERT( pTls == g_pThreadKeyList ); + g_pThreadKeyList = pTls->pNext; + } + + if ( pTls->pNext ) + pTls->pNext->pPrev = pTls->pPrev; + DosReleaseMutexSem( MutexLock); + } +} + +void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void) +{ + PTLS pTls; + + DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT ); + pTls = g_pThreadKeyList; + while ( pTls ) + { + if ( pTls->pfnCallback ) + { + void *pValue = (void*)*pTls->pulPtr; + + if ( pValue ) + pTls->pfnCallback( pValue ); + } + + pTls = pTls->pNext; + } + DosReleaseMutexSem( MutexLock); +} + +/*****************************************************************************/ +/* osl_createThreadKey */ +/*****************************************************************************/ +oslThreadKey SAL_CALL osl_createThreadKey(oslThreadKeyCallbackFunction pCallback) +{ + PTLS pTls = (PTLS)rtl_allocateMemory( sizeof(TLS) ); + + if ( pTls ) + { + pTls->pfnCallback = pCallback; + if (DosAllocThreadLocalMemory(1, &pTls->pulPtr) != NO_ERROR) + { + rtl_freeMemory( pTls ); + pTls = 0; + } + else + { + *pTls->pulPtr = 0; + AddKeyToList( pTls ); + } + } + + return ((oslThreadKey)pTls); +} + +/*****************************************************************************/ +/* osl_destroyThreadKey */ +/*****************************************************************************/ +void SAL_CALL osl_destroyThreadKey(oslThreadKey Key) +{ + if (Key != 0) + { + PTLS pTls = (PTLS)Key; + + RemoveKeyFromList( pTls ); + DosFreeThreadLocalMemory(pTls->pulPtr); + rtl_freeMemory( pTls ); + } +} + +/*****************************************************************************/ +/* osl_getThreadKeyData */ +/*****************************************************************************/ +void * SAL_CALL osl_getThreadKeyData(oslThreadKey Key) +{ + if (Key != 0) + { + PTLS pTls = (PTLS)Key; + + return ((void *) *pTls->pulPtr); + } + + return (NULL); +} + +/*****************************************************************************/ +/* osl_setThreadKeyData */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData) +{ + if (Key != 0) + { + PTLS pTls = (PTLS)Key; + void* pOldData = NULL; + BOOL fSuccess = TRUE; //YD cannot fail + + if ( pTls->pfnCallback ) + pOldData = (void*)*pTls->pulPtr; + + *pTls->pulPtr = (ULONG)pData; + + if ( fSuccess && pTls->pfnCallback && pOldData ) + pTls->pfnCallback( pOldData ); + + return (sal_Bool)(fSuccess != FALSE); + } + + return (sal_False); +} + + + +/*****************************************************************************/ +/* osl_getThreadTextEncoding */ +/*****************************************************************************/ + +ULONG g_dwTLSTextEncodingIndex = (ULONG)-1; + +sal_uInt32 SAL_CALL _GetACP( void) +{ + APIRET rc; + ULONG aulCpList[8] = {0}; + ULONG ulListSize; + + rc = DosQueryCp( sizeof( aulCpList), aulCpList, &ulListSize); + if (rc) + return 437; // in case of error, return codepage EN_US + // current codepage is first of list, others are the prepared codepages. + return aulCpList[0]; +} + +rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding(void) +{ + rtl_TextEncoding _encoding; + + if ( (ULONG)-1 == g_dwTLSTextEncodingIndex ) { + rtl_TextEncoding defaultEncoding; + const char * pszEncoding; + + /* create thread specific data key */ + g_dwTLSTextEncodingIndex = osl_createThreadKey( NULL); + + /* determine default text encoding */ + pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING"); + if (pszEncoding) + defaultEncoding = atoi(pszEncoding); + else + defaultEncoding = rtl_getTextEncodingFromWindowsCodePage( _GetACP()); + + //OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW); + //g_thread.m_textencoding.m_default = defaultEncoding; + osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)defaultEncoding); + } + + _encoding = (rtl_TextEncoding)osl_getThreadKeyData( g_dwTLSTextEncodingIndex ); + if (0 == _encoding) { + const char * pszEncoding; + /* determine default text encoding */ + pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING"); + if (pszEncoding) + _encoding = atoi(pszEncoding); + else + _encoding = rtl_getTextEncodingFromWindowsCodePage( _GetACP()); + /* save for future reference */ + osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)_encoding); + } + + return _encoding; +} + +/*****************************************************************************/ +/* osl_getThreadTextEncoding */ +/*****************************************************************************/ +rtl_TextEncoding SAL_CALL osl_setThreadTextEncoding( rtl_TextEncoding Encoding ) +{ + rtl_TextEncoding oldEncoding = osl_getThreadTextEncoding(); + + osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)Encoding); + + return oldEncoding; +} + + + diff --git a/sal/osl/os2/time.c b/sal/osl/os2/time.c new file mode 100644 index 000000000000..5c0833ce23e8 --- /dev/null +++ b/sal/osl/os2/time.c @@ -0,0 +1,272 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: time.c,v $ + * $Revision: 1.5 $ + * + * 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( ¤tTime, NULL ); + + nSeconds = (sal_uInt32)( currentTime.tv_sec - startTime.tv_sec ); + + return ( nSeconds * 1000 ) + (long) (( currentTime.tv_usec - startTime.tv_usec) / 1000 ); +} diff --git a/sal/osl/os2/util.c b/sal/osl/os2/util.c new file mode 100644 index 000000000000..217c71878838 --- /dev/null +++ b/sal/osl/os2/util.c @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: util.c,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "osl/util.h" + + + +extern sal_Bool osl_getEthernetAddress( sal_uInt8 * pTargetAddress ) +{ + return sal_False; +} + + diff --git a/sal/osl/os2/uunxapi.cxx b/sal/osl/os2/uunxapi.cxx new file mode 100644 index 000000000000..a0a3fe952f11 --- /dev/null +++ b/sal/osl/os2/uunxapi.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: uunxapi.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + #ifndef _LIMITS_H + #include <limits.h> + #endif + + #ifndef _RTL_USTRING_HXX_ + #include <rtl/ustring.hxx> + #endif + + #ifndef _OSL_THREAD_H_ + #include <osl/thread.h> + #endif + + #ifndef _OSL_UUNXAPI_HXX_ + #include "uunxapi.hxx" + #endif + + //########################### + //access_u + int access_u(const rtl_uString* pustrPath, int mode) + { + return access(OUStringToOString(pustrPath).getStr(), mode); + } + + //######################### + //realpath_u + sal_Bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName) + { + rtl::OString fn = rtl::OUStringToOString( + rtl::OUString(const_cast<rtl_uString*>(pustrFileName)), + osl_getThreadTextEncoding()); + + char rp[PATH_MAX]; + bool bRet = realpath(fn.getStr(), rp); + + if (bRet) + { + rtl::OUString resolved = rtl::OStringToOUString( + rtl::OString(static_cast<sal_Char*>(rp)), + osl_getThreadTextEncoding()); + + rtl_uString_assign(ppustrResolvedName, resolved.pData); + } + return bRet; + } + + //######################### + //lstat_u + int lstat_u(const rtl_uString* pustrPath, struct stat* buf) + { + return lstat(OUStringToOString(pustrPath).getStr(), buf); + } + + //######################### + // @see mkdir + int mkdir_u(const rtl_uString* path, mode_t mode) + { + return mkdir(OUStringToOString(path).getStr(), mode); + } + diff --git a/sal/osl/os2/uunxapi.h b/sal/osl/os2/uunxapi.h new file mode 100644 index 000000000000..7eb224f6309f --- /dev/null +++ b/sal/osl/os2/uunxapi.h @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: uunxapi.h,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + #ifndef _OSL_UUNXAPI_H_ + #define _OSL_UUNXAPI_H_ + + #ifndef _UNISTD_H + #include <unistd.h> + #endif + + #ifndef _STDLIB_H + #include <stdlib.h> + #endif + + #ifndef _TYPES_H + #include <sys/types.h> + #endif + + #ifndef _STAT_H + #include <sys/stat.h> + #endif + + #ifndef _RTL_USTRING_H_ + #include <rtl/ustring.h> + #endif + + + #ifdef __cplusplus + extern "C" + { + #endif + + /* @see access */ + int access_u(const rtl_uString* pustrPath, int mode); + + /*********************************** + @descr + The return value differs from the + realpath function + + @returns sal_True on success else + sal_False + + @see realpath + **********************************/ + sal_Bool realpath_u( + const rtl_uString* pustrFileName, + rtl_uString** ppustrResolvedName); + + /* @see lstat */ + int lstat_u(const rtl_uString* pustrPath, struct stat* buf); + + /* @see mkdir */ + int mkdir_u(const rtl_uString* path, mode_t mode); + + #ifdef __cplusplus + } + #endif + + + #endif /* _OSL_UUNXAPI_H_ */ + diff --git a/sal/osl/os2/uunxapi.hxx b/sal/osl/os2/uunxapi.hxx new file mode 100644 index 000000000000..3b99ec98e808 --- /dev/null +++ b/sal/osl/os2/uunxapi.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: uunxapi.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + #ifndef _OSL_UUNXAPI_HXX_ + #define _OSL_UUNXAPI_HXX_ + + #ifndef _OSL_UUNXAPI_H_ + #include "uunxapi.h" + #endif + + #ifndef _RTL_USTRING_HXX_ + #include <rtl/ustring.hxx> + #endif + + //########################### + inline rtl::OString OUStringToOString(const rtl_uString* s) + { + return rtl::OUStringToOString( + rtl::OUString(const_cast<rtl_uString*>(s)), + osl_getThreadTextEncoding()); + } + + namespace osl + { + + /*********************************** + osl::access + + @see access + **********************************/ + + inline int access(const rtl::OUString& ustrPath, int mode) + { + return access_u(ustrPath.pData, mode); + } + + /*********************************** + osl::realpath + + @descr + The return value differs from the + realpath function + + @returns sal_True on success else + sal_False + + @see realpath + **********************************/ + + inline sal_Bool realpath( + const rtl::OUString& ustrFileName, + rtl::OUString& ustrResolvedName) + { + return realpath_u(ustrFileName.pData, &ustrResolvedName.pData); + } + + + /*********************************** + osl::lstat + + @see lstat + **********************************/ + + inline int lstat(const rtl::OUString& ustrPath, struct stat& buf) + { + return lstat_u(ustrPath.pData, &buf); + } + + /*********************************** + osl::mkdir + @see mkdir + **********************************/ + inline int mkdir(const rtl::OUString& aPath, mode_t aMode) + { + return mkdir_u(aPath.pData, aMode); + } + + } // end namespace osl + + + #endif /* _OSL_UUNXAPI_HXX_ */ + |