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
~LoggerGuard()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
getLogMutex()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
getFileUrl(const OUString & name)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
init()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
rtl_logfile_trace(const char * pszFormat,...)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
rtl_logfile_longTrace(char const * format,...)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
rtl_logfile_hasLogFile(void)247 extern "C" sal_Bool SAL_CALL rtl_logfile_hasLogFile( void ) {
248 init();
249 return g_buffer != 0;
250 }
251