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 "platform/globals.h" |
6 | #if defined(HOST_OS_MACOS) |
7 | |
8 | #include "platform/utils.h" |
9 | |
10 | #include <errno.h> // NOLINT |
11 | #include <sys/utsname.h> // NOLINT |
12 | |
13 | namespace dart { |
14 | |
15 | char* Utils::StrNDup(const char* s, intptr_t n) { |
16 | // strndup has only been added to Mac OS X in 10.7. We are supplying |
17 | // our own copy here if needed. |
18 | #if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \ |
19 | __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060 |
20 | intptr_t len = strlen(s); |
21 | if ((n < 0) || (len < 0)) { |
22 | return NULL; |
23 | } |
24 | if (n < len) { |
25 | len = n; |
26 | } |
27 | char* result = reinterpret_cast<char*>(malloc(len + 1)); |
28 | if (result == NULL) { |
29 | return NULL; |
30 | } |
31 | result[len] = '\0'; |
32 | return reinterpret_cast<char*>(memmove(result, s, len)); |
33 | #else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ... |
34 | return strndup(s, n); |
35 | #endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ... |
36 | } |
37 | |
38 | char* Utils::StrDup(const char* s) { |
39 | return strdup(s); |
40 | } |
41 | |
42 | intptr_t Utils::StrNLen(const char* s, intptr_t n) { |
43 | // strnlen has only been added to Mac OS X in 10.7. We are supplying |
44 | // our own copy here if needed. |
45 | #if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \ |
46 | __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060 |
47 | intptr_t len = 0; |
48 | while ((len <= n) && (*s != '\0')) { |
49 | s++; |
50 | len++; |
51 | } |
52 | return len; |
53 | #else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ... |
54 | return strnlen(s, n); |
55 | #endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ... |
56 | } |
57 | |
58 | int Utils::SNPrint(char* str, size_t size, const char* format, ...) { |
59 | va_list args; |
60 | va_start(args, format); |
61 | int retval = VSNPrint(str, size, format, args); |
62 | va_end(args); |
63 | return retval; |
64 | } |
65 | |
66 | int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) { |
67 | int retval = vsnprintf(str, size, format, args); |
68 | if (retval < 0) { |
69 | FATAL1("Fatal error in Utils::VSNPrint with format '%s'" , format); |
70 | } |
71 | return retval; |
72 | } |
73 | |
74 | int Utils::Close(int fildes) { |
75 | return close(fildes); |
76 | } |
77 | size_t Utils::Read(int filedes, void* buf, size_t nbyte) { |
78 | return read(filedes, buf, nbyte); |
79 | } |
80 | int Utils::Unlink(const char* path) { |
81 | return unlink(path); |
82 | } |
83 | |
84 | namespace internal { |
85 | |
86 | // Returns the running system's Darwin major version. Don't call this, it's |
87 | // an implementation detail and its result is meant to be cached by |
88 | // MacOSXMinorVersion. |
89 | int32_t DarwinMajorVersionInternal() { |
90 | // uname is implemented as a simple series of sysctl system calls to |
91 | // obtain the relevant data from the kernel. The data is |
92 | // compiled right into the kernel, so no threads or blocking or other |
93 | // funny business is necessary. |
94 | |
95 | struct utsname uname_info; |
96 | if (uname(&uname_info) != 0) { |
97 | FATAL("Fatal error in DarwinMajorVersionInternal : invalid return uname" ); |
98 | return 0; |
99 | } |
100 | |
101 | if (strcmp(uname_info.sysname, "Darwin" ) != 0) { |
102 | FATAL1( |
103 | "Fatal error in DarwinMajorVersionInternal : unexpected uname" |
104 | " sysname '%s'" , |
105 | uname_info.sysname); |
106 | return 0; |
107 | } |
108 | |
109 | int32_t darwin_major_version = 0; |
110 | char* dot = strchr(uname_info.release, '.'); |
111 | if (dot) { |
112 | errno = 0; |
113 | char* end_ptr = NULL; |
114 | darwin_major_version = strtol(uname_info.release, &end_ptr, 10); |
115 | if (errno != 0 || (end_ptr == uname_info.release)) { |
116 | dot = NULL; |
117 | } |
118 | } |
119 | |
120 | if (!dot) { |
121 | FATAL1( |
122 | "Fatal error in DarwinMajorVersionInternal :" |
123 | " could not parse uname release '%s'" , |
124 | uname_info.release); |
125 | return 0; |
126 | } |
127 | |
128 | return darwin_major_version; |
129 | } |
130 | |
131 | // Returns the running system's Mac OS X minor version. This is the |y| value |
132 | // in 10.y or 10.y.z. Don't call this, it's an implementation detail and the |
133 | // result is meant to be cached by MacOSXMinorVersion. |
134 | int32_t MacOSXMinorVersionInternal() { |
135 | int darwin_major_version = DarwinMajorVersionInternal(); |
136 | |
137 | // The Darwin major version is always 4 greater than the Mac OS X minor |
138 | // version for Darwin versions beginning with 6, corresponding to Mac OS X |
139 | // 10.2. Since this correspondence may change in the future, warn when |
140 | // encountering a version higher than anything seen before. Older Darwin |
141 | // versions, or versions that can't be determined, result in |
142 | // immediate death. |
143 | ASSERT(darwin_major_version >= 6); |
144 | return (darwin_major_version - 4); |
145 | } |
146 | |
147 | int32_t MacOSXMinorVersion() { |
148 | static int mac_os_x_minor_version = MacOSXMinorVersionInternal(); |
149 | return mac_os_x_minor_version; |
150 | } |
151 | |
152 | } // namespace internal |
153 | |
154 | } // namespace dart |
155 | |
156 | #endif // defined(HOST_OS_MACOS) |
157 | |