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