Ninja
util.cc
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util.h"
16 
17 #ifdef __CYGWIN__
18 #include <windows.h>
19 #include <io.h>
20 #elif defined( _WIN32)
21 #include <windows.h>
22 #include <io.h>
23 #include <share.h>
24 #include <direct.h>
25 #endif
26 
27 #include <assert.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 
37 #ifndef _WIN32
38 #include <unistd.h>
39 #include <sys/time.h>
40 #endif
41 
42 #include <algorithm>
43 #include <vector>
44 
45 #if defined(__APPLE__) || defined(__FreeBSD__)
46 #include <sys/sysctl.h>
47 #elif defined(__SVR4) && defined(__sun)
48 #include <unistd.h>
49 #include <sys/loadavg.h>
50 #elif defined(_AIX) && !defined(__PASE__)
51 #include <libperfstat.h>
52 #elif defined(__linux__) || defined(__GLIBC__)
53 #include <sys/sysinfo.h>
54 #include <fstream>
55 #include <map>
56 #include "string_piece_util.h"
57 #endif
58 
59 #if defined(__FreeBSD__)
60 #include <sys/cpuset.h>
61 #endif
62 
63 #include "edit_distance.h"
64 
65 using namespace std;
66 
67 void Fatal(const char* msg, ...) {
68  va_list ap;
69  fprintf(stderr, "ninja: fatal: ");
70  va_start(ap, msg);
71  vfprintf(stderr, msg, ap);
72  va_end(ap);
73  fprintf(stderr, "\n");
74 #ifdef _WIN32
75  // On Windows, some tools may inject extra threads.
76  // exit() may block on locks held by those threads, so forcibly exit.
77  fflush(stderr);
78  fflush(stdout);
79  ExitProcess(1);
80 #else
81  exit(1);
82 #endif
83 }
84 
85 void Warning(const char* msg, va_list ap) {
86  fprintf(stderr, "ninja: warning: ");
87  vfprintf(stderr, msg, ap);
88  fprintf(stderr, "\n");
89 }
90 
91 void Warning(const char* msg, ...) {
92  va_list ap;
93  va_start(ap, msg);
94  Warning(msg, ap);
95  va_end(ap);
96 }
97 
98 void Error(const char* msg, va_list ap) {
99  fprintf(stderr, "ninja: error: ");
100  vfprintf(stderr, msg, ap);
101  fprintf(stderr, "\n");
102 }
103 
104 void Error(const char* msg, ...) {
105  va_list ap;
106  va_start(ap, msg);
107  Error(msg, ap);
108  va_end(ap);
109 }
110 
111 void Info(const char* msg, va_list ap) {
112  fprintf(stdout, "ninja: ");
113  vfprintf(stdout, msg, ap);
114  fprintf(stdout, "\n");
115 }
116 
117 void Info(const char* msg, ...) {
118  va_list ap;
119  va_start(ap, msg);
120  Info(msg, ap);
121  va_end(ap);
122 }
123 
124 void CanonicalizePath(string* path, uint64_t* slash_bits) {
125  size_t len = path->size();
126  char* str = 0;
127  if (len > 0)
128  str = &(*path)[0];
129  CanonicalizePath(str, &len, slash_bits);
130  path->resize(len);
131 }
132 
133 static bool IsPathSeparator(char c) {
134 #ifdef _WIN32
135  return c == '/' || c == '\\';
136 #else
137  return c == '/';
138 #endif
139 }
140 
141 void CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits) {
142  // WARNING: this function is performance-critical; please benchmark
143  // any changes you make to it.
144  if (*len == 0) {
145  return;
146  }
147 
148  char* start = path;
149  char* dst = start;
150  char* dst_start = dst;
151  const char* src = start;
152  const char* end = start + *len;
153  const char* src_next;
154 
155  // For absolute paths, skip the leading directory separator
156  // as this one should never be removed from the result.
157  if (IsPathSeparator(*src)) {
158 #ifdef _WIN32
159  // Windows network path starts with //
160  if (src + 2 <= end && IsPathSeparator(src[1])) {
161  src += 2;
162  dst += 2;
163  } else {
164  ++src;
165  ++dst;
166  }
167 #else
168  ++src;
169  ++dst;
170 #endif
171  dst_start = dst;
172  } else {
173  // For relative paths, skip any leading ../ as these are quite common
174  // to reference source files in build plans, and doing this here makes
175  // the loop work below faster in general.
176  while (src + 3 <= end && src[0] == '.' && src[1] == '.' &&
177  IsPathSeparator(src[2])) {
178  src += 3;
179  dst += 3;
180  }
181  }
182 
183  // Loop over all components of the paths _except_ the last one, in
184  // order to simplify the loop's code and make it faster.
185  int component_count = 0;
186  char* dst0 = dst;
187  for (; src < end; src = src_next) {
188 #ifndef _WIN32
189  // Use memchr() for faster lookups thanks to optimized C library
190  // implementation. `hyperfine canon_perftest` shows a significant
191  // difference (e,g, 484ms vs 437ms).
192  const char* next_sep =
193  static_cast<const char*>(::memchr(src, '/', end - src));
194  if (!next_sep) {
195  // This is the last component, will be handled out of the loop.
196  break;
197  }
198 #else
199  // Need to check for both '/' and '\\' so do not use memchr().
200  // Cannot use strpbrk() because end[0] can be \0 or something else!
201  const char* next_sep = src;
202  while (next_sep != end && !IsPathSeparator(*next_sep))
203  ++next_sep;
204  if (next_sep == end) {
205  // This is the last component, will be handled out of the loop.
206  break;
207  }
208 #endif
209  // Position for next loop iteration.
210  src_next = next_sep + 1;
211  // Length of the component, excluding trailing directory.
212  size_t component_len = next_sep - src;
213 
214  if (component_len <= 2) {
215  if (component_len == 0) {
216  continue; // Ignore empty component, e.g. 'foo//bar' -> 'foo/bar'.
217  }
218  if (src[0] == '.') {
219  if (component_len == 1) {
220  continue; // Ignore '.' component, e.g. './foo' -> 'foo'.
221  } else if (src[1] == '.') {
222  // Process the '..' component if found. Back up if possible.
223  if (component_count > 0) {
224  // Move back to start of previous component.
225  --component_count;
226  while (--dst > dst0 && !IsPathSeparator(dst[-1])) {
227  // nothing to do here, decrement happens before condition check.
228  }
229  } else {
230  dst[0] = '.';
231  dst[1] = '.';
232  dst[2] = src[2];
233  dst += 3;
234  }
235  continue;
236  }
237  }
238  }
239  ++component_count;
240 
241  // Copy or skip component, including trailing directory separator.
242  if (dst != src) {
243  ::memmove(dst, src, src_next - src);
244  }
245  dst += src_next - src;
246  }
247 
248  // Handling the last component that does not have a trailing separator.
249  // The logic here is _slightly_ different since there is no trailing
250  // directory separator.
251  size_t component_len = end - src;
252  do {
253  if (component_len == 0)
254  break; // Ignore empty component (e.g. 'foo//' -> 'foo/')
255  if (src[0] == '.') {
256  if (component_len == 1)
257  break; // Ignore trailing '.' (e.g. 'foo/.' -> 'foo/')
258  if (component_len == 2 && src[1] == '.') {
259  // Handle '..'. Back up if possible.
260  if (component_count > 0) {
261  while (--dst > dst0 && !IsPathSeparator(dst[-1])) {
262  // nothing to do here, decrement happens before condition check.
263  }
264  } else {
265  dst[0] = '.';
266  dst[1] = '.';
267  dst += 2;
268  // No separator to add here.
269  }
270  break;
271  }
272  }
273  // Skip or copy last component, no trailing separator.
274  if (dst != src) {
275  ::memmove(dst, src, component_len);
276  }
277  dst += component_len;
278  } while (0);
279 
280  // Remove trailing path separator if any, but keep the initial
281  // path separator(s) if there was one (or two on Windows).
282  if (dst > dst_start && IsPathSeparator(dst[-1]))
283  dst--;
284 
285  if (dst == start) {
286  // Handle special cases like "aa/.." -> "."
287  *dst++ = '.';
288  }
289 
290  *len = dst - start; // dst points after the trailing char here.
291 #ifdef _WIN32
292  uint64_t bits = 0;
293  uint64_t bits_mask = 1;
294 
295  for (char* c = start; c < start + *len; ++c) {
296  switch (*c) {
297  case '\\':
298  bits |= bits_mask;
299  *c = '/';
301  case '/':
302  bits_mask <<= 1;
303  }
304  }
305 
306  *slash_bits = bits;
307 #else
308  *slash_bits = 0;
309 #endif
310 }
311 
312 static inline bool IsKnownShellSafeCharacter(char ch) {
313  if ('A' <= ch && ch <= 'Z') return true;
314  if ('a' <= ch && ch <= 'z') return true;
315  if ('0' <= ch && ch <= '9') return true;
316 
317  switch (ch) {
318  case '_':
319  case '+':
320  case '-':
321  case '.':
322  case '/':
323  return true;
324  default:
325  return false;
326  }
327 }
328 
329 static inline bool IsKnownWin32SafeCharacter(char ch) {
330  switch (ch) {
331  case ' ':
332  case '"':
333  return false;
334  default:
335  return true;
336  }
337 }
338 
339 static inline bool StringNeedsShellEscaping(const string& input) {
340  for (size_t i = 0; i < input.size(); ++i) {
341  if (!IsKnownShellSafeCharacter(input[i])) return true;
342  }
343  return false;
344 }
345 
346 static inline bool StringNeedsWin32Escaping(const string& input) {
347  for (size_t i = 0; i < input.size(); ++i) {
348  if (!IsKnownWin32SafeCharacter(input[i])) return true;
349  }
350  return false;
351 }
352 
353 void GetShellEscapedString(const string& input, string* result) {
354  assert(result);
355 
356  if (!StringNeedsShellEscaping(input)) {
357  result->append(input);
358  return;
359  }
360 
361  const char kQuote = '\'';
362  const char kEscapeSequence[] = "'\\'";
363 
364  result->push_back(kQuote);
365 
366  string::const_iterator span_begin = input.begin();
367  for (string::const_iterator it = input.begin(), end = input.end(); it != end;
368  ++it) {
369  if (*it == kQuote) {
370  result->append(span_begin, it);
371  result->append(kEscapeSequence);
372  span_begin = it;
373  }
374  }
375  result->append(span_begin, input.end());
376  result->push_back(kQuote);
377 }
378 
379 
380 void GetWin32EscapedString(const string& input, string* result) {
381  assert(result);
382  if (!StringNeedsWin32Escaping(input)) {
383  result->append(input);
384  return;
385  }
386 
387  const char kQuote = '"';
388  const char kBackslash = '\\';
389 
390  result->push_back(kQuote);
391  size_t consecutive_backslash_count = 0;
392  string::const_iterator span_begin = input.begin();
393  for (string::const_iterator it = input.begin(), end = input.end(); it != end;
394  ++it) {
395  switch (*it) {
396  case kBackslash:
397  ++consecutive_backslash_count;
398  break;
399  case kQuote:
400  result->append(span_begin, it);
401  result->append(consecutive_backslash_count + 1, kBackslash);
402  span_begin = it;
403  consecutive_backslash_count = 0;
404  break;
405  default:
406  consecutive_backslash_count = 0;
407  break;
408  }
409  }
410  result->append(span_begin, input.end());
411  result->append(consecutive_backslash_count, kBackslash);
412  result->push_back(kQuote);
413 }
414 
415 int ReadFile(const string& path, string* contents, string* err) {
416 #ifdef _WIN32
417  // This makes a ninja run on a set of 1500 manifest files about 4% faster
418  // than using the generic fopen code below.
419  err->clear();
420  HANDLE f = ::CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
421  OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
422  if (f == INVALID_HANDLE_VALUE) {
423  err->assign(GetLastErrorString());
424  return -ENOENT;
425  }
426 
427  for (;;) {
428  DWORD len;
429  char buf[64 << 10];
430  if (!::ReadFile(f, buf, sizeof(buf), &len, NULL)) {
431  err->assign(GetLastErrorString());
432  contents->clear();
433  ::CloseHandle(f);
434  return -EIO;
435  }
436  if (len == 0)
437  break;
438  contents->append(buf, len);
439  }
440  ::CloseHandle(f);
441  return 0;
442 #else
443  FILE* f = fopen(path.c_str(), "rb");
444  if (!f) {
445  err->assign(strerror(errno));
446  return -errno;
447  }
448 
449 #ifdef __USE_LARGEFILE64
450  struct stat64 st;
451  if (fstat64(fileno(f), &st) < 0) {
452 #else
453  struct stat st;
454  if (fstat(fileno(f), &st) < 0) {
455 #endif
456  err->assign(strerror(errno));
457  fclose(f);
458  return -errno;
459  }
460 
461  // +1 is for the resize in ManifestParser::Load
462  contents->reserve(st.st_size + 1);
463 
464  char buf[64 << 10];
465  size_t len;
466  while (!feof(f) && (len = fread(buf, 1, sizeof(buf), f)) > 0) {
467  contents->append(buf, len);
468  }
469  if (ferror(f)) {
470  err->assign(strerror(errno)); // XXX errno?
471  contents->clear();
472  fclose(f);
473  return -errno;
474  }
475  fclose(f);
476  return 0;
477 #endif
478 }
479 
480 void SetCloseOnExec(int fd) {
481 #ifndef _WIN32
482  int flags = fcntl(fd, F_GETFD);
483  if (flags < 0) {
484  perror("fcntl(F_GETFD)");
485  } else {
486  if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
487  perror("fcntl(F_SETFD)");
488  }
489 #else
490  HANDLE hd = (HANDLE) _get_osfhandle(fd);
491  if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
492  fprintf(stderr, "SetHandleInformation(): %s", GetLastErrorString().c_str());
493  }
494 #endif // ! _WIN32
495 }
496 
497 
498 const char* SpellcheckStringV(const string& text,
499  const vector<const char*>& words) {
500  const bool kAllowReplacements = true;
501  const int kMaxValidEditDistance = 3;
502 
503  int min_distance = kMaxValidEditDistance + 1;
504  const char* result = NULL;
505  for (vector<const char*>::const_iterator i = words.begin();
506  i != words.end(); ++i) {
507  int distance = EditDistance(*i, text, kAllowReplacements,
508  kMaxValidEditDistance);
509  if (distance < min_distance) {
510  min_distance = distance;
511  result = *i;
512  }
513  }
514  return result;
515 }
516 
517 const char* SpellcheckString(const char* text, ...) {
518  // Note: This takes a const char* instead of a string& because using
519  // va_start() with a reference parameter is undefined behavior.
520  va_list ap;
521  va_start(ap, text);
522  vector<const char*> words;
523  const char* word;
524  while ((word = va_arg(ap, const char*)))
525  words.push_back(word);
526  va_end(ap);
527  return SpellcheckStringV(text, words);
528 }
529 
530 #ifdef _WIN32
531 string GetLastErrorString() {
532  DWORD err = GetLastError();
533 
534  char* msg_buf;
535  FormatMessageA(
536  FORMAT_MESSAGE_ALLOCATE_BUFFER |
537  FORMAT_MESSAGE_FROM_SYSTEM |
538  FORMAT_MESSAGE_IGNORE_INSERTS,
539  NULL,
540  err,
541  MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
542  (char*)&msg_buf,
543  0,
544  NULL);
545 
546  if (msg_buf == nullptr) {
547  char fallback_msg[128] = {0};
548  snprintf(fallback_msg, sizeof(fallback_msg), "GetLastError() = %lu", err);
549  return fallback_msg;
550  }
551 
552  string msg = msg_buf;
553  LocalFree(msg_buf);
554  return msg;
555 }
556 
557 void Win32Fatal(const char* function, const char* hint) {
558  if (hint) {
559  Fatal("%s: %s (%s)", function, GetLastErrorString().c_str(), hint);
560  } else {
561  Fatal("%s: %s", function, GetLastErrorString().c_str());
562  }
563 }
564 #endif
565 
566 bool islatinalpha(int c) {
567  // isalpha() is locale-dependent.
568  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
569 }
570 
571 string StripAnsiEscapeCodes(const string& in) {
572  string stripped;
573  stripped.reserve(in.size());
574 
575  for (size_t i = 0; i < in.size(); ++i) {
576  if (in[i] != '\33') {
577  // Not an escape code.
578  stripped.push_back(in[i]);
579  continue;
580  }
581 
582  // Only strip CSIs for now.
583  if (i + 1 >= in.size()) break;
584  if (in[i + 1] != '[') continue; // Not a CSI.
585  i += 2;
586 
587  // Skip everything up to and including the next [a-zA-Z].
588  while (i < in.size() && !islatinalpha(in[i]))
589  ++i;
590  }
591  return stripped;
592 }
593 
594 #if defined(__linux__) || defined(__GLIBC__)
595 std::pair<int64_t, bool> readCount(const std::string& path) {
596  std::ifstream file(path.c_str());
597  if (!file.is_open())
598  return std::make_pair(0, false);
599  int64_t n = 0;
600  file >> n;
601  if (file.good())
602  return std::make_pair(n, true);
603  return std::make_pair(0, false);
604 }
605 
606 struct MountPoint {
607  int mountId;
608  int parentId;
609  StringPiece deviceId;
610  StringPiece root;
611  StringPiece mountPoint;
612  vector<StringPiece> options;
613  vector<StringPiece> optionalFields;
614  StringPiece fsType;
615  StringPiece mountSource;
616  vector<StringPiece> superOptions;
617  bool parse(const string& line) {
618  vector<StringPiece> pieces = SplitStringPiece(line, ' ');
619  if (pieces.size() < 10)
620  return false;
621  size_t optionalStart = 0;
622  for (size_t i = 6; i < pieces.size(); i++) {
623  if (pieces[i] == "-") {
624  optionalStart = i + 1;
625  break;
626  }
627  }
628  if (optionalStart == 0)
629  return false;
630  if (optionalStart + 3 != pieces.size())
631  return false;
632  mountId = atoi(pieces[0].AsString().c_str());
633  parentId = atoi(pieces[1].AsString().c_str());
634  deviceId = pieces[2];
635  root = pieces[3];
636  mountPoint = pieces[4];
637  options = SplitStringPiece(pieces[5], ',');
638  optionalFields =
639  vector<StringPiece>(&pieces[6], &pieces[optionalStart - 1]);
640  fsType = pieces[optionalStart];
641  mountSource = pieces[optionalStart + 1];
642  superOptions = SplitStringPiece(pieces[optionalStart + 2], ',');
643  return true;
644  }
645  string translate(string& path) const {
646  // path must be sub dir of root
647  if (path.compare(0, root.len_, root.str_, root.len_) != 0) {
648  return string();
649  }
650  path.erase(0, root.len_);
651  if (path == ".." || (path.length() > 2 && path.compare(0, 3, "../") == 0)) {
652  return string();
653  }
654  return mountPoint.AsString() + "/" + path;
655  }
656 };
657 
658 struct CGroupSubSys {
659  int id;
660  string name;
661  vector<string> subsystems;
662  bool parse(string& line) {
663  size_t first = line.find(':');
664  if (first == string::npos)
665  return false;
666  line[first] = '\0';
667  size_t second = line.find(':', first + 1);
668  if (second == string::npos)
669  return false;
670  line[second] = '\0';
671  id = atoi(line.c_str());
672  name = line.substr(second + 1);
673  vector<StringPiece> pieces =
674  SplitStringPiece(StringPiece(line.c_str() + first + 1), ',');
675  for (size_t i = 0; i < pieces.size(); i++) {
676  subsystems.push_back(pieces[i].AsString());
677  }
678  return true;
679  }
680 };
681 
682 map<string, string> ParseMountInfo(map<string, CGroupSubSys>& subsystems) {
683  map<string, string> cgroups;
684  ifstream mountinfo("/proc/self/mountinfo");
685  if (!mountinfo.is_open())
686  return cgroups;
687  while (!mountinfo.eof()) {
688  string line;
689  getline(mountinfo, line);
690  MountPoint mp;
691  if (!mp.parse(line))
692  continue;
693  if (mp.fsType == "cgroup") {
694  for (size_t i = 0; i < mp.superOptions.size(); i++) {
695  std::string opt = mp.superOptions[i].AsString();
696  auto subsys = subsystems.find(opt);
697  if (subsys == subsystems.end()) {
698  continue;
699  }
700  std::string newPath = mp.translate(subsys->second.name);
701  if (!newPath.empty()) {
702  cgroups.emplace(opt, newPath);
703  }
704  }
705  } else if (mp.fsType == "cgroup2") {
706  // Find cgroup2 entry in format "0::/path/to/cgroup"
707  auto subsys = std::find_if(subsystems.begin(), subsystems.end(),
708  [](const auto& sys) {
709  return sys.first == "" && sys.second.id == 0;
710  });
711  if (subsys == subsystems.end()) {
712  continue;
713  }
714  std::string path = mp.mountPoint.AsString();
715  if (subsys->second.name != "/") {
716  // Append the relative path for the cgroup to the mount point
717  path.append(subsys->second.name);
718  }
719  cgroups.emplace("cgroup2", path);
720  }
721  }
722  return cgroups;
723 }
724 
725 map<string, CGroupSubSys> ParseSelfCGroup() {
726  map<string, CGroupSubSys> cgroups;
727  ifstream cgroup("/proc/self/cgroup");
728  if (!cgroup.is_open())
729  return cgroups;
730  string line;
731  while (!cgroup.eof()) {
732  getline(cgroup, line);
733  CGroupSubSys subsys;
734  if (!subsys.parse(line))
735  continue;
736  for (size_t i = 0; i < subsys.subsystems.size(); i++) {
737  cgroups.insert(make_pair(subsys.subsystems[i], subsys));
738  }
739  }
740  return cgroups;
741 }
742 
743 int ParseCgroupV1(std::string& path) {
744  std::pair<int64_t, bool> quota = readCount(path + "/cpu.cfs_quota_us");
745  if (!quota.second || quota.first == -1)
746  return -1;
747  std::pair<int64_t, bool> period = readCount(path + "/cpu.cfs_period_us");
748  if (!period.second)
749  return -1;
750  if (period.first == 0)
751  return -1;
752  return quota.first / period.first;
753 }
754 
755 int ParseCgroupV2(std::string& path) {
756  // Read CPU quota from cgroup v2
757  std::ifstream cpu_max(path + "/cpu.max");
758  if (!cpu_max.is_open()) {
759  return -1;
760  }
761  std::string max_line;
762  if (!std::getline(cpu_max, max_line) || max_line.empty()) {
763  return -1;
764  }
765  // Format is "quota period" or "max period"
766  size_t space_pos = max_line.find(' ');
767  if (space_pos == string::npos) {
768  return -1;
769  }
770  std::string quota_str = max_line.substr(0, space_pos);
771  std::string period_str = max_line.substr(space_pos + 1);
772  if (quota_str == "max") {
773  return -1; // No CPU limit set
774  }
775  // Convert quota string to integer
776  char* quota_end = nullptr;
777  errno = 0;
778  int64_t quota = strtoll(quota_str.c_str(), &quota_end, 10);
779  // Check for conversion errors
780  if (errno == ERANGE || quota_end == quota_str.c_str() || *quota_end != '\0' ||
781  quota <= 0) {
782  return -1;
783  }
784  // Convert period string to integer
785  char* period_end = nullptr;
786  errno = 0;
787  int64_t period = strtoll(period_str.c_str(), &period_end, 10);
788  // Check for conversion errors
789  if (errno == ERANGE || period_end == period_str.c_str() ||
790  *period_end != '\0' || period <= 0) {
791  return -1;
792  }
793  return quota / period;
794 }
795 
796 int ParseCPUFromCGroup() {
797  auto subsystems = ParseSelfCGroup();
798  auto cgroups = ParseMountInfo(subsystems);
799 
800  // Prefer cgroup v2 if both v1 and v2 should be present
801  const auto cgroup2 = cgroups.find("cgroup2");
802  if (cgroup2 != cgroups.end()) {
803  return ParseCgroupV2(cgroup2->second);
804  }
805 
806  const auto cpu = cgroups.find("cpu");
807  if (cpu != cgroups.end()) {
808  return ParseCgroupV1(cpu->second);
809  }
810  return -1;
811 }
812 #endif
813 
815 #ifdef _WIN32
816  DWORD cpuCount = 0;
817 #ifndef _WIN64
818  // Need to use GetLogicalProcessorInformationEx to get real core count on
819  // machines with >64 cores. See https://stackoverflow.com/a/31209344/21475
820  DWORD len = 0;
821  if (!GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &len)
822  && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
823  std::vector<char> buf(len);
824  int cores = 0;
825  if (GetLogicalProcessorInformationEx(RelationProcessorCore,
826  reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(
827  buf.data()), &len)) {
828  for (DWORD i = 0; i < len; ) {
829  auto info = reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(
830  buf.data() + i);
831  if (info->Relationship == RelationProcessorCore &&
832  info->Processor.GroupCount == 1) {
833  for (KAFFINITY core_mask = info->Processor.GroupMask[0].Mask;
834  core_mask; core_mask >>= 1) {
835  cores += (core_mask & 1);
836  }
837  }
838  i += info->Size;
839  }
840  if (cores != 0) {
841  cpuCount = cores;
842  }
843  }
844  }
845 #endif
846  if (cpuCount == 0) {
847  cpuCount = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
848  }
849  JOBOBJECT_CPU_RATE_CONTROL_INFORMATION info;
850  // reference:
851  // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information
852  if (QueryInformationJobObject(NULL, JobObjectCpuRateControlInformation, &info,
853  sizeof(info), NULL)) {
854  if (info.ControlFlags & (JOB_OBJECT_CPU_RATE_CONTROL_ENABLE |
855  JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP)) {
856  return cpuCount * info.CpuRate / 10000;
857  }
858  }
859  return cpuCount;
860 #else
861  int cgroupCount = -1;
862  int schedCount = -1;
863 #if defined(__linux__) || defined(__GLIBC__)
864  cgroupCount = ParseCPUFromCGroup();
865 #endif
866  // The number of exposed processors might not represent the actual number of
867  // processors threads can run on. This happens when a CPU set limitation is
868  // active, see https://github.com/ninja-build/ninja/issues/1278
869 #if defined(__FreeBSD__)
870  cpuset_t mask;
871  CPU_ZERO(&mask);
872  if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(mask),
873  &mask) == 0) {
874  return CPU_COUNT(&mask);
875  }
876 #elif defined(CPU_COUNT)
877  cpu_set_t set;
878  if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) {
879  schedCount = CPU_COUNT(&set);
880  }
881 #endif
882  if (cgroupCount >= 0 && schedCount >= 0) return std::min(cgroupCount, schedCount);
883  if (cgroupCount < 0 && schedCount < 0)
884  return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
885  return std::max(cgroupCount, schedCount);
886 #endif
887 }
888 
889 #if defined(_WIN32) || defined(__CYGWIN__)
890 static double CalculateProcessorLoad(uint64_t idle_ticks, uint64_t total_ticks)
891 {
892  static uint64_t previous_idle_ticks = 0;
893  static uint64_t previous_total_ticks = 0;
894  static double previous_load = -0.0;
895 
896  uint64_t idle_ticks_since_last_time = idle_ticks - previous_idle_ticks;
897  uint64_t total_ticks_since_last_time = total_ticks - previous_total_ticks;
898 
899  bool first_call = (previous_total_ticks == 0);
900  bool ticks_not_updated_since_last_call = (total_ticks_since_last_time == 0);
901 
902  double load;
903  if (first_call || ticks_not_updated_since_last_call) {
904  load = previous_load;
905  } else {
906  // Calculate load.
907  double idle_to_total_ratio =
908  ((double)idle_ticks_since_last_time) / total_ticks_since_last_time;
909  double load_since_last_call = 1.0 - idle_to_total_ratio;
910 
911  // Filter/smooth result when possible.
912  if(previous_load > 0) {
913  load = 0.9 * previous_load + 0.1 * load_since_last_call;
914  } else {
915  load = load_since_last_call;
916  }
917  }
918 
919  previous_load = load;
920  previous_total_ticks = total_ticks;
921  previous_idle_ticks = idle_ticks;
922 
923  return load;
924 }
925 
926 static uint64_t FileTimeToTickCount(const FILETIME & ft)
927 {
928  uint64_t high = (((uint64_t)(ft.dwHighDateTime)) << 32);
929  uint64_t low = ft.dwLowDateTime;
930  return (high | low);
931 }
932 
933 double GetLoadAverage() {
934  FILETIME idle_time, kernel_time, user_time;
935  BOOL get_system_time_succeeded =
936  GetSystemTimes(&idle_time, &kernel_time, &user_time);
937 
938  double posix_compatible_load;
939  if (get_system_time_succeeded) {
940  uint64_t idle_ticks = FileTimeToTickCount(idle_time);
941 
942  // kernel_time from GetSystemTimes already includes idle_time.
943  uint64_t total_ticks =
944  FileTimeToTickCount(kernel_time) + FileTimeToTickCount(user_time);
945 
946  double processor_load = CalculateProcessorLoad(idle_ticks, total_ticks);
947  posix_compatible_load = processor_load * GetProcessorCount();
948 
949  } else {
950  posix_compatible_load = -0.0;
951  }
952 
953  return posix_compatible_load;
954 }
955 #elif defined(__PASE__)
956 double GetLoadAverage() {
957  return -0.0f;
958 }
959 #elif defined(_AIX)
960 double GetLoadAverage() {
961  perfstat_cpu_total_t cpu_stats;
962  if (perfstat_cpu_total(NULL, &cpu_stats, sizeof(cpu_stats), 1) < 0) {
963  return -0.0f;
964  }
965 
966  // Calculation taken from comment in libperfstats.h
967  return double(cpu_stats.loadavg[0]) / double(1 << SBITS);
968 }
969 #elif defined(__UCLIBC__) || (defined(__BIONIC__) && __ANDROID_API__ < 29)
970 double GetLoadAverage() {
971  struct sysinfo si;
972  if (sysinfo(&si) != 0)
973  return -0.0f;
974  return 1.0 / (1 << SI_LOAD_SHIFT) * si.loads[0];
975 }
976 #elif defined(__HAIKU__)
977 double GetLoadAverage() {
978  return -0.0f;
979 }
980 #else
981 double GetLoadAverage() {
982  double loadavg[3] = { 0.0f, 0.0f, 0.0f };
983  if (getloadavg(loadavg, 3) < 0) {
984  // Maybe we should return an error here or the availability of
985  // getloadavg(3) should be checked when ninja is configured.
986  return -0.0f;
987  }
988  return loadavg[0];
989 }
990 #endif // _WIN32
991 
992 std::string GetWorkingDirectory() {
993  std::string ret;
994  char* success = NULL;
995  do {
996  ret.resize(ret.size() + 1024);
997  errno = 0;
998  success = getcwd(&ret[0], ret.size());
999  } while (!success && errno == ERANGE);
1000  if (!success) {
1001  Fatal("cannot determine working directory: %s", strerror(errno));
1002  }
1003  ret.resize(strlen(&ret[0]));
1004  return ret;
1005 }
1006 
1007 bool Truncate(const string& path, size_t size, string* err) {
1008 #ifdef _WIN32
1009  int fh = _sopen(path.c_str(), _O_RDWR | _O_CREAT, _SH_DENYNO,
1010  _S_IREAD | _S_IWRITE);
1011  int success = _chsize(fh, size);
1012  _close(fh);
1013 #else
1014  int success = truncate(path.c_str(), size);
1015 #endif
1016  // Both truncate() and _chsize() return 0 on success and set errno and return
1017  // -1 on failure.
1018  if (success < 0) {
1019  *err = strerror(errno);
1020  return false;
1021  }
1022  return true;
1023 }
1024 
1025 int platformAwareUnlink(const char* filename) {
1026  #ifdef _WIN32
1027  return _unlink(filename);
1028  #else
1029  return unlink(filename);
1030  #endif
1031 }
int EditDistance(const StringPiece &s1, const StringPiece &s2, bool allow_replacements, int max_edit_distance)
Definition: hash_map.h:26
vector< StringPiece > SplitStringPiece(StringPiece input, char sep)
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:25
const char * str_
Definition: string_piece.h:70
size_t len_
Definition: string_piece.h:71
std::string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:46
int GetProcessorCount()
Definition: util.cc:814
void GetWin32EscapedString(const string &input, string *result)
Definition: util.cc:380
void Error(const char *msg, va_list ap)
Definition: util.cc:98
static bool IsKnownShellSafeCharacter(char ch)
Definition: util.cc:312
const char * SpellcheckString(const char *text,...)
Like SpellcheckStringV, but takes a NULL-terminated list.
Definition: util.cc:517
static bool StringNeedsShellEscaping(const string &input)
Definition: util.cc:339
int platformAwareUnlink(const char *filename)
Definition: util.cc:1025
bool islatinalpha(int c)
Definition: util.cc:566
static bool IsKnownWin32SafeCharacter(char ch)
Definition: util.cc:329
bool Truncate(const string &path, size_t size, string *err)
Definition: util.cc:1007
void GetShellEscapedString(const string &input, string *result)
Definition: util.cc:353
std::string GetWorkingDirectory()
a wrapper for getcwd()
Definition: util.cc:992
void Warning(const char *msg, va_list ap)
Definition: util.cc:85
void Info(const char *msg, va_list ap)
Definition: util.cc:111
static bool IsPathSeparator(char c)
Definition: util.cc:133
void SetCloseOnExec(int fd)
Mark a file descriptor to not be inherited on exec()s.
Definition: util.cc:480
void CanonicalizePath(string *path, uint64_t *slash_bits)
Definition: util.cc:124
string StripAnsiEscapeCodes(const string &in)
Definition: util.cc:571
static bool StringNeedsWin32Escaping(const string &input)
Definition: util.cc:346
const char * SpellcheckStringV(const string &text, const vector< const char * > &words)
Definition: util.cc:498
void Fatal(const char *msg,...)
Log a fatal message and exit.
Definition: util.cc:67
int ReadFile(const string &path, string *contents, string *err)
Definition: util.cc:415
double GetLoadAverage()
Definition: util.cc:981
#define NINJA_FALLTHROUGH
Definition: util.h:48
unsigned long long uint64_t
Definition: win32port.h:29
signed long long int64_t
A 64-bit integer type.
Definition: win32port.h:28