1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sal.hxx" 30 #include <cstdarg> 31 #include <cstdio> 32 #include <stdio.h> 33 #include <stdarg.h> 34 35 #include <rtl/logfile.h> 36 #include <osl/process.h> 37 #ifndef _OSL_FILE_H_ 38 #include <osl/time.h> 39 #endif 40 #include <osl/time.h> 41 #include <osl/mutex.hxx> 42 #include <rtl/bootstrap.h> 43 #include <rtl/ustring.hxx> 44 #ifndef _RTL_STRBUF_HXX_ 45 #include <rtl/ustrbuf.hxx> 46 #endif 47 #include <rtl/alloc.h> 48 #include "osl/thread.h" 49 50 #include <algorithm> 51 52 #ifdef _MSC_VER 53 #define vsnprintf _vsnprintf 54 #endif 55 56 using namespace rtl; 57 using namespace osl; 58 using namespace std; 59 60 namespace { 61 62 static oslFileHandle g_aFile = 0; 63 static sal_Bool g_bHasBeenCalled = sal_False; 64 static const sal_Int32 g_BUFFERSIZE = 4096; 65 static sal_Char *g_buffer = 0; 66 67 class LoggerGuard 68 { 69 public: 70 ~LoggerGuard(); 71 }; 72 73 LoggerGuard::~LoggerGuard() 74 { 75 if( g_buffer ) 76 { 77 sal_Int64 nWritten, nConverted = 78 sprintf( g_buffer, "closing log file at %06" SAL_PRIuUINT32, osl_getGlobalTimer() ); 79 if( nConverted > 0 ) 80 osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten ); 81 osl_closeFile( g_aFile ); 82 g_aFile = 0; 83 84 rtl_freeMemory( g_buffer ); 85 g_buffer = 0; 86 g_bHasBeenCalled = sal_False; 87 } 88 } 89 90 // The destructor of this static LoggerGuard is "activated" by the assignment to 91 // g_buffer in init(): 92 LoggerGuard loggerGuard; 93 94 Mutex & getLogMutex() 95 { 96 static Mutex *pMutex = 0; 97 if( !pMutex ) 98 { 99 MutexGuard guard( Mutex::getGlobalMutex() ); 100 if( ! pMutex ) 101 { 102 static Mutex mutex; 103 pMutex = &mutex; 104 } 105 } 106 return *pMutex; 107 } 108 109 OUString getFileUrl( const OUString &name ) 110 { 111 OUString aRet; 112 if ( osl_getFileURLFromSystemPath( name.pData, &aRet.pData ) 113 != osl_File_E_None ) 114 { 115 OSL_ASSERT( false ); 116 } 117 118 OUString aWorkingDirectory; 119 osl_getProcessWorkingDir( &(aWorkingDirectory.pData) ); 120 osl_getAbsoluteFileURL( aWorkingDirectory.pData, aRet.pData, &(aRet.pData) ); 121 122 return aRet; 123 } 124 125 void init() { 126 if( !g_bHasBeenCalled ) 127 { 128 MutexGuard guard( getLogMutex() ); 129 if( ! g_bHasBeenCalled ) 130 { 131 OUString name( RTL_CONSTASCII_USTRINGPARAM( "RTL_LOGFILE" ) ); 132 OUString value; 133 if( rtl_bootstrap_get( name.pData, &value.pData, 0 ) ) 134 { 135 // Obtain process id. 136 oslProcessIdentifier aProcessId = 0; 137 oslProcessInfo info; 138 info.Size = sizeof (oslProcessInfo); 139 if (osl_getProcessInfo (0, osl_Process_IDENTIFIER, &info) == osl_Process_E_None) 140 aProcessId = info.Ident; 141 142 // Construct name of log file and open the file. 143 OUStringBuffer buf( 128 ); 144 buf.append( value ); 145 146 // if the filename ends with .nopid, the incoming filename is not modified 147 if( value.getLength() < 6 /* ".nopid" */ || 148 rtl_ustr_ascii_compare_WithLength( 149 value.getStr() + (value.getLength()-6) , 6 , ".nopid" ) ) 150 { 151 buf.appendAscii( "_" ); 152 buf.append( (sal_Int32) aProcessId ); 153 buf.appendAscii( ".log" ); 154 } 155 156 OUString o = getFileUrl( buf.makeStringAndClear() ); 157 oslFileError e = osl_openFile( 158 o.pData, &g_aFile, osl_File_OpenFlag_Write|osl_File_OpenFlag_Create); 159 160 if( osl_File_E_None == e ) 161 { 162 TimeValue aCurrentTime; 163 g_buffer = ( sal_Char * ) rtl_allocateMemory( g_BUFFERSIZE ); 164 sal_Int64 nConverted = 0; 165 if (osl_getSystemTime (&aCurrentTime)) 166 { 167 nConverted = (sal_Int64 ) sprintf ( 168 g_buffer, 169 "opening log file %f seconds past January 1st 1970\n" 170 "corresponding to %" SAL_PRIuUINT32 " ms after timer start\n", 171 aCurrentTime.Seconds + 1e-9 * aCurrentTime.Nanosec, 172 osl_getGlobalTimer()); 173 174 if( nConverted > 0 ) 175 { 176 sal_Int64 nWritten; 177 osl_writeFile( g_aFile, g_buffer, nConverted , (sal_uInt64 *)&nWritten ); 178 } 179 } 180 181 nConverted = sprintf (g_buffer, "Process id is %" SAL_PRIuUINT32 "\n", aProcessId); 182 if( nConverted ) 183 { 184 sal_Int64 nWritten; 185 osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten ); 186 } 187 } 188 else 189 { 190 OSL_TRACE( "Couldn't open logfile %s(%d)" , o.getStr(), e ); 191 } 192 } 193 g_bHasBeenCalled = sal_True; 194 } 195 } 196 } 197 198 } 199 200 extern "C" void SAL_CALL rtl_logfile_trace ( const char *pszFormat, ... ) 201 { 202 init(); 203 if( g_buffer ) 204 { 205 va_list args; 206 va_start(args, pszFormat); 207 { 208 sal_Int64 nConverted, nWritten; 209 MutexGuard guard( getLogMutex() ); 210 nConverted = vsnprintf( g_buffer , g_BUFFERSIZE, pszFormat, args ); 211 nConverted = (nConverted > g_BUFFERSIZE ? g_BUFFERSIZE : nConverted ); 212 if( nConverted > 0 ) 213 osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64*)&nWritten ); 214 } 215 va_end(args); 216 } 217 } 218 219 extern "C" void SAL_CALL rtl_logfile_longTrace(char const * format, ...) { 220 init(); 221 if (g_buffer != 0) { 222 sal_uInt32 time = osl_getGlobalTimer(); 223 oslThreadIdentifier threadId = osl_getThreadIdentifier(0); 224 va_list args; 225 va_start(args, format); 226 { 227 MutexGuard g(getLogMutex()); 228 int n1 = snprintf( 229 g_buffer, g_BUFFERSIZE, "%06" SAL_PRIuUINT32 " %" SAL_PRIuUINT32 " ", time, threadId); 230 if (n1 >= 0) { 231 sal_uInt64 n2; 232 osl_writeFile( 233 g_aFile, g_buffer, 234 static_cast< sal_uInt64 >( 235 std::min(n1, static_cast< int >(g_BUFFERSIZE))), 236 &n2); 237 n1 = vsnprintf(g_buffer, g_BUFFERSIZE, format, args); 238 if (n1 > 0) { 239 osl_writeFile( 240 g_aFile, g_buffer, 241 static_cast< sal_uInt64 >( 242 std::min(n1, static_cast< int >(g_BUFFERSIZE))), 243 &n2); 244 } 245 } 246 } 247 va_end(args); 248 } 249 } 250 251 extern "C" sal_Bool SAL_CALL rtl_logfile_hasLogFile( void ) { 252 init(); 253 return g_buffer != 0; 254 } 255