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
13namespace dart {
14
15char* 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
38char* Utils::StrDup(const char* s) {
39 return strdup(s);
40}
41
42intptr_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
58int 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
66int 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
74int Utils::Close(int fildes) {
75 return close(fildes);
76}
77size_t Utils::Read(int filedes, void* buf, size_t nbyte) {
78 return read(filedes, buf, nbyte);
79}
80int Utils::Unlink(const char* path) {
81 return unlink(path);
82}
83
84namespace 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.
89int32_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.
134int32_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
147int32_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