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