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