1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "vm/globals.h" |
6 | #if defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID) |
7 | |
8 | #include "vm/proccpuinfo.h" |
9 | |
10 | #include <ctype.h> // NOLINT |
11 | #include <string.h> // NOLINT |
12 | |
13 | #include "platform/assert.h" |
14 | |
15 | namespace dart { |
16 | |
17 | char* ProcCpuInfo::data_ = NULL; |
18 | intptr_t ProcCpuInfo::datalen_ = 0; |
19 | |
20 | void ProcCpuInfo::Init() { |
21 | // Get the size of the cpuinfo file by reading it until the end. This is |
22 | // required because files under /proc do not always return a valid size |
23 | // when using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. |
24 | static const char PATHNAME[] = "/proc/cpuinfo" ; |
25 | FILE* fp = fopen(PATHNAME, "r" ); |
26 | if (fp != NULL) { |
27 | for (;;) { |
28 | char buffer[256]; |
29 | size_t n = fread(buffer, 1, sizeof(buffer), fp); |
30 | if (n == 0) { |
31 | break; |
32 | } |
33 | datalen_ += n; |
34 | } |
35 | fclose(fp); |
36 | } |
37 | |
38 | // Read the contents of the cpuinfo file. |
39 | data_ = reinterpret_cast<char*>(malloc(datalen_ + 1)); |
40 | fp = fopen(PATHNAME, "r" ); |
41 | if (fp != NULL) { |
42 | for (intptr_t offset = 0; offset < datalen_;) { |
43 | size_t n = fread(data_ + offset, 1, datalen_ - offset, fp); |
44 | if (n == 0) { |
45 | break; |
46 | } |
47 | offset += n; |
48 | } |
49 | fclose(fp); |
50 | } |
51 | |
52 | // Zero-terminate the data. |
53 | data_[datalen_] = '\0'; |
54 | } |
55 | |
56 | void ProcCpuInfo::Cleanup() { |
57 | ASSERT(data_); |
58 | free(data_); |
59 | data_ = NULL; |
60 | } |
61 | |
62 | char* ProcCpuInfo::FieldStart(const char* field) { |
63 | // Look for first field occurrence, and ensure it starts the line. |
64 | size_t fieldlen = strlen(field); |
65 | char* p = data_; |
66 | for (;;) { |
67 | p = strstr(p, field); |
68 | if (p == NULL) { |
69 | return NULL; |
70 | } |
71 | if (p == data_ || p[-1] == '\n') { |
72 | break; |
73 | } |
74 | p += fieldlen; |
75 | } |
76 | |
77 | // Skip to the first colon followed by a space. |
78 | p = strchr(p + fieldlen, ':'); |
79 | if (p == NULL || (isspace(p[1]) == 0)) { |
80 | return NULL; |
81 | } |
82 | p += 2; |
83 | |
84 | return p; |
85 | } |
86 | |
87 | bool ProcCpuInfo::FieldContains(const char* field, const char* search_string) { |
88 | ASSERT(data_ != NULL); |
89 | ASSERT(search_string != NULL); |
90 | |
91 | char* p = FieldStart(field); |
92 | if (p == NULL) { |
93 | return false; |
94 | } |
95 | |
96 | // Find the end of the line. |
97 | char* q = strchr(p, '\n'); |
98 | if (q == NULL) { |
99 | q = data_ + datalen_; |
100 | } |
101 | |
102 | char saved_end = *q; |
103 | *q = '\0'; |
104 | bool ret = (strcasestr(p, search_string) != NULL); |
105 | *q = saved_end; |
106 | |
107 | return ret; |
108 | } |
109 | |
110 | // Extract the content of a the first occurrence of a given field in |
111 | // the content of the cpuinfo file and return it as a heap-allocated |
112 | // string that must be freed by the caller using free. |
113 | // Return NULL if not found. |
114 | const char* ProcCpuInfo::(const char* field) { |
115 | ASSERT(field != NULL); |
116 | ASSERT(data_ != NULL); |
117 | |
118 | char* p = FieldStart(field); |
119 | if (p == NULL) { |
120 | return NULL; |
121 | } |
122 | |
123 | // Find the end of the line. |
124 | char* q = strchr(p, '\n'); |
125 | if (q == NULL) { |
126 | q = data_ + datalen_; |
127 | } |
128 | |
129 | intptr_t len = q - p; |
130 | char* result = reinterpret_cast<char*>(malloc(len + 1)); |
131 | // Copy the line into result, leaving enough room for a null-terminator. |
132 | char saved_end = *q; |
133 | *q = '\0'; |
134 | strncpy(result, p, len); |
135 | result[len] = '\0'; |
136 | *q = saved_end; |
137 | |
138 | return result; |
139 | } |
140 | |
141 | bool ProcCpuInfo::HasField(const char* field) { |
142 | ASSERT(field != NULL); |
143 | ASSERT(data_ != NULL); |
144 | return (FieldStart(field) != NULL); |
145 | } |
146 | |
147 | } // namespace dart |
148 | |
149 | #endif // defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID) |
150 | |