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