]> git.proxmox.com Git - rustc.git/blob - src/rt/rust_builtin.c
1a2917a1dd67f9c8d0251fff51b1d8b0cbc425b4
[rustc.git] / src / rt / rust_builtin.c
1 // Copyright 2012-2015 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.
4 //
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.
10
11 #include <stdint.h>
12 #include <time.h>
13 #include <string.h>
14 #include <assert.h>
15 #include <stdlib.h>
16
17
18 #if !defined(_WIN32)
19 #include <dirent.h>
20 #include <pthread.h>
21 #include <signal.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #else
27 #include <windows.h>
28 #include <wincrypt.h>
29 #include <stdio.h>
30 #include <tchar.h>
31 #endif
32
33 #ifdef __APPLE__
34 #include <TargetConditionals.h>
35 #include <mach/mach_time.h>
36
37 #if !(TARGET_OS_IPHONE)
38 #include <crt_externs.h>
39 #endif
40 #endif
41
42 /* Foreign builtins. */
43 //include valgrind.h after stdint.h so that uintptr_t is defined for msys2 w64
44 #ifndef _WIN32
45 #include "valgrind/valgrind.h"
46 #endif
47
48 #if defined(_MSC_VER)
49 # define RUST_BUILTIN_API __declspec(dllexport)
50 #else
51 # define RUST_BUILTIN_API
52 #endif
53
54 #ifndef _WIN32
55 char*
56 rust_list_dir_val(struct dirent* entry_ptr) {
57 return entry_ptr->d_name;
58 }
59
60 int
61 rust_dir_get_mode(struct dirent* entry_ptr) {
62 #if defined(_DIRENT_HAVE_D_TYPE) || defined(__APPLE__)
63 switch (entry_ptr->d_type) {
64 case DT_BLK: return S_IFBLK;
65 case DT_CHR: return S_IFCHR;
66 case DT_FIFO: return S_IFIFO;
67 case DT_LNK: return S_IFLNK;
68 case DT_REG: return S_IFREG;
69 case DT_SOCK: return S_IFSOCK;
70 case DT_DIR: return S_IFDIR;
71 }
72 #endif
73 return -1;
74 }
75
76 ino_t
77 rust_dir_get_ino(struct dirent* entry_ptr) {
78 return entry_ptr->d_ino;
79 }
80
81 DIR*
82 rust_opendir(char *dirname) {
83 return opendir(dirname);
84 }
85
86 int
87 rust_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
88 return readdir_r(dirp, entry, result);
89 }
90
91 int
92 rust_dirent_t_size() {
93 return sizeof(struct dirent);
94 }
95 #endif
96
97 #if defined(_WIN32)
98 int
99 get_num_cpus() {
100 SYSTEM_INFO sysinfo;
101 GetSystemInfo(&sysinfo);
102
103 return (int) sysinfo.dwNumberOfProcessors;
104 }
105 #elif defined(__BSD__)
106 int
107 get_num_cpus() {
108 /* swiped from http://stackoverflow.com/questions/150355/
109 programmatically-find-the-number-of-cores-on-a-machine */
110
111 unsigned int numCPU;
112 int mib[4];
113 size_t len = sizeof(numCPU);
114
115 /* set the mib for hw.ncpu */
116 mib[0] = CTL_HW;
117 mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;
118
119 /* get the number of CPUs from the system */
120 sysctl(mib, 2, &numCPU, &len, NULL, 0);
121
122 if( numCPU < 1 ) {
123 mib[1] = HW_NCPU;
124 sysctl( mib, 2, &numCPU, &len, NULL, 0 );
125
126 if( numCPU < 1 ) {
127 numCPU = 1;
128 }
129 }
130 return numCPU;
131 }
132 #elif defined(__GNUC__)
133 int
134 get_num_cpus() {
135 return sysconf(_SC_NPROCESSORS_ONLN);
136 }
137 #endif
138
139 RUST_BUILTIN_API
140 uintptr_t
141 rust_get_num_cpus() {
142 return get_num_cpus();
143 }
144
145 uintptr_t
146 rust_running_on_valgrind() {
147 #ifdef _WIN32
148 return 0;
149 #else
150 return RUNNING_ON_VALGRIND;
151 #endif
152 }
153
154 #if defined(__DragonFly__)
155 #include <errno.h>
156 // In DragonFly __error() is an inline function and as such
157 // no symbol exists for it.
158 int *__dfly_error(void) { return __error(); }
159 #endif
160
161 #if defined(__Bitrig__)
162 #include <stdio.h>
163 #include <sys/param.h>
164 #include <sys/sysctl.h>
165 #include <limits.h>
166
167 int rust_get_path(void *p, size_t* sz)
168 {
169 int mib[4];
170 char *eq = NULL;
171 char *key = NULL;
172 char *val = NULL;
173 char **menv = NULL;
174 size_t maxlen, len;
175 int nenv = 0;
176 int i;
177
178 if ((p == NULL) && (sz == NULL))
179 return -1;
180
181 /* get the argv array */
182 mib[0] = CTL_KERN;
183 mib[1] = KERN_PROC_ARGS;
184 mib[2] = getpid();
185 mib[3] = KERN_PROC_ENV;
186
187 /* get the number of bytes needed to get the env */
188 maxlen = 0;
189 if (sysctl(mib, 4, NULL, &maxlen, NULL, 0) == -1)
190 return -1;
191
192 /* allocate the buffer */
193 if ((menv = calloc(maxlen, sizeof(char))) == NULL)
194 return -1;
195
196 /* get the env array */
197 if (sysctl(mib, 4, menv, &maxlen, NULL, 0) == -1)
198 {
199 free(menv);
200 return -1;
201 }
202
203 mib[3] = KERN_PROC_NENV;
204 len = sizeof(int);
205 /* get the length of env array */
206 if (sysctl(mib, 4, &nenv, &len, NULL, 0) == -1)
207 {
208 free(menv);
209 return -1;
210 }
211
212 /* find _ key and resolve the value */
213 for (i = 0; i < nenv; i++)
214 {
215 if ((eq = strstr(menv[i], "=")) == NULL)
216 continue;
217
218 key = menv[i];
219 val = eq + 1;
220 *eq = '\0';
221
222 if (strncmp(key, "PATH", maxlen) != 0)
223 continue;
224
225 if (p == NULL)
226 {
227 /* return the length of the value + NUL */
228 *sz = strnlen(val, maxlen) + 1;
229 free(menv);
230 return 0;
231 }
232 else
233 {
234 /* copy *sz bytes to the output buffer */
235 memcpy(p, val, *sz);
236 free(menv);
237 return 0;
238 }
239 }
240
241 free(menv);
242 return -1;
243 }
244
245 int rust_get_path_array(void * p, size_t * sz)
246 {
247 char *path, *str;
248 char **buf;
249 int i, num;
250 size_t len;
251
252 if ((p == NULL) && (sz == NULL))
253 return -1;
254
255 /* get the length of the PATH value */
256 if (rust_get_path(NULL, &len) == -1)
257 return -1;
258
259 if (len == 0)
260 return -1;
261
262 /* allocate the buffer */
263 if ((path = calloc(len, sizeof(char))) == NULL)
264 return -1;
265
266 /* get the PATH value */
267 if (rust_get_path(path, &len) == -1)
268 {
269 free(path);
270 return -1;
271 }
272
273 /* count the number of parts in the PATH */
274 num = 1;
275 for(str = path; *str != '\0'; str++)
276 {
277 if (*str == ':')
278 num++;
279 }
280
281 /* calculate the size of the buffer for the 2D array */
282 len = (num * sizeof(char*) + 1) + strlen(path) + 1;
283
284 if (p == NULL)
285 {
286 free(path);
287 *sz = len;
288 return 0;
289 }
290
291 /* make sure we have enough buffer space */
292 if (*sz < len)
293 {
294 free(path);
295 return -1;
296 }
297
298 /* zero out the buffer */
299 buf = (char**)p;
300 memset(buf, 0, *sz);
301
302 /* copy the data into the right place */
303 str = p + ((num+1) * sizeof(char*));
304 memcpy(str, path, strlen(path));
305
306 /* parse the path into it's parts */
307 for (i = 0; i < num && (buf[i] = strsep(&str, ":")) != NULL; i++) {;}
308 buf[num] = NULL;
309
310 free(path);
311 return 0;
312 }
313
314 int rust_get_argv_zero(void* p, size_t* sz)
315 {
316 int mib[4];
317 char **argv = NULL;
318 size_t len;
319
320 if ((p == NULL) && (sz == NULL))
321 return -1;
322
323 /* get the argv array */
324 mib[0] = CTL_KERN;
325 mib[1] = KERN_PROC_ARGS;
326 mib[2] = getpid();
327 mib[3] = KERN_PROC_ARGV;
328
329 /* request KERN_PROC_ARGV size */
330 len = 0;
331 if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1)
332 return -1;
333
334 /* allocate buffer to receive the values */
335 if ((argv = malloc(len)) == NULL)
336 return -1;
337
338 /* get the argv array */
339 if (sysctl(mib, 4, argv, &len, NULL, 0) == -1)
340 {
341 free(argv);
342 return -1;
343 }
344
345 /* get length of argv[0] */
346 len = strnlen(argv[0], len) + 1;
347
348 if (p == NULL)
349 {
350 *sz = len;
351 free(argv);
352 return 0;
353 }
354
355 if (*sz < len)
356 {
357 free(argv);
358 return -1;
359 }
360
361 memset(p, 0, len);
362 memcpy(p, argv[0], len);
363 free(argv);
364 return 0;
365 }
366
367 const char * rust_current_exe()
368 {
369 static char *self = NULL;
370 char *argv0;
371 char **paths;
372 size_t sz;
373 int i;
374 char buf[2*PATH_MAX], exe[2*PATH_MAX];
375
376 if (self != NULL)
377 return self;
378
379 if (rust_get_argv_zero(NULL, &sz) == -1)
380 return NULL;
381 if ((argv0 = calloc(sz, sizeof(char))) == NULL)
382 return NULL;
383 if (rust_get_argv_zero(argv0, &sz) == -1)
384 {
385 free(argv0);
386 return NULL;
387 }
388
389 /* if argv0 is a relative or absolute path, resolve it with realpath */
390 if ((*argv0 == '.') || (*argv0 == '/') || (strstr(argv0, "/") != NULL))
391 {
392 self = realpath(argv0, NULL);
393 free(argv0);
394 return self;
395 }
396
397 /* get the path array */
398 if (rust_get_path_array(NULL, &sz) == -1)
399 {
400 free(argv0);
401 return NULL;
402 }
403 if ((paths = calloc(sz, sizeof(char))) == NULL)
404 {
405 free(argv0);
406 return NULL;
407 }
408 if (rust_get_path_array(paths, &sz) == -1)
409 {
410 free(argv0);
411 free(paths);
412 return NULL;
413 }
414
415 for(i = 0; paths[i] != NULL; i++)
416 {
417 snprintf(buf, 2*PATH_MAX, "%s/%s", paths[i], argv0);
418 if (realpath(buf, exe) == NULL)
419 continue;
420
421 if (access(exe, F_OK | X_OK) == -1)
422 continue;
423
424 self = strdup(exe);
425 free(argv0);
426 free(paths);
427 return self;
428 }
429
430 free(argv0);
431 free(paths);
432 return NULL;
433 }
434
435 #elif defined(__OpenBSD__)
436
437 #include <sys/param.h>
438 #include <sys/sysctl.h>
439 #include <limits.h>
440
441 const char * rust_current_exe() {
442 static char *self = NULL;
443
444 if (self == NULL) {
445 int mib[4];
446 char **argv = NULL;
447 size_t argv_len;
448
449 /* initialize mib */
450 mib[0] = CTL_KERN;
451 mib[1] = KERN_PROC_ARGS;
452 mib[2] = getpid();
453 mib[3] = KERN_PROC_ARGV;
454
455 /* request KERN_PROC_ARGV size */
456 argv_len = 0;
457 if (sysctl(mib, 4, NULL, &argv_len, NULL, 0) == -1)
458 return (NULL);
459
460 /* allocate size */
461 if ((argv = malloc(argv_len)) == NULL)
462 return (NULL);
463
464 /* request KERN_PROC_ARGV */
465 if (sysctl(mib, 4, argv, &argv_len, NULL, 0) == -1) {
466 free(argv);
467 return (NULL);
468 }
469
470 /* get realpath if possible */
471 if ((argv[0] != NULL) && ((*argv[0] == '.') || (*argv[0] == '/')
472 || (strstr(argv[0], "/") != NULL)))
473
474 self = realpath(argv[0], NULL);
475 else
476 self = NULL;
477
478 /* cleanup */
479 free(argv);
480 }
481
482 return (self);
483 }
484
485 #endif
486
487 //
488 // Local Variables:
489 // mode: C++
490 // fill-column: 78;
491 // indent-tabs-mode: nil
492 // c-basic-offset: 4
493 // buffer-file-coding-system: utf-8-unix
494 // End:
495 //