Bug Summary

File:jdk/src/hotspot/share/logging/logFileOutput.cpp
Warning:line 150, column 7
Value stored to 'found' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name logFileOutput.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp
1/*
2 * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24#include "precompiled.hpp"
25#include "jvm.h"
26#include "logging/log.hpp"
27#include "logging/logAsyncWriter.hpp"
28#include "logging/logConfiguration.hpp"
29#include "logging/logFileOutput.hpp"
30#include "memory/allocation.inline.hpp"
31#include "runtime/arguments.hpp"
32#include "runtime/os.hpp"
33#include "utilities/globalDefinitions.hpp"
34#include "utilities/defaultStream.hpp"
35
36const char* const LogFileOutput::Prefix = "file=";
37const char* const LogFileOutput::FileOpenMode = "a";
38const char* const LogFileOutput::PidFilenamePlaceholder = "%p";
39const char* const LogFileOutput::TimestampFilenamePlaceholder = "%t";
40const char* const LogFileOutput::TimestampFormat = "%Y-%m-%d_%H-%M-%S";
41const char* const LogFileOutput::FileSizeOptionKey = "filesize";
42const char* const LogFileOutput::FileCountOptionKey = "filecount";
43char LogFileOutput::_pid_str[PidBufferSize];
44char LogFileOutput::_vm_start_time_str[StartTimeBufferSize];
45
46LogFileOutput::LogFileOutput(const char* name)
47 : LogFileStreamOutput(NULL__null), _name(os::strdup_check_oom(name, mtLogging)),
48 _file_name(NULL__null), _archive_name(NULL__null), _current_file(0),
49 _file_count(DefaultFileCount), _is_default_file_count(true), _archive_name_len(0),
50 _rotate_size(DefaultFileSize), _current_size(0), _rotation_semaphore(1) {
51 assert(strstr(name, Prefix) == name, "invalid output name '%s': missing prefix: %s", name, Prefix)do { if (!(strstr(name, Prefix) == name)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 51, "assert(" "strstr(name, Prefix) == name" ") failed", "invalid output name '%s': missing prefix: %s"
, name, Prefix); ::breakpoint(); } } while (0)
;
52 _file_name = make_file_name(name + strlen(Prefix), _pid_str, _vm_start_time_str);
53}
54
55const char* LogFileOutput::cur_log_file_name() {
56 if (strlen(_archive_name) == 0) {
57 return _file_name;
58 } else {
59 return _archive_name;
60 }
61}
62
63void LogFileOutput::set_file_name_parameters(jlong vm_start_time) {
64 int res = jio_snprintf(_pid_str, sizeof(_pid_str), "%d", os::current_process_id());
65 assert(res > 0, "PID buffer too small")do { if (!(res > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 65, "assert(" "res > 0" ") failed", "PID buffer too small"
); ::breakpoint(); } } while (0)
;
66
67 struct tm local_time;
68 time_t utc_time = vm_start_time / 1000;
69 os::localtime_pd(&utc_time, &local_time);
70 res = (int)strftime(_vm_start_time_str, sizeof(_vm_start_time_str), TimestampFormat, &local_time);
71 assert(res > 0, "VM start time buffer too small.")do { if (!(res > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 71, "assert(" "res > 0" ") failed", "VM start time buffer too small."
); ::breakpoint(); } } while (0)
;
72}
73
74LogFileOutput::~LogFileOutput() {
75 if (_stream != NULL__null) {
76 if (fclose(_stream) != 0) {
77 jio_fprintf(defaultStream::error_stream(), "Could not close log file '%s' (%s).\n",
78 _file_name, os::strerror(errno(*__errno_location ())));
79 }
80 }
81 os::free(_archive_name);
82 os::free(_file_name);
83 os::free(const_cast<char*>(_name));
84}
85
86static size_t parse_value(const char* value_str) {
87 char* end;
88 unsigned long long value = strtoull(value_str, &end, 10);
89 if (!isdigit(*value_str) || end != value_str + strlen(value_str) || value >= SIZE_MAX(18446744073709551615UL)) {
90 return SIZE_MAX(18446744073709551615UL);
91 }
92 return value;
93}
94
95static uint number_of_digits(uint number) {
96 return number < 10 ? 1 : (number < 100 ? 2 : 3);
97}
98
99static bool is_regular_file(const char* filename) {
100 struct stat st;
101 int ret = os::stat(filename, &st);
102 if (ret != 0) {
103 return false;
104 }
105 return (st.st_mode & S_IFMT0170000) == S_IFREG0100000;
106}
107
108static bool is_fifo_file(const char* filename) {
109 struct stat st;
110 int ret = os::stat(filename, &st);
111 if (ret != 0) {
112 return false;
113 }
114 return S_ISFIFO(st.st_mode)((((st.st_mode)) & 0170000) == (0010000));
115}
116
117// Try to find the next number that should be used for file rotation.
118// Return UINT_MAX on error.
119static uint next_file_number(const char* filename,
120 uint number_of_digits,
121 uint filecount,
122 outputStream* errstream) {
123 bool found = false;
124 uint next_num = 0;
125
126 // len is filename + dot + digits + null char
127 size_t len = strlen(filename) + number_of_digits + 2;
128 char* archive_name = NEW_C_HEAP_ARRAY(char, len, mtLogging)(char*) (AllocateHeap((len) * sizeof(char), mtLogging));
129 char* oldest_name = NEW_C_HEAP_ARRAY(char, len, mtLogging)(char*) (AllocateHeap((len) * sizeof(char), mtLogging));
130
131 for (uint i = 0; i < filecount; i++) {
132 int ret = jio_snprintf(archive_name, len, "%s.%0*u",
133 filename, number_of_digits, i);
134 assert(ret > 0 && static_cast<size_t>(ret) == len - 1,do { if (!(ret > 0 && static_cast<size_t>(ret
) == len - 1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 135, "assert(" "ret > 0 && static_cast<size_t>(ret) == len - 1"
") failed", "incorrect buffer length calculation"); ::breakpoint
(); } } while (0)
135 "incorrect buffer length calculation")do { if (!(ret > 0 && static_cast<size_t>(ret
) == len - 1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 135, "assert(" "ret > 0 && static_cast<size_t>(ret) == len - 1"
") failed", "incorrect buffer length calculation"); ::breakpoint
(); } } while (0)
;
136
137 if (os::file_exists(archive_name) && !is_regular_file(archive_name)) {
138 // We've encountered something that's not a regular file among the
139 // possible file rotation targets. Fail immediately to prevent
140 // problems later.
141 errstream->print_cr("Possible rotation target file '%s' already exists "
142 "but is not a regular file.", archive_name);
143 next_num = UINT_MAX(2147483647 *2U +1U);
144 break;
145 }
146
147 // Stop looking if we find an unused file name
148 if (!os::file_exists(archive_name)) {
149 next_num = i;
150 found = true;
Value stored to 'found' is never read
151 break;
152 }
153
154 // Keep track of oldest existing log file
155 if (!found
156 || os::compare_file_modified_times(oldest_name, archive_name) > 0) {
157 strcpy(oldest_name, archive_name);
158 next_num = i;
159 found = true;
160 }
161 }
162
163 FREE_C_HEAP_ARRAY(char, oldest_name)FreeHeap((char*)(oldest_name));
164 FREE_C_HEAP_ARRAY(char, archive_name)FreeHeap((char*)(archive_name));
165 return next_num;
166}
167
168bool LogFileOutput::set_option(const char* key, const char* value, outputStream* errstream) {
169 bool success = LogFileStreamOutput::set_option(key, value, errstream);
170 if (!success) {
171 if (strcmp(FileCountOptionKey, key) == 0) {
172 size_t sizeval = parse_value(value);
173 if (sizeval > MaxRotationFileCount) {
174 errstream->print_cr("Invalid option: %s must be in range [0, %u]",
175 FileCountOptionKey,
176 MaxRotationFileCount);
177 } else {
178 _file_count = static_cast<uint>(sizeval);
179 _is_default_file_count = false;
180 success = true;
181 }
182 } else if (strcmp(FileSizeOptionKey, key) == 0) {
183 julong longval;
184 success = Arguments::atojulong(value, &longval);
185 if (!success || (longval > SIZE_MAX(18446744073709551615UL))) {
186 errstream->print_cr("Invalid option: %s must be in range [0, "
187 SIZE_FORMAT"%" "l" "u" "]", FileSizeOptionKey, (size_t)SIZE_MAX(18446744073709551615UL));
188 success = false;
189 } else {
190 _rotate_size = static_cast<size_t>(longval);
191 success = true;
192 }
193 }
194 }
195 return success;
196}
197
198bool LogFileOutput::initialize(const char* options, outputStream* errstream) {
199 if (!parse_options(options, errstream)) {
200 return false;
201 }
202
203 bool file_exist = os::file_exists(_file_name);
204 if (file_exist && _is_default_file_count && is_fifo_file(_file_name)) {
205 _file_count = 0; // Prevent file rotation for fifo's such as named pipes.
206 }
207
208 if (_file_count > 0) {
209 // compute digits with filecount - 1 since numbers will start from 0
210 _file_count_max_digits = number_of_digits(_file_count - 1);
211 _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits;
212 _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging)(char*) (AllocateHeap((_archive_name_len) * sizeof(char), mtLogging
))
;
213 _archive_name[0] = 0;
214 }
215
216 log_trace(logging)(!(LogImpl<(LogTag::_logging), (LogTag::__NO_TAG), (LogTag
::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::
__NO_TAG)>::is_level(LogLevel::Trace))) ? (void)0 : LogImpl
<(LogTag::_logging), (LogTag::__NO_TAG), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG)
>::write<LogLevel::Trace>
("Initializing logging to file '%s' (filecount: %u"
217 ", filesize: " SIZE_FORMAT"%" "l" "u" " KiB).",
218 _file_name, _file_count, _rotate_size / K);
219
220 if (_file_count > 0 && file_exist) {
221 if (!is_regular_file(_file_name)) {
222 errstream->print_cr("Unable to log to file %s with log file rotation: "
223 "%s is not a regular file",
224 _file_name, _file_name);
225 return false;
226 }
227 _current_file = next_file_number(_file_name,
228 _file_count_max_digits,
229 _file_count,
230 errstream);
231 if (_current_file == UINT_MAX(2147483647 *2U +1U)) {
232 return false;
233 }
234 log_trace(logging)(!(LogImpl<(LogTag::_logging), (LogTag::__NO_TAG), (LogTag
::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::
__NO_TAG)>::is_level(LogLevel::Trace))) ? (void)0 : LogImpl
<(LogTag::_logging), (LogTag::__NO_TAG), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG)
>::write<LogLevel::Trace>
("Existing log file found, saving it as '%s.%0*u'",
235 _file_name, _file_count_max_digits, _current_file);
236 archive();
237 increment_file_count();
238 }
239
240 _stream = os::fopen(_file_name, FileOpenMode);
241 if (_stream == NULL__null) {
242 errstream->print_cr("Error opening log file '%s': %s",
243 _file_name, os::strerror(errno(*__errno_location ())));
244 return false;
245 }
246
247 if (_file_count == 0 && is_regular_file(_file_name)) {
248 log_trace(logging)(!(LogImpl<(LogTag::_logging), (LogTag::__NO_TAG), (LogTag
::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::
__NO_TAG)>::is_level(LogLevel::Trace))) ? (void)0 : LogImpl
<(LogTag::_logging), (LogTag::__NO_TAG), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG)
>::write<LogLevel::Trace>
("Truncating log file");
249 os::ftruncate(os::get_fileno(_stream), 0);
250 }
251
252 return true;
253}
254
255class RotationLocker : public StackObj {
256 Semaphore& _sem;
257
258 public:
259 RotationLocker(Semaphore& sem) : _sem(sem) {
260 sem.wait();
261 }
262
263 ~RotationLocker() {
264 _sem.signal();
265 }
266};
267
268int LogFileOutput::write_blocking(const LogDecorations& decorations, const char* msg) {
269 RotationLocker lock(_rotation_semaphore);
270 if (_stream == NULL__null) {
271 // An error has occurred with this output, avoid writing to it.
272 return 0;
273 }
274
275 int written = LogFileStreamOutput::write(decorations, msg);
276 if (written > 0) {
277 _current_size += written;
278
279 if (should_rotate()) {
280 rotate();
281 }
282 }
283
284 return written;
285}
286
287int LogFileOutput::write(const LogDecorations& decorations, const char* msg) {
288 if (_stream == NULL__null) {
289 // An error has occurred with this output, avoid writing to it.
290 return 0;
291 }
292
293 AsyncLogWriter* aio_writer = AsyncLogWriter::instance();
294 if (aio_writer != nullptr) {
295 aio_writer->enqueue(*this, decorations, msg);
296 return 0;
297 }
298
299 return write_blocking(decorations, msg);
300}
301
302int LogFileOutput::write(LogMessageBuffer::Iterator msg_iterator) {
303 if (_stream == NULL__null) {
304 // An error has occurred with this output, avoid writing to it.
305 return 0;
306 }
307
308 AsyncLogWriter* aio_writer = AsyncLogWriter::instance();
309 if (aio_writer != nullptr) {
310 aio_writer->enqueue(*this, msg_iterator);
311 return 0;
312 }
313
314 RotationLocker lock(_rotation_semaphore);
315 int written = LogFileStreamOutput::write(msg_iterator);
316 if (written > 0) {
317 _current_size += written;
318
319 if (should_rotate()) {
320 rotate();
321 }
322 }
323
324 return written;
325}
326
327void LogFileOutput::archive() {
328 assert(_archive_name != NULL && _archive_name_len > 0, "Rotation must be configured before using this function.")do { if (!(_archive_name != __null && _archive_name_len
> 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 328, "assert(" "_archive_name != __null && _archive_name_len > 0"
") failed", "Rotation must be configured before using this function."
); ::breakpoint(); } } while (0)
;
329 int ret = jio_snprintf(_archive_name, _archive_name_len, "%s.%0*u",
330 _file_name, _file_count_max_digits, _current_file);
331 assert(ret >= 0, "Buffer should always be large enough")do { if (!(ret >= 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/logging/logFileOutput.cpp"
, 331, "assert(" "ret >= 0" ") failed", "Buffer should always be large enough"
); ::breakpoint(); } } while (0)
;
332
333 // Attempt to remove possibly existing archived log file before we rename.
334 // Don't care if it fails, we really only care about the rename that follows.
335 remove(_archive_name);
336
337 // Rename the file from ex hotspot.log to hotspot.log.2
338 if (rename(_file_name, _archive_name) == -1) {
339 jio_fprintf(defaultStream::error_stream(), "Could not rename log file '%s' to '%s' (%s).\n",
340 _file_name, _archive_name, os::strerror(errno(*__errno_location ())));
341 }
342}
343
344void LogFileOutput::force_rotate() {
345 if (_file_count == 0) {
346 // Rotation not possible
347 return;
348 }
349
350 RotationLocker lock(_rotation_semaphore);
351 rotate();
352}
353
354void LogFileOutput::rotate() {
355 if (fclose(_stream)) {
356 jio_fprintf(defaultStream::error_stream(), "Error closing file '%s' during log rotation (%s).\n",
357 _file_name, os::strerror(errno(*__errno_location ())));
358 }
359
360 // Archive the current log file
361 archive();
362
363 // Open the active log file using the same stream as before
364 _stream = os::fopen(_file_name, FileOpenMode);
365 if (_stream == NULL__null) {
366 jio_fprintf(defaultStream::error_stream(), "Could not reopen file '%s' during log rotation (%s).\n",
367 _file_name, os::strerror(errno(*__errno_location ())));
368 return;
369 }
370
371 // Reset accumulated size, increase current file counter, and check for file count wrap-around.
372 _current_size = 0;
373 increment_file_count();
374}
375
376char* LogFileOutput::make_file_name(const char* file_name,
377 const char* pid_string,
378 const char* timestamp_string) {
379 char* result = NULL__null;
380
381 // Lets start finding out if we have any %d and/or %t in the name.
382 // We will only replace the first occurrence of any placeholder
383 const char* pid = strstr(file_name, PidFilenamePlaceholder);
384 const char* timestamp = strstr(file_name, TimestampFilenamePlaceholder);
385
386 if (pid == NULL__null && timestamp == NULL__null) {
387 // We found no place-holders, return the simple filename
388 return os::strdup_check_oom(file_name, mtLogging);
389 }
390
391 // At least one of the place-holders were found in the file_name
392 const char* first = "";
393 size_t first_pos = SIZE_MAX(18446744073709551615UL);
394 size_t first_replace_len = 0;
395
396 const char* second = "";
397 size_t second_pos = SIZE_MAX(18446744073709551615UL);
398 size_t second_replace_len = 0;
399
400 // If we found a %p, then setup our variables accordingly
401 if (pid != NULL__null) {
402 if (timestamp == NULL__null || pid < timestamp) {
403 first = pid_string;
404 first_pos = pid - file_name;
405 first_replace_len = strlen(PidFilenamePlaceholder);
406 } else {
407 second = pid_string;
408 second_pos = pid - file_name;
409 second_replace_len = strlen(PidFilenamePlaceholder);
410 }
411 }
412
413 if (timestamp != NULL__null) {
414 if (pid == NULL__null || timestamp < pid) {
415 first = timestamp_string;
416 first_pos = timestamp - file_name;
417 first_replace_len = strlen(TimestampFilenamePlaceholder);
418 } else {
419 second = timestamp_string;
420 second_pos = timestamp - file_name;
421 second_replace_len = strlen(TimestampFilenamePlaceholder);
422 }
423 }
424
425 size_t first_len = strlen(first);
426 size_t second_len = strlen(second);
427
428 // Allocate the new buffer, size it to hold all we want to put in there +1.
429 size_t result_len = strlen(file_name) + first_len - first_replace_len + second_len - second_replace_len;
430 result = NEW_C_HEAP_ARRAY(char, result_len + 1, mtLogging)(char*) (AllocateHeap((result_len + 1) * sizeof(char), mtLogging
))
;
431
432 // Assemble the strings
433 size_t file_name_pos = 0;
434 size_t i = 0;
435 while (i < result_len) {
436 if (file_name_pos == first_pos) {
437 // We are in the range of the first placeholder
438 strcpy(result + i, first);
439 // Bump output buffer position with length of replacing string
440 i += first_len;
441 // Bump source buffer position to skip placeholder
442 file_name_pos += first_replace_len;
443 } else if (file_name_pos == second_pos) {
444 // We are in the range of the second placeholder
445 strcpy(result + i, second);
446 i += second_len;
447 file_name_pos += second_replace_len;
448 } else {
449 // Else, copy char by char of the original file
450 result[i] = file_name[file_name_pos++];
451 i++;
452 }
453 }
454 // Add terminating char
455 result[result_len] = '\0';
456 return result;
457}
458
459void LogFileOutput::describe(outputStream *out) {
460 LogFileStreamOutput::describe(out);
461 out->print(",filecount=%u,filesize=" SIZE_FORMAT"%" "l" "u" "%s,async=%s", _file_count,
462 byte_size_in_proper_unit(_rotate_size),
463 proper_unit_for_byte_size(_rotate_size),
464 LogConfiguration::is_async_mode() ? "true" : "false");
465}