ninja_build/utils.rs
1// Copyright 2011 Google Inc. All Rights Reserved.
2// Copyright 2017 The Ninja-rs Project Developers. All Rights Reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std;
17use libc;
18use libc_stdhandle;
19use errno;
20use num_cpus;
21use std::path::PathBuf;
22use std::ffi::OsString;
23
24/// The primary interface to metrics. Use METRIC_RECORD("foobar") at the top
25/// of a function to get timing stats recorded for each call of the function.
26macro_rules! metric_record {
27 ($metric: expr) => {
28 metric_record!($metric, METRIC_VAR, metric_borrow);
29 };
30 ($metric: expr, $metric_var: ident, $metric_borrow: ident) => {
31 lazy_static! {
32 static ref $metric_var :
33 Option<::std::sync::Arc<::std::sync::Mutex<$crate::metrics::Metric>>> =
34 $crate::debug_flags::METRICS.as_ref()
35 .map(|m| m.lock().unwrap().new_metric($metric));
36 }
37 let mut $metric_borrow = $metric_var.as_ref().map(|r| r.lock().unwrap());
38 let _ = $crate::metrics::ScopedMetric::new($metric_borrow.as_mut().map(|r| &mut **r));
39 };
40}
41
42#[macro_export]
43macro_rules! explain {
44 ($fmt:expr) =>
45 (if $crate::debug_flags::EXPLAINING {
46 eprint!(concat!("ninja explain: ", $fmt, "\n"))
47 });
48 ($fmt:expr, $($arg:tt)*) =>
49 (if $crate::debug_flags::EXPLAINING {
50 eprint!(concat!("ninja explain: ", $fmt, "\n"), $($arg)*)
51 });
52}
53
54/// Log a fatal message and exit.
55#[macro_export]
56macro_rules! fatal {
57 ($fmt:expr) =>
58 ({
59 eprint!(concat!("ninja fatal: ", $fmt, "\n"));
60 $crate::utils::exit();
61 });
62 ($fmt:expr, $($arg:tt)*) =>
63 ({
64 eprint!(concat!("ninja fatal: ", $fmt, "\n"), $($arg)*);
65 $crate::utils::exit();
66 });
67}
68
69/// Log a warning message.
70#[macro_export]
71macro_rules! warning {
72 ($fmt:expr) =>
73 (eprint!(concat!("ninja warning: ", $fmt, "\n")));
74 ($fmt:expr, $($arg:tt)*) =>
75 (eprint!(concat!("ninja warning: ", $fmt, "\n"), $($arg)*));
76}
77
78/// Log an error message.
79#[macro_export]
80macro_rules! error {
81 ($fmt:expr) =>
82 (eprint!(concat!("ninja error: ", $fmt, "\n")));
83 ($fmt:expr, $($arg:tt)*) =>
84 (eprint!(concat!("ninja error: ", $fmt, "\n"), $($arg)*));
85}
86
87#[cfg(windows)]
88pub fn exit() -> ! {
89 use kernel32;
90 use std::io::Write;
91
92 // On Windows, some tools may inject extra threads.
93 // exit() may block on locks held by those threads, so forcibly exit.
94 let _ = std::io::stderr().flush();
95 let _ = std::io::stdout().flush();
96 unsafe {
97 kernel32::ExitProcess(1);
98 }
99 unreachable!()
100}
101
102#[cfg(not(windows))]
103pub fn exit() -> ! {
104 unsafe {
105 libc::exit(1);
106 }
107 unreachable!()
108}
109
110pub trait ZeroOrErrnoResult {
111 fn as_zero_errno_result(self) -> Result<(), errno::Errno>;
112}
113
114impl ZeroOrErrnoResult for libc::c_int {
115 fn as_zero_errno_result(self) -> Result<(), errno::Errno> {
116 if self == 0 {
117 Ok(())
118 } else {
119 Err(errno::errno())
120 }
121 }
122}
123
124
125pub fn set_stdout_linebuffered() {
126 unsafe {
127 libc::setvbuf(
128 libc_stdhandle::stdout(),
129 std::ptr::null_mut(),
130 libc::_IOLBF,
131 libc::BUFSIZ as _,
132 );
133 }
134}
135
136pub fn get_processor_count() -> usize {
137 num_cpus::get()
138}
139
140#[cfg(unix)]
141fn pathbuf_from_bytes_os(bytes: Vec<u8>) -> Result<PathBuf, Vec<u8>> {
142 use std::os::unix::ffi::OsStringExt;
143
144 Ok(PathBuf::from(OsString::from_vec(bytes)))
145}
146
147#[cfg(not(unix))]
148fn pathbuf_from_bytes_os(bytes: Vec<u8>) -> Result<PathBuf, Vec<u8>> {
149 Err(bytes)
150}
151
152pub fn pathbuf_from_bytes(mut bytes: Vec<u8>) -> Result<PathBuf, Vec<u8>> {
153 bytes = match String::from_utf8(bytes) {
154 Ok(r) => {
155 return Ok(PathBuf::from(r));
156 }
157 Err(e) => e.into_bytes(),
158 };
159 return pathbuf_from_bytes_os(bytes);
160}
161
162pub trait RangeContains<T> {
163 fn contains_stable(&self, item: T) -> bool;
164}
165
166impl<Idx: PartialOrd<Idx>> RangeContains<Idx> for std::ops::Range<Idx> {
167 fn contains_stable(&self, item: Idx) -> bool {
168 (self.start <= item) && (item < self.end)
169 }
170}
171/*
172
173/// Canonicalize a path like "foo/../bar.h" into just "bar.h".
174/// |slash_bits| has bits set starting from lowest for a backslash that was
175/// normalized to a forward slash. (only used on Windows)
176bool CanonicalizePath(string* path, uint64_t* slash_bits, string* err);
177bool CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits,
178 string* err);
179
180/// Appends |input| to |*result|, escaping according to the whims of either
181/// Bash, or Win32's CommandLineToArgvW().
182/// Appends the string directly to |result| without modification if we can
183/// determine that it contains no problematic characters.
184void GetShellEscapedString(const string& input, string* result);
185void GetWin32EscapedString(const string& input, string* result);
186
187/// Read a file to a string (in text mode: with CRLF conversion
188/// on Windows).
189/// Returns -errno and fills in \a err on error.
190int ReadFile(const string& path, string* contents, string* err);
191*/
192
193/// Mark a file descriptor to not be inherited on exec()s.
194#[cfg(unix)]
195pub fn set_close_on_exec(fd: ::libc::c_int) {
196 use libc;
197 use errno;
198
199 unsafe {
200 let flags = libc::fcntl(fd, libc::F_GETFD);
201 if flags < 0 {
202 fatal!("fcntl(F_GETFD): {}", errno::errno());
203 }
204 if libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC) < 0 {
205 fatal!("fcntl(F_SETFD): {}", errno::errno());
206 }
207 }
208}
209
210/*
211/// Given a misspelled string and a list of correct spellings, returns
212/// the closest match or NULL if there is no close enough match.
213const char* SpellcheckStringV(const string& text,
214 const vector<const char*>& words);
215
216/// Like SpellcheckStringV, but takes a NULL-terminated list.
217const char* SpellcheckString(const char* text, ...);
218
219bool islatinalpha(int c);
220
221/// Removes all Ansi escape codes (http://www.termsys.demon.co.uk/vtansi.htm).
222string StripAnsiEscapeCodes(const string& in);
223
224/// @return the number of processors on the machine. Useful for an initial
225/// guess for how many jobs to run in parallel. @return 0 on error.
226int GetProcessorCount();
227
228/// @return the load average of the machine. A negative value is returned
229/// on error.
230double GetLoadAverage();
231
232/// Elide the given string @a str with '...' in the middle if the length
233/// exceeds @a width.
234string ElideMiddle(const string& str, size_t width);
235
236/// Truncates a file to the given size.
237bool Truncate(const string& path, size_t size, string* err);
238
239#ifdef _MSC_VER
240#define snprintf _snprintf
241#define fileno _fileno
242#define unlink _unlink
243#define chdir _chdir
244#define strtoull _strtoui64
245#define getcwd _getcwd
246#define PATH_MAX _MAX_PATH
247#endif
248
249#ifdef _WIN32
250/// Convert the value returned by GetLastError() into a string.
251string GetLastErrorString();
252
253/// Calls Fatal() with a function name and GetLastErrorString.
254NORETURN void Win32Fatal(const char* function);
255#endif
256
257
258#include "util.h"
259
260#ifdef __CYGWIN__
261#include <windows.h>
262#include <io.h>
263#elif defined( _WIN32)
264#include <windows.h>
265#include <io.h>
266#include <share.h>
267#endif
268
269#include <assert.h>
270#include <errno.h>
271#include <fcntl.h>c
272#include <stdarg.h>
273#include <stdio.h>
274#include <stdlib.h>
275#include <string.h>
276#include <sys/stat.h>
277#include <sys/types.h>
278
279#ifndef _WIN32
280#include <unistd.h>
281#include <sys/time.h>
282#endif
283
284#include <vector>
285
286#if defined(__APPLE__) || defined(__FreeBSD__)
287#include <sys/sysctl.h>
288#elif defined(__SVR4) && defined(__sun)
289#include <unistd.h>
290#include <sys/loadavg.h>
291#elif defined(_AIX)
292#include <libperfstat.h>
293#elif defined(linux) || defined(__GLIBC__)
294#include <sys/sysinfo.h>
295#endif
296
297#include "edit_distance.h"
298#include "metrics.h"
299*/
300
301/*
302static bool IsPathSeparator(char c) {
303#ifdef _WIN32
304 return c == '/' || c == '\\';
305#else
306 return c == '/';
307#endif
308}
309*/
310
311#[cfg(windows)]
312pub const WINDOWS_PATH: bool = true;
313#[cfg(not(windows))]
314pub const WINDOWS_PATH: bool = false;
315
316fn is_path_separator(c: u8) -> bool {
317 c == b'/' || WINDOWS_PATH && c == b'\\'
318}
319
320
321pub fn canonicalize_path(path: &mut Vec<u8>) -> Result<u64, String> {
322 metric_record!("canonicalize str");
323 let (newsize, slash_bits) = canonicalize_path_slice(path.as_mut_slice())?;
324 path.truncate(newsize);
325 Ok(slash_bits)
326}
327
328pub fn canonicalize_path_slice(path: &mut [u8]) -> Result<(usize, u64), String> {
329 // WARNING: this function is performance-critical; please benchmark
330 // any changes you make to it.
331 metric_record!("canonicalize path");
332 if path.is_empty() {
333 return Err("empty path".to_owned());
334 }
335
336 const MAX_PATH_COMPONENTS: usize = 60usize;
337 let mut components = [0usize; MAX_PATH_COMPONENTS];
338 let mut component_count = 0usize;
339
340 let len = path.len();
341
342 let start = 0;
343 let end = len;
344 let mut dst = 0;
345 let mut src = 0;
346
347 if is_path_separator(path[0]) {
348 if WINDOWS_PATH && len >= 2 && is_path_separator(path[1]) {
349 src += 1;
350 dst += 1;
351 }
352 src += 1;
353 dst += 1;
354 }
355
356 while src < end {
357 if path[src] == b'.' && (src + 1 == end || is_path_separator(path[src + 1])) {
358 // '.' component; eliminate.
359 src += 2;
360 } else if path[src] == b'.' && path[src + 1] == b'.' &&
361 (src + 2 == end || is_path_separator(path[src + 2]))
362 {
363 if component_count == 0 {
364 path[dst] = path[src];
365 path[dst + 1] = path[src + 1];
366 path[dst + 2] = path[src + 2];
367 dst += 3;
368 } else {
369 dst = components[component_count - 1];
370 component_count -= 1;
371 }
372 src += 3;
373 } else if is_path_separator(path[src]) {
374 src += 1;
375 } else {
376 if component_count == MAX_PATH_COMPONENTS {
377 fatal!(
378 "path has too many components : {}",
379 String::from_utf8_lossy(path)
380 );
381 }
382
383 components[component_count] = dst;
384 component_count += 1;
385
386 while {
387 path[dst] = path[src];
388 dst += 1;
389 src += 1;
390 src < end && !is_path_separator(path[dst - 1])
391 }
392 {}
393 }
394 }
395
396 if dst == start {
397 path[dst] = b'.';
398 dst += 1;
399 }
400
401 let new_len = dst - start;
402 let mut slash_bits = 0u64;
403 if WINDOWS_PATH {
404 let mut mask = 1u64;
405 for i in 0..new_len {
406 if path[i] == b'\\' {
407 slash_bits |= mask;
408 path[i] = b'/';
409 mask <<= 1;
410 } else if path[i] == b'/' {
411 mask <<= 1;
412 }
413 }
414 }
415 Ok((new_len, slash_bits))
416}
417
418
419// static
420pub fn decanonicalize_path(path: &[u8], slash_bits: u64) -> Vec<u8> {
421 let mut result = path.to_owned();
422 if WINDOWS_PATH {
423 let mut mask = 1u64;
424 for c in result.iter_mut().filter(|c| **c == b'/') {
425 if (slash_bits & mask) != 0 {
426 *c = b'\\';
427 }
428 mask <<= 1;
429 }
430 }
431 result
432}
433
434pub trait ExtendFromEscapedSlice<T> {
435 fn extend_from_shell_escaped_slice(&mut self, other: &[T]);
436 fn extend_from_win32_escaped_slice(&mut self, other: &[T]);
437}
438
439#[inline]
440fn is_known_shell_safe_character(ch: u8) -> bool {
441 match ch {
442 b'A'...b'Z' => true,
443 b'a'...b'z' => true,
444 b'0'...b'9' => true,
445 b'_' | b'+' | b'-' | b'.' | b'/' => true,
446 _ => false,
447 }
448}
449
450#[inline]
451fn is_known_win32_safe_char(ch: u8) -> bool {
452 match ch {
453 b' ' | b'"' => false,
454 _ => true,
455 }
456}
457
458#[inline]
459fn slice_needs_shell_escaping(input: &[u8]) -> bool {
460 !input.iter().cloned().all(is_known_shell_safe_character)
461}
462
463#[inline]
464fn slice_needs_win32_escaping(input: &[u8]) -> bool {
465 !input.iter().cloned().all(is_known_win32_safe_char)
466}
467
468impl ExtendFromEscapedSlice<u8> for Vec<u8> {
469 fn extend_from_shell_escaped_slice(&mut self, input: &[u8]) {
470 if !slice_needs_shell_escaping(input) {
471 self.extend_from_slice(input);
472 return;
473 }
474 unimplemented!()
475/*
476 const char kQuote = '\'';
477 const char kEscapeSequence[] = "'\\'";
478
479 result->push_back(kQuote);
480
481 string::const_iterator span_begin = input.begin();
482 for (string::const_iterator it = input.begin(), end = input.end(); it != end;
483 ++it) {
484 if (*it == kQuote) {
485 result->append(span_begin, it);
486 result->append(kEscapeSequence);
487 span_begin = it;
488 }
489 }
490 result->append(span_begin, input.end());
491 result->push_back(kQuote);
492*/
493
494 }
495 fn extend_from_win32_escaped_slice(&mut self, input: &[u8]) {
496 if !slice_needs_win32_escaping(input) {
497 self.extend_from_slice(input);
498 return;
499 }
500 /*
501 const char kQuote = '"';
502 const char kBackslash = '\\';
503
504 result->push_back(kQuote);
505 size_t consecutive_backslash_count = 0;
506 string::const_iterator span_begin = input.begin();
507 for (string::const_iterator it = input.begin(), end = input.end(); it != end;
508 ++it) {
509 switch (*it) {
510 case kBackslash:
511 ++consecutive_backslash_count;
512 break;
513 case kQuote:
514 result->append(span_begin, it);
515 result->append(consecutive_backslash_count + 1, kBackslash);
516 span_begin = it;
517 consecutive_backslash_count = 0;
518 break;
519 default:
520 consecutive_backslash_count = 0;
521 break;
522 }
523 }
524 result->append(span_begin, input.end());
525 result->append(consecutive_backslash_count, kBackslash);
526 result->push_back(kQuote);
527*/
528
529
530 unimplemented!()
531 }
532}
533
534/*
535int ReadFile(const string& path, string* contents, string* err) {
536#ifdef _WIN32
537 // This makes a ninja run on a set of 1500 manifest files about 4% faster
538 // than using the generic fopen code below.
539 err->clear();
540 HANDLE f = ::CreateFile(path.c_str(),
541 GENERIC_READ,
542 FILE_SHARE_READ,
543 NULL,
544 OPEN_EXISTING,
545 FILE_FLAG_SEQUENTIAL_SCAN,
546 NULL);
547 if (f == INVALID_HANDLE_VALUE) {
548 err->assign(GetLastErrorString());
549 return -ENOENT;
550 }
551
552 for (;;) {
553 DWORD len;
554 char buf[64 << 10];
555 if (!::ReadFile(f, buf, sizeof(buf), &len, NULL)) {
556 err->assign(GetLastErrorString());
557 contents->clear();
558 return -1;
559 }
560 if (len == 0)
561 break;
562 contents->append(buf, len);
563 }
564 ::CloseHandle(f);
565 return 0;
566#else
567 FILE* f = fopen(path.c_str(), "rb");
568 if (!f) {
569 err->assign(strerror(errno));
570 return -errno;
571 }
572
573 char buf[64 << 10];
574 size_t len;
575 while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
576 contents->append(buf, len);
577 }
578 if (ferror(f)) {
579 err->assign(strerror(errno)); // XXX errno?
580 contents->clear();
581 fclose(f);
582 return -errno;
583 }
584 fclose(f);
585 return 0;
586#endif
587}
588
589void SetCloseOnExec(int fd) {
590#ifndef _WIN32
591 int flags = fcntl(fd, F_GETFD);
592 if (flags < 0) {
593 perror("fcntl(F_GETFD)");
594 } else {
595 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
596 perror("fcntl(F_SETFD)");
597 }
598#else
599 HANDLE hd = (HANDLE) _get_osfhandle(fd);
600 if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
601 fprintf(stderr, "SetHandleInformation(): %s", GetLastErrorString().c_str());
602 }
603#endif // ! _WIN32
604}
605
606
607const char* SpellcheckStringV(const string& text,
608 const vector<const char*>& words) {
609 const bool kAllowReplacements = true;
610 const int kMaxValidEditDistance = 3;
611
612 int min_distance = kMaxValidEditDistance + 1;
613 const char* result = NULL;
614 for (vector<const char*>::const_iterator i = words.begin();
615 i != words.end(); ++i) {
616 int distance = EditDistance(*i, text, kAllowReplacements,
617 kMaxValidEditDistance);
618 if (distance < min_distance) {
619 min_distance = distance;
620 result = *i;
621 }
622 }
623 return result;
624}
625
626const char* SpellcheckString(const char* text, ...) {
627 // Note: This takes a const char* instead of a string& because using
628 // va_start() with a reference parameter is undefined behavior.
629 va_list ap;
630 va_start(ap, text);
631 vector<const char*> words;
632 const char* word;
633 while ((word = va_arg(ap, const char*)))
634 words.push_back(word);
635 va_end(ap);
636 return SpellcheckStringV(text, words);
637}
638
639#ifdef _WIN32
640string GetLastErrorString() {
641 DWORD err = GetLastError();
642
643 char* msg_buf;
644 FormatMessageA(
645 FORMAT_MESSAGE_ALLOCATE_BUFFER |
646 FORMAT_MESSAGE_FROM_SYSTEM |
647 FORMAT_MESSAGE_IGNORE_INSERTS,
648 NULL,
649 err,
650 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
651 (char*)&msg_buf,
652 0,
653 NULL);
654 string msg = msg_buf;
655 LocalFree(msg_buf);
656 return msg;
657}
658
659void Win32Fatal(const char* function) {
660 Fatal("%s: %s", function, GetLastErrorString().c_str());
661}
662#endif
663
664bool islatinalpha(int c) {
665 // isalpha() is locale-dependent.
666 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
667}
668
669string StripAnsiEscapeCodes(const string& in) {
670 string stripped;
671 stripped.reserve(in.size());
672
673 for (size_t i = 0; i < in.size(); ++i) {
674 if (in[i] != '\33') {
675 // Not an escape code.
676 stripped.push_back(in[i]);
677 continue;
678 }
679
680 // Only strip CSIs for now.
681 if (i + 1 >= in.size()) break;
682 if (in[i + 1] != '[') continue; // Not a CSI.
683 i += 2;
684
685 // Skip everything up to and including the next [a-zA-Z].
686 while (i < in.size() && !islatinalpha(in[i]))
687 ++i;
688 }
689 return stripped;
690}
691
692*/
693
694#[cfg(windows)]
695pub fn get_load_average() -> Option<f64> {
696 use std::mem::zeroed;
697 use winapi;
698 use kernel32;
699
700 use winapi::FILETIME;
701
702 fn filetime_to_tickcount(ft: &FILETIME) -> u64 {
703 ((ft.dwHighDateTime as u64) << 32) | (ft.dwLowDateTime as u64)
704 }
705
706 fn calculate_processor_load(idle_ticks: u64, total_ticks: u64) -> Option<f64> {
707 static mut PREVIOUS_IDLE_TICKS: u64 = 0;
708 static mut PREVIOUS_TOTAL_TICKS: u64 = 0;
709 static mut PREVIOUS_LOAD: Option<f64> = None;
710
711 let (previous_idle_ticks, previous_total_ticks, previous_load) =
712 unsafe { (PREVIOUS_IDLE_TICKS, PREVIOUS_TOTAL_TICKS, PREVIOUS_LOAD) };
713
714 let idle_ticks_since_last_time = idle_ticks - previous_idle_ticks;
715 let total_ticks_since_last_time = total_ticks - previous_total_ticks;
716
717 let first_call = previous_total_ticks == 0;
718 let ticks_not_updated_since_last_call = total_ticks_since_last_time == 0;
719
720 let load;
721 if first_call || ticks_not_updated_since_last_call {
722 load = previous_load;
723 } else {
724 // Calculate load.
725 let idle_to_total_ratio = idle_ticks_since_last_time as f64 /
726 total_ticks_since_last_time as f64;
727 let load_since_last_call = 1.0f64 - idle_to_total_ratio;
728
729 // Filter/smooth result when possible.
730 load = Some(if let Some(previous_load) = previous_load {
731 0.9 * previous_load + 0.1 * load_since_last_call
732 } else {
733 load_since_last_call
734 });
735 }
736
737 unsafe {
738 PREVIOUS_LOAD = load;
739 PREVIOUS_TOTAL_TICKS = total_ticks;
740 PREVIOUS_IDLE_TICKS = idle_ticks;
741 }
742
743 load
744 }
745
746 unsafe {
747 let mut idle_time = zeroed::<FILETIME>();
748 let mut kernel_time = zeroed::<FILETIME>();
749 let mut user_time = zeroed::<FILETIME>();
750
751 if kernel32::GetSystemTimes(&mut idle_time, &mut kernel_time, &mut user_time) ==
752 winapi::FALSE
753 {
754 return None;
755 };
756
757 let idle_ticks = filetime_to_tickcount(&idle_time);
758 let total_ticks = filetime_to_tickcount(&kernel_time) + filetime_to_tickcount(&user_time);
759
760 if let Some(processor_load) = calculate_processor_load(idle_ticks, total_ticks) {
761 Some(processor_load * get_processor_count() as f64)
762 } else {
763 None
764 }
765 }
766}
767/*
768double GetLoadAverage() {
769 FILETIME idle_time, kernel_time, user_time;
770 BOOL get_system_time_succeeded =
771 GetSystemTimes(&idle_time, &kernel_time, &user_time);
772
773 double posix_compatible_load;
774 if (get_system_time_succeeded) {
775 uint64_t idle_ticks = FileTimeToTickCount(idle_time);
776
777 // kernel_time from GetSystemTimes already includes idle_time.
778 uint64_t total_ticks =
779 FileTimeToTickCount(kernel_time) + FileTimeToTickCount(user_time);
780
781 double processor_load = CalculateProcessorLoad(idle_ticks, total_ticks);
782 posix_compatible_load = processor_load * GetProcessorCount();
783
784 } else {
785 posix_compatible_load = -0.0;
786 }
787
788 return posix_compatible_load;
789}
790#elif defined(_AIX)
791double GetLoadAverage() {
792 perfstat_cpu_total_t cpu_stats;
793 if (perfstat_cpu_total(NULL, &cpu_stats, sizeof(cpu_stats), 1) < 0) {
794 return -0.0f;
795 }
796
797 // Calculation taken from comment in libperfstats.h
798 return double(cpu_stats.loadavg[0]) / double(1 << SBITS);
799}
800#elif defined(__UCLIBC__)
801double GetLoadAverage() {
802 struct sysinfo si;
803 if (sysinfo(&si) != 0)
804 return -0.0f;
805 return 1.0 / (1 << SI_LOAD_SHIFT) * si.loads[0];
806}
807#else
808*/
809#[cfg(unix)]
810pub fn get_load_average() -> Option<f64> {
811 let mut load_avg: [f64; 3] = [0.0f64, 0.0f64, 0.0f64];
812 unsafe {
813 if libc::getloadavg(load_avg.as_mut_ptr(), 3) < 0 {
814 return None;
815 }
816 }
817 Some(load_avg[0])
818}
819
820/*
821double GetLoadAverage() {
822 double loadavg[3] = { 0.0f, 0.0f, 0.0f };
823 if (getloadavg(loadavg, 3) < 0) {
824 // Maybe we should return an error here or the availability of
825 // getloadavg(3) should be checked when ninja is configured.
826 return -0.0f;
827 }
828 return loadavg[0];
829}
830#endif // _WIN32
831
832string ElideMiddle(const string& str, size_t width) {
833 const int kMargin = 3; // Space for "...".
834 string result = str;
835 if (result.size() + kMargin > width) {
836 size_t elide_size = (width - kMargin) / 2;
837 result = result.substr(0, elide_size)
838 + "..."
839 + result.substr(result.size() - elide_size, elide_size);
840 }
841 return result;
842}
843
844bool Truncate(const string& path, size_t size, string* err) {
845#ifdef _WIN32
846 int fh = _sopen(path.c_str(), _O_RDWR | _O_CREAT, _SH_DENYNO,
847 _S_IREAD | _S_IWRITE);
848 int success = _chsize(fh, size);
849 _close(fh);
850#else
851 int success = truncate(path.c_str(), size);
852#endif
853 // Both truncate() and _chsize() return 0 on success and set errno and return
854 // -1 on failure.
855 if (success < 0) {
856 *err = strerror(errno);
857 return false;
858 }
859 return true;
860}
861
862*/
863
864#[cfg(test)]
865mod tests {
866 use super::*;
867
868 #[test]
869 fn canonicalize_path_path_samples() {
870 struct TestItem {
871 path: &'static [u8],
872 result: &'static [u8],
873 }
874
875 assert_eq!(canonicalize_path(&mut vec![]), Err("empty path".to_owned()));
876
877 let test_items = vec![
878 TestItem {
879 path: b"foo.h",
880 result: b"foo.h",
881 },
882 ];
883
884 for test_item in test_items {
885 let mut path = test_item.path.to_owned();
886 assert!(canonicalize_path(&mut path).is_ok());
887 assert_eq!(path.as_slice(), test_item.result);
888 }
889 }
890
891}
892
893/*
894
895namespace {
896
897bool CanonicalizePath(string* path, string* err) {
898 uint64_t unused;
899 return ::CanonicalizePath(path, &unused, err);
900}
901
902} // namespace
903
904TEST(CanonicalizePath, PathSamples) {
905 string path;
906 string err;
907
908 EXPECT_FALSE(CanonicalizePath(&path, &err));
909 EXPECT_EQ("empty path", err);
910
911 path = "foo.h"; err = "";
912 EXPECT_TRUE(CanonicalizePath(&path, &err));
913 EXPECT_EQ("foo.h", path);
914
915 path = "./foo.h";
916 EXPECT_TRUE(CanonicalizePath(&path, &err));
917 EXPECT_EQ("foo.h", path);
918
919 path = "./foo/./bar.h";
920 EXPECT_TRUE(CanonicalizePath(&path, &err));
921 EXPECT_EQ("foo/bar.h", path);
922
923 path = "./x/foo/../bar.h";
924 EXPECT_TRUE(CanonicalizePath(&path, &err));
925 EXPECT_EQ("x/bar.h", path);
926
927 path = "./x/foo/../../bar.h";
928 EXPECT_TRUE(CanonicalizePath(&path, &err));
929 EXPECT_EQ("bar.h", path);
930
931 path = "foo//bar";
932 EXPECT_TRUE(CanonicalizePath(&path, &err));
933 EXPECT_EQ("foo/bar", path);
934
935 path = "foo//.//..///bar";
936 EXPECT_TRUE(CanonicalizePath(&path, &err));
937 EXPECT_EQ("bar", path);
938
939 path = "./x/../foo/../../bar.h";
940 EXPECT_TRUE(CanonicalizePath(&path, &err));
941 EXPECT_EQ("../bar.h", path);
942
943 path = "foo/./.";
944 EXPECT_TRUE(CanonicalizePath(&path, &err));
945 EXPECT_EQ("foo", path);
946
947 path = "foo/bar/..";
948 EXPECT_TRUE(CanonicalizePath(&path, &err));
949 EXPECT_EQ("foo", path);
950
951 path = "foo/.hidden_bar";
952 EXPECT_TRUE(CanonicalizePath(&path, &err));
953 EXPECT_EQ("foo/.hidden_bar", path);
954
955 path = "/foo";
956 EXPECT_TRUE(CanonicalizePath(&path, &err));
957 EXPECT_EQ("/foo", path);
958
959 path = "//foo";
960 EXPECT_TRUE(CanonicalizePath(&path, &err));
961#ifdef _WIN32
962 EXPECT_EQ("//foo", path);
963#else
964 EXPECT_EQ("/foo", path);
965#endif
966
967 path = "/";
968 EXPECT_TRUE(CanonicalizePath(&path, &err));
969 EXPECT_EQ("", path);
970
971 path = "/foo/..";
972 EXPECT_TRUE(CanonicalizePath(&path, &err));
973 EXPECT_EQ("", path);
974
975 path = ".";
976 EXPECT_TRUE(CanonicalizePath(&path, &err));
977 EXPECT_EQ(".", path);
978
979 path = "./.";
980 EXPECT_TRUE(CanonicalizePath(&path, &err));
981 EXPECT_EQ(".", path);
982
983 path = "foo/..";
984 EXPECT_TRUE(CanonicalizePath(&path, &err));
985 EXPECT_EQ(".", path);
986}
987
988#ifdef _WIN32
989TEST(CanonicalizePath, PathSamplesWindows) {
990 string path;
991 string err;
992
993 EXPECT_FALSE(CanonicalizePath(&path, &err));
994 EXPECT_EQ("empty path", err);
995
996 path = "foo.h"; err = "";
997 EXPECT_TRUE(CanonicalizePath(&path, &err));
998 EXPECT_EQ("foo.h", path);
999
1000 path = ".\\foo.h";
1001 EXPECT_TRUE(CanonicalizePath(&path, &err));
1002 EXPECT_EQ("foo.h", path);
1003
1004 path = ".\\foo\\.\\bar.h";
1005 EXPECT_TRUE(CanonicalizePath(&path, &err));
1006 EXPECT_EQ("foo/bar.h", path);
1007
1008 path = ".\\x\\foo\\..\\bar.h";
1009 EXPECT_TRUE(CanonicalizePath(&path, &err));
1010 EXPECT_EQ("x/bar.h", path);
1011
1012 path = ".\\x\\foo\\..\\..\\bar.h";
1013 EXPECT_TRUE(CanonicalizePath(&path, &err));
1014 EXPECT_EQ("bar.h", path);
1015
1016 path = "foo\\\\bar";
1017 EXPECT_TRUE(CanonicalizePath(&path, &err));
1018 EXPECT_EQ("foo/bar", path);
1019
1020 path = "foo\\\\.\\\\..\\\\\\bar";
1021 EXPECT_TRUE(CanonicalizePath(&path, &err));
1022 EXPECT_EQ("bar", path);
1023
1024 path = ".\\x\\..\\foo\\..\\..\\bar.h";
1025 EXPECT_TRUE(CanonicalizePath(&path, &err));
1026 EXPECT_EQ("../bar.h", path);
1027
1028 path = "foo\\.\\.";
1029 EXPECT_TRUE(CanonicalizePath(&path, &err));
1030 EXPECT_EQ("foo", path);
1031
1032 path = "foo\\bar\\..";
1033 EXPECT_TRUE(CanonicalizePath(&path, &err));
1034 EXPECT_EQ("foo", path);
1035
1036 path = "foo\\.hidden_bar";
1037 EXPECT_TRUE(CanonicalizePath(&path, &err));
1038 EXPECT_EQ("foo/.hidden_bar", path);
1039
1040 path = "\\foo";
1041 EXPECT_TRUE(CanonicalizePath(&path, &err));
1042 EXPECT_EQ("/foo", path);
1043
1044 path = "\\\\foo";
1045 EXPECT_TRUE(CanonicalizePath(&path, &err));
1046 EXPECT_EQ("//foo", path);
1047
1048 path = "\\";
1049 EXPECT_TRUE(CanonicalizePath(&path, &err));
1050 EXPECT_EQ("", path);
1051}
1052
1053TEST(CanonicalizePath, SlashTracking) {
1054 string path;
1055 string err;
1056 uint64_t slash_bits;
1057
1058 path = "foo.h"; err = "";
1059 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1060 EXPECT_EQ("foo.h", path);
1061 EXPECT_EQ(0, slash_bits);
1062
1063 path = "a\\foo.h";
1064 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1065 EXPECT_EQ("a/foo.h", path);
1066 EXPECT_EQ(1, slash_bits);
1067
1068 path = "a/bcd/efh\\foo.h";
1069 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1070 EXPECT_EQ("a/bcd/efh/foo.h", path);
1071 EXPECT_EQ(4, slash_bits);
1072
1073 path = "a\\bcd/efh\\foo.h";
1074 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1075 EXPECT_EQ("a/bcd/efh/foo.h", path);
1076 EXPECT_EQ(5, slash_bits);
1077
1078 path = "a\\bcd\\efh\\foo.h";
1079 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1080 EXPECT_EQ("a/bcd/efh/foo.h", path);
1081 EXPECT_EQ(7, slash_bits);
1082
1083 path = "a/bcd/efh/foo.h";
1084 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1085 EXPECT_EQ("a/bcd/efh/foo.h", path);
1086 EXPECT_EQ(0, slash_bits);
1087
1088 path = "a\\./efh\\foo.h";
1089 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1090 EXPECT_EQ("a/efh/foo.h", path);
1091 EXPECT_EQ(3, slash_bits);
1092
1093 path = "a\\../efh\\foo.h";
1094 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1095 EXPECT_EQ("efh/foo.h", path);
1096 EXPECT_EQ(1, slash_bits);
1097
1098 path = "a\\b\\c\\d\\e\\f\\g\\foo.h";
1099 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1100 EXPECT_EQ("a/b/c/d/e/f/g/foo.h", path);
1101 EXPECT_EQ(127, slash_bits);
1102
1103 path = "a\\b\\c\\..\\..\\..\\g\\foo.h";
1104 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1105 EXPECT_EQ("g/foo.h", path);
1106 EXPECT_EQ(1, slash_bits);
1107
1108 path = "a\\b/c\\../../..\\g\\foo.h";
1109 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1110 EXPECT_EQ("g/foo.h", path);
1111 EXPECT_EQ(1, slash_bits);
1112
1113 path = "a\\b/c\\./../..\\g\\foo.h";
1114 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1115 EXPECT_EQ("a/g/foo.h", path);
1116 EXPECT_EQ(3, slash_bits);
1117
1118 path = "a\\b/c\\./../..\\g/foo.h";
1119 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1120 EXPECT_EQ("a/g/foo.h", path);
1121 EXPECT_EQ(1, slash_bits);
1122
1123 path = "a\\\\\\foo.h";
1124 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1125 EXPECT_EQ("a/foo.h", path);
1126 EXPECT_EQ(1, slash_bits);
1127
1128 path = "a/\\\\foo.h";
1129 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1130 EXPECT_EQ("a/foo.h", path);
1131 EXPECT_EQ(0, slash_bits);
1132
1133 path = "a\\//foo.h";
1134 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1135 EXPECT_EQ("a/foo.h", path);
1136 EXPECT_EQ(1, slash_bits);
1137}
1138
1139TEST(CanonicalizePath, CanonicalizeNotExceedingLen) {
1140 // Make sure searching \/ doesn't go past supplied len.
1141 char buf[] = "foo/bar\\baz.h\\"; // Last \ past end.
1142 uint64_t slash_bits;
1143 string err;
1144 size_t size = 13;
1145 EXPECT_TRUE(::CanonicalizePath(buf, &size, &slash_bits, &err));
1146 EXPECT_EQ(0, strncmp("foo/bar/baz.h", buf, size));
1147 EXPECT_EQ(2, slash_bits); // Not including the trailing one.
1148}
1149
1150TEST(CanonicalizePath, TooManyComponents) {
1151 string path;
1152 string err;
1153 uint64_t slash_bits;
1154
1155 // 64 is OK.
1156 path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./"
1157 "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x.h";
1158 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1159 EXPECT_EQ(slash_bits, 0x0);
1160
1161 // Backslashes version.
1162 path =
1163 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
1164 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
1165 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
1166 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x.h";
1167
1168 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1169 EXPECT_EQ(slash_bits, 0xffffffff);
1170
1171 // 65 is OK if #component is less than 60 after path canonicalization.
1172 err = "";
1173 path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./"
1174 "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x/y.h";
1175 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1176 EXPECT_EQ(slash_bits, 0x0);
1177
1178 // Backslashes version.
1179 err = "";
1180 path =
1181 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
1182 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
1183 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\"
1184 "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x\\y.h";
1185 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1186 EXPECT_EQ(slash_bits, 0x1ffffffff);
1187
1188
1189 // 59 after canonicalization is OK.
1190 err = "";
1191 path = "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/"
1192 "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/x/y.h";
1193 EXPECT_EQ(58, std::count(path.begin(), path.end(), '/'));
1194 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1195 EXPECT_EQ(slash_bits, 0x0);
1196
1197 // Backslashes version.
1198 err = "";
1199 path =
1200 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
1201 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
1202 "a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\a\\"
1203 "a\\a\\a\\a\\a\\a\\a\\a\\a\\x\\y.h";
1204 EXPECT_EQ(58, std::count(path.begin(), path.end(), '\\'));
1205 EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err));
1206 EXPECT_EQ(slash_bits, 0x3ffffffffffffff);
1207}
1208#endif
1209
1210TEST(CanonicalizePath, UpDir) {
1211 string path, err;
1212 path = "../../foo/bar.h";
1213 EXPECT_TRUE(CanonicalizePath(&path, &err));
1214 EXPECT_EQ("../../foo/bar.h", path);
1215
1216 path = "test/../../foo/bar.h";
1217 EXPECT_TRUE(CanonicalizePath(&path, &err));
1218 EXPECT_EQ("../foo/bar.h", path);
1219}
1220
1221TEST(CanonicalizePath, AbsolutePath) {
1222 string path = "/usr/include/stdio.h";
1223 string err;
1224 EXPECT_TRUE(CanonicalizePath(&path, &err));
1225 EXPECT_EQ("/usr/include/stdio.h", path);
1226}
1227
1228TEST(CanonicalizePath, NotNullTerminated) {
1229 string path;
1230 string err;
1231 size_t len;
1232 uint64_t unused;
1233
1234 path = "foo/. bar/.";
1235 len = strlen("foo/."); // Canonicalize only the part before the space.
1236 EXPECT_TRUE(CanonicalizePath(&path[0], &len, &unused, &err));
1237 EXPECT_EQ(strlen("foo"), len);
1238 EXPECT_EQ("foo/. bar/.", string(path));
1239
1240 path = "foo/../file bar/.";
1241 len = strlen("foo/../file");
1242 EXPECT_TRUE(CanonicalizePath(&path[0], &len, &unused, &err));
1243 EXPECT_EQ(strlen("file"), len);
1244 EXPECT_EQ("file ./file bar/.", string(path));
1245}
1246
1247TEST(PathEscaping, TortureTest) {
1248 string result;
1249
1250 GetWin32EscapedString("foo bar\\\"'$@d!st!c'\\path'\\", &result);
1251 EXPECT_EQ("\"foo bar\\\\\\\"'$@d!st!c'\\path'\\\\\"", result);
1252 result.clear();
1253
1254 GetShellEscapedString("foo bar\"/'$@d!st!c'/path'", &result);
1255 EXPECT_EQ("'foo bar\"/'\\''$@d!st!c'\\''/path'\\'''", result);
1256}
1257
1258TEST(PathEscaping, SensiblePathsAreNotNeedlesslyEscaped) {
1259 const char* path = "some/sensible/path/without/crazy/characters.c++";
1260 string result;
1261
1262 GetWin32EscapedString(path, &result);
1263 EXPECT_EQ(path, result);
1264 result.clear();
1265
1266 GetShellEscapedString(path, &result);
1267 EXPECT_EQ(path, result);
1268}
1269
1270TEST(PathEscaping, SensibleWin32PathsAreNotNeedlesslyEscaped) {
1271 const char* path = "some\\sensible\\path\\without\\crazy\\characters.c++";
1272 string result;
1273
1274 GetWin32EscapedString(path, &result);
1275 EXPECT_EQ(path, result);
1276}
1277
1278TEST(StripAnsiEscapeCodes, EscapeAtEnd) {
1279 string stripped = StripAnsiEscapeCodes("foo\33");
1280 EXPECT_EQ("foo", stripped);
1281
1282 stripped = StripAnsiEscapeCodes("foo\33[");
1283 EXPECT_EQ("foo", stripped);
1284}
1285
1286TEST(StripAnsiEscapeCodes, StripColors) {
1287 // An actual clang warning.
1288 string input = "\33[1maffixmgr.cxx:286:15: \33[0m\33[0;1;35mwarning: "
1289 "\33[0m\33[1musing the result... [-Wparentheses]\33[0m";
1290 string stripped = StripAnsiEscapeCodes(input);
1291 EXPECT_EQ("affixmgr.cxx:286:15: warning: using the result... [-Wparentheses]",
1292 stripped);
1293}
1294
1295TEST(ElideMiddle, NothingToElide) {
1296 string input = "Nothing to elide in this short string.";
1297 EXPECT_EQ(input, ElideMiddle(input, 80));
1298}
1299
1300TEST(ElideMiddle, ElideInTheMiddle) {
1301 string input = "01234567890123456789";
1302 string elided = ElideMiddle(input, 10);
1303 EXPECT_EQ("012...789", elided);
1304}
1305*/