16 #define _GNU_SOURCE 1 // needed for O_NOFOLLOW and pread()/pwrite()
31 #include <sys/utsname.h>
40 #include <sys/types.h>
48 #include "absl/debugging/stacktrace.h"
49 #include "absl/time/time.h"
58 std::once_flag init_done;
63 absl::SetFlag(&FLAGS_logtostderr,
true);
64 absl::SetFlag(&FLAGS_log_prefix,
false);
71 using std::ostringstream;
85 #define fdopen _fdopen
86 #define strcasecmp _stricmp
91 enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
94 inline char* strerror_r(
int errnum,
char* buf,
size_t buflen) {
95 strerror_s(buf, buflen, errnum);
99 inline struct tm* localtime_r(
const time_t* timep,
struct tm* result) {
100 localtime_s(result, timep);
106 "log messages go to stderr instead of logfiles");
108 "log messages go to stderr in addition to logfiles");
110 "color messages logged to stderr (if supported by terminal)");
111 #if defined(__linux__)
113 "Drop in-memory buffers of log contents. "
114 "Logs can grow very quickly and they are rarely read before they "
115 "need to be evicted from memory. Instead, drop them from memory "
116 "as soon as they are flushed to disk.");
125 "log messages at or above this level are copied to stderr in "
126 "addition to logfiles. This flag obsoletes --alsologtostderr.");
129 "Prepend the log prefix to the start of each log line");
131 "Messages logged at a lower level than this don't "
132 "actually get logged anywhere");
134 "Buffer log messages logged at this level or lower"
135 " (-1 means don't buffer; 0 means buffer INFO only;"
138 "Buffer log messages for at most this many seconds");
143 env = getenv(
"GOOGLE_LOG_DIR");
144 if (env != NULL && env[0] !=
'\0') {
147 env = getenv(
"TEST_TMPDIR");
148 if (env != NULL && env[0] !=
'\0') {
154 ABSL_FLAG(
int, logfile_mode, 0664,
"Log file mode/permissions.");
157 "If specified, logfiles are written into this directory instead "
158 "of the default logging directory.");
160 "Put additional links to the log "
161 "files in this directory");
164 "approx. maximum log file size (in MB). A value of 0 will "
165 "be silently overridden to 1.");
168 "Stop attempting to log to disk if the disk is full.");
171 "Emit a backtrace when logging at file:linenum.");
173 #if defined(_MSC_VER)
174 #define PATH_SEPARATOR '\\'
176 #define PATH_SEPARATOR '/'
181 #define ssize_t SSIZE_T
182 static ssize_t pread(
int fd,
void* buf,
size_t count, off_t offset) {
183 off_t orig_offset = lseek(fd, 0, SEEK_CUR);
184 if (orig_offset == (off_t)-1)
return -1;
185 if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
return -1;
186 ssize_t len = read(fd, buf, count);
187 if (len < 0)
return len;
188 if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
return -1;
192 static ssize_t pwrite(
int fd,
void* buf,
size_t count, off_t offset) {
193 off_t orig_offset = lseek(fd, 0, SEEK_CUR);
194 if (orig_offset == (off_t)-1)
return -1;
195 if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
return -1;
196 ssize_t len = write(fd, buf, count);
197 if (len < 0)
return len;
198 if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
return -1;
204 #if !defined(_MSC_VER)
206 if (0 != uname(&buf)) {
208 *buf.nodename =
'\0';
210 *hostname = buf.nodename;
212 char buf[MAX_COMPUTERNAME_LENGTH + 1];
213 DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
214 if (GetComputerNameA(buf, &len)) {
224 bool term_supports_color =
false;
228 term_supports_color =
true;
231 const char*
const term = getenv(
"TERM");
232 if (term != NULL && term[0] !=
'\0') {
233 term_supports_color =
234 !strcmp(term,
"xterm") || !strcmp(term,
"xterm-color") ||
235 !strcmp(term,
"xterm-256color") || !strcmp(term,
"screen-256color") ||
236 !strcmp(term,
"konsole") || !strcmp(term,
"konsole-16color") ||
237 !strcmp(term,
"konsole-256color") || !strcmp(term,
"screen") ||
238 !strcmp(term,
"linux") || !strcmp(term,
"cygwin");
241 return term_supports_color;
272 static WORD GetColorAttribute(
GLogColor color) {
275 return FOREGROUND_RED;
277 return FOREGROUND_GREEN;
279 return FOREGROUND_RED | FOREGROUND_GREEN;
306 return (absl::GetFlag(FLAGS_max_log_size) > 0
307 ? absl::GetFlag(FLAGS_max_log_size)
375 LogFileObject(
LogSeverity severity,
const char* base_filename);
378 virtual void Write(
bool force_flush,
380 const char*
message,
int message_len);
383 void SetBasename(
const char* basename);
384 void SetExtension(
const char* ext);
385 void SetSymlinkBasename(
const char* symlink_basename);
388 virtual void Flush();
392 virtual uint32 LogSize() {
393 absl::MutexLock l(&lock_);
400 void FlushUnlocked();
403 static const uint32 kRolloverAttemptFrequency = 0x20;
406 bool base_filename_selected_;
407 string base_filename_;
408 string symlink_basename_;
409 string filename_extension_;
412 uint32 bytes_since_flush_;
413 uint32 dropped_mem_length_;
415 unsigned int rollover_attempt_;
416 int64 next_flush_time_;
421 bool CreateLogfile(
const string& time_pid_string);
435 const char* base_filename);
449 static const int kNetworkBytes = 1400;
451 static const string& hostname();
453 return terminal_supports_color_;
456 static void DeleteLogDestinations();
469 static void MaybeLogToLogfile(
LogSeverity severity, time_t timestamp,
470 const char*
message,
size_t len);
474 static void LogToAllLogfiles(
LogSeverity severity, time_t timestamp,
475 const char*
message,
size_t len);
478 static void LogToSinks(
LogSeverity severity,
const char* full_filename,
479 const char* base_filename,
int line,
480 const struct ::tm* tm_time,
const char*
message,
485 static void WaitForSinks(LogMessage::LogMessageData* data);
487 static LogDestination* log_destination(
LogSeverity severity);
489 LogFileObject fileobject_;
490 base::Logger* logger_;
493 static string addresses_;
494 static string hostname_;
495 static bool terminal_supports_color_;
498 static vector<LogSink*>* sinks_;
502 static absl::Mutex sink_mutex_;
505 LogDestination(
const LogDestination&);
506 LogDestination& operator=(
const LogDestination&);
509 string LogDestination::addresses_;
510 string LogDestination::hostname_;
512 vector<LogSink*>* LogDestination::sinks_ = NULL;
513 absl::Mutex LogDestination::sink_mutex_;
518 if (hostname_.empty()) {
520 if (hostname_.empty()) {
521 hostname_ =
"(unknown)";
527 LogDestination::LogDestination(
LogSeverity severity,
const char* base_filename)
528 : fileobject_(severity, base_filename), logger_(&fileobject_) {}
538 log->fileobject_.FlushUnlocked();
550 log->logger_->
Flush();
556 const char* base_filename) {
561 log_destination(severity)->fileobject_.SetBasename(base_filename);
565 const char* symlink_basename) {
569 log_destination(severity)->fileobject_.SetSymlinkBasename(symlink_basename);
575 absl::MutexLock l(&sink_mutex_);
576 if (!sinks_) sinks_ =
new vector<LogSink*>;
577 sinks_->push_back(destination);
583 absl::MutexLock l(&sink_mutex_);
586 for (
int i = sinks_->size() - 1; i >= 0; i--) {
587 if ((*sinks_)[i] == destination) {
588 (*sinks_)[i] = (*sinks_)[sinks_->size() - 1];
601 log_destination(severity)->fileobject_.SetExtension(ext);
610 absl::SetFlag(&FLAGS_stderrthreshold, min_severity);
625 absl::GetFlag(FLAGS_colorlogtostderr))
632 fwrite(
message, len, 1, stderr);
636 const HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
639 CONSOLE_SCREEN_BUFFER_INFO buffer_info;
640 GetConsoleScreenBufferInfo(stderr_handle, &buffer_info);
641 const WORD old_color_attrs = buffer_info.wAttributes;
647 SetConsoleTextAttribute(stderr_handle,
648 GetColorAttribute(color) | FOREGROUND_INTENSITY);
649 fwrite(
message, len, 1, stderr);
652 SetConsoleTextAttribute(stderr_handle, old_color_attrs);
655 fwrite(
message, len, 1, stderr);
656 fprintf(stderr,
"\033[m");
663 fwrite(
message, len, 1, stderr);
666 inline void LogDestination::MaybeLogToStderr(
LogSeverity severity,
667 const char*
message,
size_t len) {
668 if ((severity >= absl::GetFlag(FLAGS_stderrthreshold)) ||
669 absl::GetFlag(FLAGS_alsologtostderr)) {
673 ::OutputDebugStringA(
string(
message, len).c_str());
678 inline void LogDestination::MaybeLogToLogfile(
LogSeverity severity,
680 const char*
message,
size_t len) {
681 const bool should_flush = severity > absl::GetFlag(FLAGS_logbuflevel);
682 LogDestination* destination = log_destination(severity);
683 destination->logger_->Write(should_flush, timestamp,
message, len);
686 inline void LogDestination::LogToAllLogfiles(
LogSeverity severity,
688 const char*
message,
size_t len) {
689 if (absl::GetFlag(FLAGS_logtostderr)) {
692 for (
int i = severity; i >= 0; --i)
693 LogDestination::MaybeLogToLogfile(i, timestamp,
message, len);
697 inline void LogDestination::LogToSinks(
LogSeverity severity,
698 const char* full_filename,
699 const char* base_filename,
int line,
700 const struct ::tm* tm_time,
702 size_t message_len) {
703 absl::ReaderMutexLock l(&sink_mutex_);
705 for (
int i = sinks_->size() - 1; i >= 0; i--) {
706 (*sinks_)[i]->send(severity, full_filename, base_filename, line, tm_time,
712 inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) {
713 absl::ReaderMutexLock l(&sink_mutex_);
715 for (
int i = sinks_->size() - 1; i >= 0; i--) {
716 (*sinks_)[i]->WaitTillSent();
719 const bool send_to_sink =
720 (data->send_method_ == &LogMessage::SendToSink) ||
721 (data->send_method_ == &LogMessage::SendToSinkAndLog);
722 if (send_to_sink && data->sink_ != NULL) {
723 data->sink_->WaitTillSent();
727 LogDestination* LogDestination::log_destinations_[
NUM_SEVERITIES];
729 inline LogDestination* LogDestination::log_destination(
LogSeverity severity) {
731 if (!log_destinations_[severity]) {
732 log_destinations_[severity] =
new LogDestination(severity, NULL);
734 return log_destinations_[severity];
739 delete log_destinations_[severity];
740 log_destinations_[severity] = NULL;
742 absl::MutexLock l(&sink_mutex_);
749 LogFileObject::LogFileObject(
LogSeverity severity,
const char* base_filename)
750 : base_filename_selected_(base_filename != NULL),
751 base_filename_((base_filename != NULL) ? base_filename :
""),
753 filename_extension_(),
756 bytes_since_flush_(0),
757 dropped_mem_length_(0),
759 rollover_attempt_(kRolloverAttemptFrequency - 1),
760 next_flush_time_(0) {
761 assert(severity >= 0);
765 LogFileObject::~LogFileObject() {
766 absl::MutexLock l(&lock_);
773 void LogFileObject::SetBasename(
const char* basename) {
774 absl::MutexLock l(&lock_);
775 base_filename_selected_ =
true;
776 if (base_filename_ != basename) {
781 rollover_attempt_ = kRolloverAttemptFrequency - 1;
783 base_filename_ = basename;
787 void LogFileObject::SetExtension(
const char* ext) {
788 absl::MutexLock l(&lock_);
789 if (filename_extension_ != ext) {
794 rollover_attempt_ = kRolloverAttemptFrequency - 1;
796 filename_extension_ = ext;
800 void LogFileObject::SetSymlinkBasename(
const char* symlink_basename) {
801 absl::MutexLock l(&lock_);
802 symlink_basename_ = symlink_basename;
805 void LogFileObject::Flush() {
806 absl::MutexLock l(&lock_);
810 void LogFileObject::FlushUnlocked() {
813 bytes_since_flush_ = 0;
816 const int64 next = (absl::GetFlag(FLAGS_logbufsecs) *
817 static_cast<int64>(1000000));
822 bool LogFileObject::CreateLogfile(
const string& time_pid_string) {
823 string string_filename =
824 base_filename_ + filename_extension_ + time_pid_string;
825 const char* filename = string_filename.c_str();
826 int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL,
827 absl::GetFlag(FLAGS_logfile_mode));
828 if (fd == -1)
return false;
829 #if !defined(_MSC_VER)
831 fcntl(fd, F_SETFD, FD_CLOEXEC);
834 file_ = fdopen(fd,
"a");
846 if (!symlink_basename_.empty()) {
849 const string linkname =
853 linkpath = string(filename, slash - filename + 1);
854 linkpath += linkname;
855 unlink(linkpath.c_str());
857 #if !defined(_MSC_VER)
861 const char* linkdest = slash ? (slash + 1) : filename;
862 if (symlink(linkdest, linkpath.c_str()) != 0) {
868 if (!absl::GetFlag(FLAGS_log_link).empty()) {
869 linkpath = absl::GetFlag(FLAGS_log_link) +
"/" + linkname;
870 unlink(linkpath.c_str());
871 if (symlink(filename, linkpath.c_str()) != 0) {
881 void LogFileObject::Write(
bool force_flush, time_t timestamp,
882 const char*
message,
int message_len) {
883 absl::MutexLock l(&lock_);
886 if (base_filename_selected_ && base_filename_.empty()) {
890 if (
static_cast<int>(file_length_ >> 20) >=
MaxLogSize()) {
891 if (file_ != NULL) fclose(file_);
893 file_length_ = bytes_since_flush_ = dropped_mem_length_ = 0;
894 rollover_attempt_ = kRolloverAttemptFrequency - 1;
902 if (++rollover_attempt_ != kRolloverAttemptFrequency)
return;
903 rollover_attempt_ = 0;
906 localtime_r(×tamp, &tm_time);
909 ostringstream time_pid_stream;
910 time_pid_stream.fill(
'0');
911 time_pid_stream << 1900 + tm_time.tm_year << setw(2) << 1 + tm_time.tm_mon
912 << setw(2) << tm_time.tm_mday <<
'-' << setw(2)
913 << tm_time.tm_hour << setw(2) << tm_time.tm_min << setw(2)
914 << tm_time.tm_sec <<
'.'
916 const string& time_pid_string = time_pid_stream.str();
918 if (base_filename_selected_) {
919 if (!CreateLogfile(time_pid_string)) {
920 perror(
"Could not create log file");
921 fprintf(stderr,
"COULD NOT CREATE LOGFILE '%s'!\n",
922 time_pid_string.c_str());
946 if (uidname.empty()) uidname =
"invalid-user";
948 stripped_filename = stripped_filename +
'.' + hostname +
'.' + uidname +
955 bool success =
false;
956 for (vector<string>::const_iterator dir = log_dirs.begin();
957 dir != log_dirs.end(); ++dir) {
958 base_filename_ = *dir +
"/" + stripped_filename;
959 if (CreateLogfile(time_pid_string)) {
965 if (success ==
false) {
966 perror(
"Could not create logging file");
967 fprintf(stderr,
"COULD NOT CREATE A LOGGINGFILE %s!",
968 time_pid_string.c_str());
974 ostringstream file_header_stream;
975 file_header_stream.fill(
'0');
976 file_header_stream <<
"Log file created at: " << 1900 + tm_time.tm_year
977 <<
'/' << setw(2) << 1 + tm_time.tm_mon <<
'/' << setw(2)
978 << tm_time.tm_mday <<
' ' << setw(2) << tm_time.tm_hour
979 <<
':' << setw(2) << tm_time.tm_min <<
':' << setw(2)
980 << tm_time.tm_sec <<
'\n'
983 <<
"Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
984 <<
"threadid file:line] msg" <<
'\n';
985 const string& file_header_string = file_header_stream.str();
987 const int header_len = file_header_string.size();
988 fwrite(file_header_string.data(), 1, header_len, file_);
989 file_length_ += header_len;
990 bytes_since_flush_ += header_len;
1001 fwrite(
message, 1, message_len, file_);
1002 if (absl::GetFlag(FLAGS_stop_logging_if_full_disk) &&
1007 file_length_ += message_len;
1008 bytes_since_flush_ += message_len;
1018 if (force_flush || (bytes_since_flush_ >= 1000000) ||
1021 #if defined(__linux__)
1023 if (absl::GetFlag(FLAGS_drop_log_memory) && file_length_ >= (3 << 20)) {
1026 uint32 total_drop_length = (file_length_ & ~((1 << 20) - 1)) - (1 << 20);
1027 uint32 this_drop_length = total_drop_length - dropped_mem_length_;
1028 if (this_drop_length >= (2 << 20)) {
1030 posix_fadvise(fileno(file_), dropped_mem_length_, this_drop_length,
1031 POSIX_FADV_DONTNEED);
1032 dropped_mem_length_ = total_drop_length;
1058 static thread_local std::aligned_storage<
1062 LogMessage::LogMessageData::LogMessageData()
1063 : stream_(message_text_,
LogMessage::kMaxLogMessageLen, 0) {}
1067 : allocated_(NULL) {
1068 Init(
file, line, severity, send_method);
1073 : allocated_(NULL) {
1075 stream() <<
"Check failed: " << (*result.
str_) <<
" ";
1083 : allocated_(NULL) {
1088 LogSink* sink,
bool also_send_to_log)
1089 : allocated_(NULL) {
1090 Init(
file, line, severity,
1091 also_send_to_log ? &LogMessage::SendToSinkAndLog
1092 : &LogMessage::SendToSink);
1093 data_->
sink_ = sink;
1097 vector<string>* outvec)
1098 : allocated_(NULL) {
1099 Init(
file, line, severity, &LogMessage::SaveOrSendToLog);
1105 : allocated_(NULL) {
1106 Init(
file, line, severity, &LogMessage::WriteToStringAndLog);
1110 void LogMessage::Init(
const char*
file,
int line,
LogSeverity severity,
1119 allocated_ =
new LogMessageData();
1138 data_->
line_ = line;
1140 data_->
sink_ = NULL;
1142 double now = ToUDate(absl::Now());
1143 data_->
timestamp_ =
static_cast<time_t
>(now);
1145 int usecs =
static_cast<int>((now - data_->
timestamp_) * 1000000);
1157 if (absl::GetFlag(FLAGS_log_prefix) && (line !=
kNoLogPrefix)) {
1160 <<
' ' << setw(2) << data_->
tm_time_.tm_hour <<
':' << setw(2)
1161 << data_->
tm_time_.tm_min <<
':' << setw(2)
1162 << data_->
tm_time_.tm_sec <<
"." << setw(6) << usecs <<
' '
1164 << setfill(
'0') <<
' ' << data_->
basename_ <<
':' << data_->
line_
1169 if (!absl::GetFlag(FLAGS_log_backtrace_at).empty()) {
1171 snprintf(fileline,
sizeof(fileline),
"%s:%d", data_->
basename_, line);
1172 if (!strcmp(absl::GetFlag(FLAGS_log_backtrace_at).c_str(), fileline)) {
1175 stream() <<
" (stacktrace:\n" << stacktrace <<
") ";
1182 #ifdef GLOG_THREAD_LOCAL_STORAGE
1184 data_->~LogMessageData();
1189 #else // !defined(GLOG_THREAD_LOCAL_STORAGE)
1191 #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
1202 data_->
severity_ < absl::GetFlag(FLAGS_minloglevel))
1210 bool append_newline =
1212 char original_final_char =
'\0';
1219 if (append_newline) {
1229 ++num_messages_[
static_cast<int>(data_->
severity_)];
1231 LogDestination::WaitForSinks(data_);
1233 if (append_newline) {
1262 if (!absl::GetFlag(FLAGS_logtostderr)) {
1272 static bool already_warned_before_initgoogle =
false;
1282 if (!already_warned_before_initgoogle &&
1285 "WARNING: Logging before InitGoogleLogging() is "
1286 "written to STDERR\n";
1288 already_warned_before_initgoogle =
true;
1294 if (absl::GetFlag(FLAGS_logtostderr) ||
1300 LogDestination::LogToSinks(
1312 LogDestination::LogToSinks(
1337 if (!absl::GetFlag(FLAGS_logtostderr)) {
1339 if (LogDestination::log_destinations_[i])
1340 LogDestination::log_destinations_[i]->logger_->Write(
true, 0,
"", 0);
1350 LogDestination::WaitForSinks(data_);
1352 const char*
message =
"*** Check failure stack trace: ***\n";
1367 absl::GetStackTrace(reason->
stack, ABSL_ARRAYSIZE(reason->
stack), 4);
1370 #if !defined(_MSC_VER)
1371 #define ATTRIBUTE_NORETURN __attribute__((noreturn))
1373 #define ATTRIBUTE_NORETURN
1376 #if defined(_MSC_VER)
1377 __declspec(noreturn)
1395 void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(
log_mutex) {
1396 if (data_->
sink_ != NULL) {
1408 void LogMessage::SendToSinkAndLog() EXCLUSIVE_LOCKS_REQUIRED(
log_mutex) {
1414 void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(
log_mutex) {
1422 data_->
outvec_->push_back(
string(start, len));
1428 void LogMessage::WriteToStringAndLog() EXCLUSIVE_LOCKS_REQUIRED(
log_mutex) {
1436 data_->
message_->assign(start, len);
1443 #if !defined(_MSC_VER)
1445 static bool openlog_already_called =
false;
1446 if (!openlog_already_called) {
1448 LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER);
1449 openlog_already_called =
true;
1453 const int SEVERITY_TO_LEVEL[] = {LOG_INFO, LOG_WARNING, LOG_ERR, LOG_EMERG};
1454 syslog(LOG_USER | SEVERITY_TO_LEVEL[
static_cast<int>(data_->
severity_)],
1465 return LogDestination::log_destination(severity)->logger_;
1470 LogDestination::log_destination(severity)->logger_ = logger;
1476 return num_messages_[severity];
1488 <<
"You must not use COUNTER with non-glog ostream";
1528 const struct ::tm* tm_time,
const char*
message,
1529 size_t message_len) {
1530 ostringstream stream(
string(
message, message_len));
1540 << setw(2) << tm_time->tm_mday <<
' ' << setw(2) << tm_time->tm_hour
1541 <<
':' << setw(2) << tm_time->tm_min <<
':' << setw(2)
1542 << tm_time->tm_sec <<
'.' << setw(6) << usecs <<
' ' << setfill(
' ')
1544 <<
':' << line <<
"] ";
1546 stream << string(
message, message_len);
1547 return stream.str();
1598 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1599 "abcdefghijklmnopqrstuvwxyz"
1600 "0123456789+-_.=/:,@";
1608 }
else if (src.find_first_of(
'\'') == string::npos) {
1615 result.assign(
"\"");
1616 for (
size_t i = 0; i < src.size(); ++i) {
1622 result.append(
"\\");
1624 result.append(src, i, 1);
1626 result.append(
"\"");
1641 if (GetTempPathA(MAX_PATH, tmp)) list->push_back(tmp);
1642 list->push_back(
"C:\\tmp\\");
1643 list->push_back(
"C:\\temp\\");
1647 const char* candidates[] = {
1649 getenv(
"TEST_TMPDIR"),
1659 for (
size_t i = 0; i < ABSL_ARRAYSIZE(candidates); i++) {
1660 const char* d = candidates[i];
1665 if (dstr[dstr.size() - 1] !=
'/') {
1668 list->push_back(dstr);
1670 struct stat statbuf;
1671 if (!stat(d, &statbuf) && S_ISDIR(statbuf.st_mode)) {
1687 if (!absl::GetFlag(FLAGS_log_dir).empty()) {
1694 if (GetWindowsDirectoryA(tmp, MAX_PATH))
1707 "TestOnly_ClearLoggingDirectoriesList should only be "
1708 "called from test code.\n");
1715 vector<string>::iterator i_dir = list->begin();
1716 while (i_dir != list->end()) {
1719 if (access(i_dir->c_str(), 0)) {
1720 i_dir = list->erase(i_dir);
1728 #define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
1729 string* Check##func##expected##Impl(const char* s1, const char* s2, \
1730 const char* names) { \
1731 bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
1732 if (equal == expected) { \
1738 ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
1739 return new string(ss.str()); \
1746 #undef DEFINE_CHECK_STROP_IMPL
1750 if (buf == NULL || len <= 0) {
1758 int old_errno = errno;
1760 char* rc =
reinterpret_cast<char*
>(strerror_r(err, buf, len));
1774 buf[len - 1] =
'\000';
1786 #if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
1787 if (
reinterpret_cast<intptr_t
>(rc) < sys_nerr) {
1792 strncat(buf, rc, len - 1);
1801 if ((rc < 0) || (buf[0] ==
'\000')) {
1802 snprintf(buf,
sizeof(buf),
"Error number %d", err);
1822 : stream_(new ostringstream) {
1823 *stream_ << exprtext <<
" (";
1829 *stream_ <<
" vs. ";
1835 return new string(stream_->str());
1842 if (v >= 32 && v <= 126) {
1843 (*os) <<
"'" << v <<
"'";
1845 (*os) <<
"char value " << (
int16)v;
1851 if (v >= 32 && v <= 126) {
1852 (*os) <<
"'" << v <<
"'";
1854 (*os) <<
"signed char value " << (
int16)v;
1860 if (v >= 32 && v <= 126) {
1861 (*os) <<
"'" << v <<
"'";
1863 (*os) <<
"unsigned char value " << (
uint16)v;