1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 /* Foreign builtins. */
13 #include "rust_globals.h"
14 #include "vg/valgrind.h"
19 #include <TargetConditionals.h>
20 #include <mach/mach_time.h>
22 #if (TARGET_OS_IPHONE)
23 extern char **environ;
25 #include <crt_externs.h>
29 #if !defined(__WIN32__)
34 extern char **environ;
60 #if defined(__WIN32__)
68 #if defined(__APPLE__) && !(TARGET_OS_IPHONE)
69 char **environ = *_NSGetEnviron();
76 #if defined(__WIN32__)
77 rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
78 return entry_ptr->cFileName;
81 rust_list_dir_val(struct dirent* entry_ptr) {
82 return entry_ptr->d_name;
87 #if defined(__WIN32__)
88 rust_list_dir_wfd_size() {
89 return sizeof(WIN32_FIND_DATAW);
92 rust_list_dir_wfd_size() {
98 #if defined(__WIN32__)
99 rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) {
104 return wfd->cFileName;
108 rust_list_dir_wfd_fp_buf(void* wfd) {
114 rust_path_is_dir(const char *path) {
116 if (stat(path, &buf)) {
119 return S_ISDIR(buf.st_mode);
123 #if defined(__WIN32__)
124 rust_path_is_dir_u16(const wchar_t *path) {
126 // Don't use GetFileAttributesW, it cannot get attributes of
127 // some system files (e.g. pagefile.sys).
128 if (_wstat(path, &buf)) {
131 return S_ISDIR(buf.st_mode);
134 rust_path_is_dir_u16(const void *path) {
135 // Wide version of function is only used on Windows.
141 rust_path_exists(const char *path) {
143 if (stat(path, &buf)) {
150 #if defined(__WIN32__)
151 rust_path_exists_u16(const wchar_t *path) {
153 if (_wstat(path, &buf)) {
159 rust_path_exists_u16(const void *path) {
160 // Wide version of function is only used on Windows.
165 FILE* rust_get_stdin() {return stdin;}
166 FILE* rust_get_stdout() {return stdout;}
167 FILE* rust_get_stderr() {return stderr;}
169 #if defined(__WIN32__)
171 rust_get_time(int64_t *sec, int32_t *nsec) {
173 GetSystemTimeAsFileTime(&fileTime);
175 // A FILETIME contains a 64-bit value representing the number of
176 // hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z.
177 // http://support.microsoft.com/kb/167296/en-us
179 ul.LowPart = fileTime.dwLowDateTime;
180 ul.HighPart = fileTime.dwHighDateTime;
181 uint64_t ns_since_1601 = ul.QuadPart / 10;
183 const uint64_t NANOSECONDS_FROM_1601_TO_1970 = 11644473600000000ull;
184 uint64_t ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970;
185 *sec = ns_since_1970 / 1000000;
186 *nsec = (ns_since_1970 % 1000000) * 1000;
190 rust_get_time(int64_t *sec, int32_t *nsec) {
193 gettimeofday(&tv, NULL);
195 *nsec = tv.tv_usec * 1000;
198 clock_gettime(CLOCK_REALTIME, &ts);
205 const int64_t ns_per_s = 1000000000LL;
208 rust_precise_time_ns(uint64_t *ns) {
211 uint64_t time = mach_absolute_time();
212 mach_timebase_info_data_t info = {0, 0};
213 if (info.denom == 0) {
214 mach_timebase_info(&info);
216 uint64_t time_nano = time * (info.numer / info.denom);
219 LARGE_INTEGER ticks_per_s;
220 BOOL query_result = QueryPerformanceFrequency(&ticks_per_s);
221 assert(query_result);
222 if (ticks_per_s.QuadPart == 0LL) {
223 ticks_per_s.QuadPart = 1LL;
226 query_result = QueryPerformanceCounter(&ticks);
227 assert(query_result);
228 *ns = (uint64_t)((ticks.QuadPart * ns_per_s) / ticks_per_s.QuadPart);
231 clock_gettime(CLOCK_MONOTONIC, &ts);
232 *ns = (uint64_t)(ts.tv_sec * ns_per_s + ts.tv_nsec);
238 size_t fill; // in bytes; if zero, heapified
239 size_t alloc; // in bytes
243 typedef rust_vec rust_str;
260 void rust_tm_to_tm(rust_tm* in_tm, struct tm* out_tm) {
261 memset(out_tm, 0, sizeof(struct tm));
262 out_tm->tm_sec = in_tm->tm_sec;
263 out_tm->tm_min = in_tm->tm_min;
264 out_tm->tm_hour = in_tm->tm_hour;
265 out_tm->tm_mday = in_tm->tm_mday;
266 out_tm->tm_mon = in_tm->tm_mon;
267 out_tm->tm_year = in_tm->tm_year;
268 out_tm->tm_wday = in_tm->tm_wday;
269 out_tm->tm_yday = in_tm->tm_yday;
270 out_tm->tm_isdst = in_tm->tm_isdst;
273 void tm_to_rust_tm(struct tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
274 const char *zone, int32_t nsec) {
275 out_tm->tm_sec = in_tm->tm_sec;
276 out_tm->tm_min = in_tm->tm_min;
277 out_tm->tm_hour = in_tm->tm_hour;
278 out_tm->tm_mday = in_tm->tm_mday;
279 out_tm->tm_mon = in_tm->tm_mon;
280 out_tm->tm_year = in_tm->tm_year;
281 out_tm->tm_wday = in_tm->tm_wday;
282 out_tm->tm_yday = in_tm->tm_yday;
283 out_tm->tm_isdst = in_tm->tm_isdst;
284 out_tm->tm_gmtoff = gmtoff;
285 out_tm->tm_nsec = nsec;
288 size_t size = strlen(zone);
289 assert(out_tm->tm_zone->alloc >= size);
290 memcpy(out_tm->tm_zone->data, zone, size);
291 out_tm->tm_zone->fill = size;
295 #if defined(__WIN32__)
296 #define TZSET() _tzset()
297 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
298 #define GMTIME(clock, result) gmtime_s((result), (clock))
299 #define LOCALTIME(clock, result) localtime_s((result), (clock))
300 #define TIMEGM(result) _mkgmtime64(result)
302 struct tm* GMTIME(const time_t *clock, struct tm *result) {
303 struct tm* t = gmtime(clock);
304 if (t == NULL || result == NULL) { return NULL; }
308 struct tm* LOCALTIME(const time_t *clock, struct tm *result) {
309 struct tm* t = localtime(clock);
310 if (t == NULL || result == NULL) { return NULL; }
314 #define TIMEGM(result) mktime((result)) - _timezone
317 #define TZSET() tzset()
318 #define GMTIME(clock, result) gmtime_r((clock), (result))
319 #define LOCALTIME(clock, result) localtime_r((clock), (result))
320 #define TIMEGM(result) timegm(result)
329 rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
334 tm_to_rust_tm(&tm, timeptr, 0, "UTC", nsec);
338 rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
343 const char* zone = NULL;
344 #if defined(__WIN32__)
345 int32_t gmtoff = -timezone;
346 wchar_t wbuffer[64] = {0};
347 char buffer[256] = {0};
348 // strftime("%Z") can contain non-UTF-8 characters on non-English locale (issue #9418),
349 // so time zone should be converted from UTF-16 string.
350 // Since wcsftime depends on setlocale() result,
351 // instead we convert it using MultiByteToWideChar.
352 if (strftime(buffer, sizeof(buffer) / sizeof(char), "%Z", &tm) > 0) {
354 MultiByteToWideChar(CP_ACP, 0, buffer, -1, wbuffer, sizeof(wbuffer) / sizeof(wchar_t));
356 WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL);
360 int32_t gmtoff = tm.tm_gmtoff;
364 tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec);
368 rust_timegm(rust_tm* timeptr) {
370 rust_tm_to_tm(timeptr, &t);
375 rust_mktime(rust_tm* timeptr) {
377 rust_tm_to_tm(timeptr, &t);
382 #include <sys/types.h>
386 rust_opendir(char *dirname) {
387 return opendir(dirname);
391 rust_readdir(DIR *dirp) {
392 return readdir(dirp);
408 rust_running_on_valgrind() {
409 return RUNNING_ON_VALGRIND;
412 #if defined(__WIN32__)
416 GetSystemInfo(&sysinfo);
418 return (int) sysinfo.dwNumberOfProcessors;
420 #elif defined(__BSD__)
423 /* swiped from http://stackoverflow.com/questions/150355/
424 programmatically-find-the-number-of-cores-on-a-machine */
428 size_t len = sizeof(numCPU);
430 /* set the mib for hw.ncpu */
432 mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;
434 /* get the number of CPUs from the system */
435 sysctl(mib, 2, &numCPU, &len, NULL, 0);
439 sysctl( mib, 2, &numCPU, &len, NULL, 0 );
447 #elif defined(__GNUC__)
450 return sysconf(_SC_NPROCESSORS_ONLN);
455 rust_get_num_cpus() {
456 return get_num_cpus();
460 rust_valgrind_stack_register(void *start, void *end) {
461 return VALGRIND_STACK_REGISTER(start, end);
465 rust_valgrind_stack_deregister(unsigned int id) {
466 VALGRIND_STACK_DEREGISTER(id);
469 #if defined(__WIN32__)
472 rust_unset_sigprocmask() {
473 // empty stub for windows to keep linker happy
482 rust_unset_sigprocmask() {
483 // this can't be safely converted to rust code because the
484 // representation of sigset_t is platform-dependent
487 sigprocmask(SIG_SETMASK, &sset, NULL);
492 #if defined(__WIN32__)
494 win32_require(LPCTSTR fn, BOOL ok) {
497 DWORD err = GetLastError();
498 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
499 FORMAT_MESSAGE_FROM_SYSTEM |
500 FORMAT_MESSAGE_IGNORE_INSERTS,
502 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
503 (LPTSTR) &buf, 0, NULL );
504 fprintf(stderr, "%s failed with error %ld: %s", fn, err, buf);
505 LocalFree((HLOCAL)buf);
511 rust_win32_rand_acquire(HCRYPTPROV* phProv) {
513 (_T("CryptAcquireContext"),
514 // changes to the parameters here should be reflected in the docs of
515 // std::rand::os::OSRng
516 CryptAcquireContext(phProv, NULL, NULL, PROV_RSA_FULL,
517 CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
521 rust_win32_rand_gen(HCRYPTPROV hProv, DWORD dwLen, BYTE* pbBuffer) {
523 (_T("CryptGenRandom"), CryptGenRandom(hProv, dwLen, pbBuffer));
526 rust_win32_rand_release(HCRYPTPROV hProv) {
528 (_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0));
533 // these symbols are listed in rustrt.def.in, so they need to exist; but they
534 // should never be called.
537 rust_win32_rand_acquire() {
541 rust_win32_rand_gen() {
545 rust_win32_rand_release() {
551 #if defined(__WIN32__)
554 rust_crit_section_size() { return sizeof(CRITICAL_SECTION); }
556 rust_pthread_mutex_t_size() { return 0; }
558 rust_pthread_cond_t_size() { return 0; }
563 rust_crit_section_size() { return 0; }
565 rust_pthread_mutex_t_size() { return sizeof(pthread_mutex_t); }
567 rust_pthread_cond_t_size() { return sizeof(pthread_cond_t); }
575 // indent-tabs-mode: nil
577 // buffer-file-coding-system: utf-8-unix