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*/