1 //===-- sanitizer_file.cc ------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===---------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries. It defines filesystem-related interfaces. This
10 // is separate from sanitizer_common.cc so that it's simpler to disable
11 // all the filesystem support code for a port that doesn't use it.
13 //===---------------------------------------------------------------------===//
15 #include "sanitizer_platform.h"
17 #if !SANITIZER_FUCHSIA
19 #include "sanitizer_common.h"
20 #include "sanitizer_file.h"
22 namespace __sanitizer
{
24 void CatastrophicErrorWrite(const char *buffer
, uptr length
) {
25 WriteToFile(kStderrFd
, buffer
, length
);
28 StaticSpinMutex report_file_mu
;
29 ReportFile report_file
= {&report_file_mu
, kStderrFd
, "", "", 0};
31 void RawWrite(const char *buffer
) {
32 report_file
.Write(buffer
, internal_strlen(buffer
));
35 void ReportFile::ReopenIfNecessary() {
37 if (fd
== kStdoutFd
|| fd
== kStderrFd
) return;
39 uptr pid
= internal_getpid();
40 // If in tracer, use the parent's file.
41 if (pid
== stoptheworld_tracer_pid
)
42 pid
= stoptheworld_tracer_ppid
;
43 if (fd
!= kInvalidFd
) {
44 // If the report file is already opened by the current process,
45 // do nothing. Otherwise the report file was opened by the parent
46 // process, close it now.
53 const char *exe_name
= GetProcessName();
54 if (common_flags()->log_exe_name
&& exe_name
) {
55 internal_snprintf(full_path
, kMaxPathLength
, "%s.%s.%zu", path_prefix
,
58 internal_snprintf(full_path
, kMaxPathLength
, "%s.%zu", path_prefix
, pid
);
60 fd
= OpenFile(full_path
, WrOnly
);
61 if (fd
== kInvalidFd
) {
62 const char *ErrorMsgPrefix
= "ERROR: Can't open file: ";
63 WriteToFile(kStderrFd
, ErrorMsgPrefix
, internal_strlen(ErrorMsgPrefix
));
64 WriteToFile(kStderrFd
, full_path
, internal_strlen(full_path
));
70 void ReportFile::SetReportPath(const char *path
) {
73 uptr len
= internal_strlen(path
);
74 if (len
> sizeof(path_prefix
) - 100) {
75 Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
76 path
[0], path
[1], path
[2], path
[3],
77 path
[4], path
[5], path
[6], path
[7]);
82 if (fd
!= kStdoutFd
&& fd
!= kStderrFd
&& fd
!= kInvalidFd
)
85 if (internal_strcmp(path
, "stdout") == 0) {
87 } else if (internal_strcmp(path
, "stderr") == 0) {
90 internal_snprintf(path_prefix
, kMaxPathLength
, "%s", path
);
94 bool ReadFileToBuffer(const char *file_name
, char **buff
, uptr
*buff_size
,
95 uptr
*read_len
, uptr max_len
, error_t
*errno_p
) {
96 uptr PageSize
= GetPageSizeCached();
97 uptr kMinFileLen
= PageSize
;
101 // The files we usually open are not seekable, so try different buffer sizes.
102 for (uptr size
= kMinFileLen
; size
<= max_len
; size
*= 2) {
103 fd_t fd
= OpenFile(file_name
, RdOnly
, errno_p
);
104 if (fd
== kInvalidFd
) return false;
105 UnmapOrDie(*buff
, *buff_size
);
106 *buff
= (char*)MmapOrDie(size
, __func__
);
109 // Read up to one page at a time.
110 bool reached_eof
= false;
111 while (*read_len
+ PageSize
<= size
) {
113 if (!ReadFromFile(fd
, *buff
+ *read_len
, PageSize
, &just_read
, errno_p
)) {
114 UnmapOrDie(*buff
, *buff_size
);
117 if (just_read
== 0) {
121 *read_len
+= just_read
;
124 if (reached_eof
) // We've read the whole file.
130 static const char kPathSeparator
= SANITIZER_WINDOWS
? ';' : ':';
132 char *FindPathToBinary(const char *name
) {
133 if (FileExists(name
)) {
134 return internal_strdup(name
);
137 const char *path
= GetEnv("PATH");
140 uptr name_len
= internal_strlen(name
);
141 InternalScopedBuffer
<char> buffer(kMaxPathLength
);
142 const char *beg
= path
;
144 const char *end
= internal_strchrnul(beg
, kPathSeparator
);
145 uptr prefix_len
= end
- beg
;
146 if (prefix_len
+ name_len
+ 2 <= kMaxPathLength
) {
147 internal_memcpy(buffer
.data(), beg
, prefix_len
);
148 buffer
[prefix_len
] = '/';
149 internal_memcpy(&buffer
[prefix_len
+ 1], name
, name_len
);
150 buffer
[prefix_len
+ 1 + name_len
] = '\0';
151 if (FileExists(buffer
.data()))
152 return internal_strdup(buffer
.data());
154 if (*end
== '\0') break;
160 } // namespace __sanitizer
162 using namespace __sanitizer
; // NOLINT
165 void __sanitizer_set_report_path(const char *path
) {
166 report_file
.SetReportPath(path
);
169 void __sanitizer_set_report_fd(void *fd
) {
170 report_file
.fd
= (fd_t
)reinterpret_cast<uptr
>(fd
);
171 report_file
.fd_pid
= internal_getpid();
175 #endif // !SANITIZER_FUCHSIA