Fixes PR130 (os::scandir invocation).
[cacao.git] / src / vm / os.hpp
1 /* src/vm/os.hpp - system (OS) functions
2
3    Copyright (C) 2007, 2008, 2009
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #ifndef _OS_HPP
28 #define _OS_HPP
29
30 #include "config.h"
31
32 // NOTE: In this file we check for all system headers, because we wrap
33 // all system calls into inline functions for better portability.
34
35 // Please don't include CACAO headers here as this header should be a
36 // very low-level one.
37
38 #if defined(HAVE_DIRENT_H)
39 # include <dirent.h>
40 #endif
41
42 #if defined(HAVE_DLFCN_H)
43 # include <dlfcn.h>
44 #endif
45
46 #if defined(HAVE_ERRNO_H)
47 # include <errno.h>
48 #endif
49
50 #if defined(HAVE_EXECINFO_H)
51 # include <execinfo.h>
52 #endif
53
54 #if defined(HAVE_FCNTL_H)
55 # include <fcntl.h>
56 #endif
57
58 #if defined(ENABLE_JRE_LAYOUT)
59 # if defined(HAVE_LIBGEN_H)
60 #  include <libgen.h>
61 # endif
62 #endif
63
64 #if defined(HAVE_SIGNAL_H)
65 # include <signal.h>
66 #endif
67
68 #if defined(HAVE_STDARG_H)
69 # include <stdarg.h>
70 #endif
71
72 #if defined(HAVE_STDINT_H)
73 # include <stdint.h>
74 #endif
75
76 #if defined(HAVE_STDIO_H)
77 # include <stdio.h>
78 #endif
79
80 #if defined(HAVE_STDLIB_H)
81 # include <stdlib.h>
82 #endif
83
84 #if defined(HAVE_STRING_H)
85 # include <string.h>
86 #endif
87
88 #if defined(HAVE_UNISTD_H)
89 # include <unistd.h>
90 #endif
91
92 #if defined(HAVE_SYS_MMAN_H)
93 # include <sys/mman.h>
94 #endif
95
96 #if defined(HAVE_SYS_SOCKET_H)
97 # include <sys/socket.h>
98 #endif
99
100 #if defined(HAVE_SYS_STAT_H)
101 # include <sys/stat.h>
102 #endif
103
104 #if defined(HAVE_SYS_TYPES_H)
105 # include <sys/types.h>
106 #endif
107
108
109 #ifdef __cplusplus
110
111 // Class wrapping system (OS) functions.
112 class os {
113 public:
114         // Inline functions.
115         static inline void    abort();
116         static inline int     accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
117         static inline int     access(const char *pathname, int mode);
118         static inline int     atoi(const char* nptr);
119         static inline int     backtrace(void** array, int size);
120         static inline char**  backtrace_symbols(void* const* array, int size) throw ();
121         static inline void*   calloc(size_t nmemb, size_t size);
122         static inline int     close(int fd);
123         static inline int     connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
124 #if defined(ENABLE_JRE_LAYOUT)
125         static inline char*   dirname(char* path);
126 #endif
127         static inline int     dlclose(void* handle);
128         static inline char*   dlerror(void);
129         static inline void*   dlopen(const char* filename, int flag);
130         static inline void*   dlsym(void* handle, const char* symbol);
131         static inline int     fclose(FILE* fp);
132         static inline FILE*   fopen(const char* path, const char* mode);
133         static inline int     fprintf(FILE* stream, const char* format, ...);
134         static inline size_t  fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
135         static inline void    free(void* ptr);
136         static inline char*   getenv(const char* name);
137         static inline int     gethostname(char* name, size_t len);
138         static inline int     getpagesize(void);
139         static inline int     getsockname(int s, struct sockaddr* name, socklen_t* namelen);
140         static inline int     getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen);
141         static inline int     listen(int sockfd, int backlog);
142         static inline void*   malloc(size_t size);
143         static inline void*   memcpy(void* dest, const void* src, size_t n);
144         static inline void*   memset(void* s, int c, size_t n);
145         static inline int     mprotect(void* addr, size_t len, int prot);
146         static inline ssize_t readlink(const char* path, char* buf, size_t bufsiz);
147         static inline int     scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
148         static inline ssize_t send(int s, const void* buf, size_t len, int flags);
149         static inline int     setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen);
150         static inline int     shutdown(int s, int how);
151         static inline int     socket(int domain, int type, int protocol);
152         static inline int     stat(const char* path, struct stat* buf);
153 #if defined(__SOLARIS__)
154         static inline int     str2sig(const char* str, int* signum);
155 #endif
156         static inline char*   strcat(char* dest, const char* src);
157         static inline int     strcmp(const char* s1, const char* s2);
158         static inline char*   strcpy(char* dest, const char* src);
159         static inline char*   strdup(const char* s);
160         static inline size_t  strlen(const char* s);
161         static inline char*   strerror(int errnum);
162
163         // Convenience functions.
164         static void  abort(const char* text, ...);
165         static void  abort_errnum(int errnum, const char* text, ...);
166         static void  abort_errno(const char* text, ...);
167         static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
168         static void  print_backtrace();
169         static int   processors_online();
170
171         // Template helper
172         template<class F1, class F2>
173         static int call_scandir(int (*scandir)(const char *, struct dirent ***, F1, F2), const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *));
174 };
175
176
177 inline void os::abort(void)
178 {
179 #if defined(HAVE_ABORT)
180         ::abort();
181 #else
182 # error abort not available
183 #endif
184 }
185
186 inline int os::accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
187 {
188 #if defined(HAVE_ACCEPT)
189         return ::accept(sockfd, addr, addrlen);
190 #else
191 # error accept not available
192 #endif
193 }
194
195 inline int os::access(const char* pathname, int mode)
196 {
197 #if defined(HAVE_ACCESS)
198         return ::access(pathname, mode);
199 #else
200 # error access not available
201 #endif
202 }
203
204 inline int os::atoi(const char* nptr)
205 {
206 #if defined(HAVE_ATOI)
207         return ::atoi(nptr);
208 #else
209 # error atoi not available
210 #endif
211 }
212
213 inline int os::backtrace(void** array, int size)
214 {
215 #if defined(HAVE_BACKTRACE)
216         return ::backtrace(array, size);
217 #else
218         fprintf(stderr, "os::backtrace: Not available.");
219         return 0;
220 #endif
221 }
222
223 inline char** os::backtrace_symbols(void* const* array, int size) throw ()
224 {
225 #if defined(HAVE_BACKTRACE_SYMBOLS)
226         return ::backtrace_symbols(array, size);
227 #else
228         fprintf(stderr, "os::backtrace_symbols: Not available.");
229         return NULL;
230 #endif
231 }
232
233 inline void* os::calloc(size_t nmemb, size_t size)
234 {
235 #if defined(HAVE_CALLOC)
236         return ::calloc(nmemb, size);
237 #else
238 # error calloc not available
239 #endif
240 }
241
242 inline int os::close(int fd)
243 {
244 #if defined(HAVE_CLOSE)
245         return ::close(fd);
246 #else
247 # error close not available
248 #endif
249 }
250
251 inline int os::connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)
252 {
253 #if defined(HAVE_CONNECT)
254         return ::connect(sockfd, serv_addr, addrlen);
255 #else
256 # error connect not available
257 #endif
258 }
259
260 #if defined(ENABLE_JRE_LAYOUT)
261 inline char* os::dirname(char* path)
262 {
263 #if defined(HAVE_DIRNAME)
264         return ::dirname(path);
265 #else
266 # error dirname not available
267 #endif
268 }
269 #endif
270
271 inline int os::dlclose(void* handle)
272 {
273 #if defined(HAVE_DLCLOSE)
274         return ::dlclose(handle);
275 #else
276 # error dlclose not available
277 #endif
278 }
279
280 inline char* os::dlerror(void)
281 {
282 #if defined(HAVE_DLERROR)
283         // At least FreeBSD defines dlerror() to return a const char*, so
284         // we simply cast it.
285         return (char*) ::dlerror();
286 #else
287 # error dlerror not available
288 #endif
289 }
290
291 inline void* os::dlopen(const char* filename, int flag)
292 {
293 #if defined(HAVE_DLOPEN)
294         return ::dlopen(filename, flag);
295 #else
296 # error dlopen not available
297 #endif
298 }
299
300 inline void* os::dlsym(void* handle, const char* symbol)
301 {
302 #if defined(HAVE_DLSYM)
303         return ::dlsym(handle, symbol);
304 #else
305 # error dlsym not available
306 #endif
307 }
308
309 inline int os::fclose(FILE* fp)
310 {
311 #if defined(HAVE_FCLOSE)
312         return ::fclose(fp);
313 #else
314 # error fclose not available
315 #endif
316 }
317
318 inline FILE* os::fopen(const char* path, const char* mode)
319 {
320 #if defined(HAVE_FOPEN)
321         return ::fopen(path, mode);
322 #else
323 # error fopen not available
324 #endif
325 }
326
327 inline int os::fprintf(FILE* stream, const char* format, ...)
328 {
329 #if defined(HAVE_FPRINTF)
330         va_list ap;
331         va_start(ap, format);
332         int result = ::vfprintf(stream, format, ap);
333         va_end(ap);
334         return result;
335 #else
336 # error fprintf not available
337 #endif
338 }
339
340 inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
341 {
342 #if defined(HAVE_FREAD)
343         return ::fread(ptr, size, nmemb, stream);
344 #else
345 # error fread not available
346 #endif
347 }
348
349 inline void os::free(void* ptr)
350 {
351 #if defined(HAVE_FREE)
352         ::free(ptr);
353 #else
354 # error free not available
355 #endif
356 }
357
358 inline static int system_fsync(int fd)
359 {
360 #if defined(HAVE_FSYNC)
361         return fsync(fd);
362 #else
363 # error fsync not available
364 #endif
365 }
366
367 inline static int system_ftruncate(int fd, off_t length)
368 {
369 #if defined(HAVE_FTRUNCATE)
370         return ftruncate(fd, length);
371 #else
372 # error ftruncate not available
373 #endif
374 }
375
376 inline char* os::getenv(const char* name)
377 {
378 #if defined(HAVE_GETENV)
379         return ::getenv(name);
380 #else
381 # error getenv not available
382 #endif
383 }
384
385 inline int os::gethostname(char* name, size_t len)
386 {
387 #if defined(HAVE_GETHOSTNAME)
388         return ::gethostname(name, len);
389 #else
390 # error gethostname not available
391 #endif
392 }
393
394 inline int os::getpagesize(void)
395 {
396 #if defined(HAVE_GETPAGESIZE)
397         return ::getpagesize();
398 #else
399 # error getpagesize not available
400 #endif
401 }
402
403 inline int os::getsockname(int s, struct sockaddr* name, socklen_t* namelen)
404 {
405 #if defined(HAVE_GETSOCKNAME)
406         return ::getsockname(s, name, namelen);
407 #else
408 # error getsockname not available
409 #endif
410 }
411
412 inline int os::getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen)
413 {
414 #if defined(HAVE_GETSOCKOPT)
415         return ::getsockopt(s, level, optname, optval, optlen);
416 #else
417 # error getsockopt not available
418 #endif
419 }
420
421 inline int os::listen(int sockfd, int backlog)
422 {
423 #if defined(HAVE_LISTEN)
424         return ::listen(sockfd, backlog);
425 #else
426 # error listen not available
427 #endif
428 }
429
430 inline static off_t system_lseek(int fildes, off_t offset, int whence)
431 {
432 #if defined(HAVE_LSEEK)
433         return lseek(fildes, offset, whence);
434 #else
435 # error lseek not available
436 #endif
437 }
438
439 inline void* os::malloc(size_t size)
440 {
441 #if defined(HAVE_MALLOC)
442         return ::malloc(size);
443 #else
444 # error malloc not available
445 #endif
446 }
447
448 inline void* os::memcpy(void* dest, const void* src, size_t n)
449 {
450 #if defined(HAVE_MEMCPY)
451         return ::memcpy(dest, src, n);
452 #else
453 # error memcpy not available
454 #endif
455 }
456
457 inline void* os::memset(void* s, int c, size_t n)
458 {
459 #if defined(HAVE_MEMSET)
460         return ::memset(s, c, n);
461 #else
462 # error memset not available
463 #endif
464 }
465
466 inline int os::mprotect(void* addr, size_t len, int prot)
467 {
468 #if defined(HAVE_MPROTECT)
469         return ::mprotect(addr, len, prot);
470 #else
471 # error mprotect not available
472 #endif
473 }
474
475 inline static int system_open(const char *pathname, int flags, mode_t mode)
476 {
477 #if defined(HAVE_OPEN)
478         return open(pathname, flags, mode);
479 #else
480 # error open not available
481 #endif
482 }
483
484 inline static ssize_t system_read(int fd, void *buf, size_t count)
485 {
486 #if defined(HAVE_READ)
487         return read(fd, buf, count);
488 #else
489 # error read not available
490 #endif
491 }
492
493 inline ssize_t os::readlink(const char* path, char* buf, size_t bufsiz)
494 {
495 #if defined(HAVE_READLINK)
496         return ::readlink(path, buf, bufsiz);
497 #else
498 # error readlink not available
499 #endif
500 }
501
502 inline static void *system_realloc(void *ptr, size_t size)
503 {
504 #if defined(HAVE_REALLOC)
505         return realloc(ptr, size);
506 #else
507 # error realloc not available
508 #endif
509 }
510
511 template<class F1, class F2>
512 inline int os::call_scandir(int (*scandir)(const char *, struct dirent ***, F1, F2), const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
513 {
514         return scandir(dir, namelist, (F1) filter, (F2) compar);
515 }
516
517 inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
518 {
519 #if defined(HAVE_SCANDIR)
520         return call_scandir(::scandir, dir, namelist, filter, compar);
521 #else
522 # error scandir not available
523 #endif
524 }
525
526 inline ssize_t os::send(int s, const void* buf, size_t len, int flags)
527 {
528         // TODO Should be restartable on Linux and interruptible on Solaris.
529 #if defined(HAVE_SEND)
530         return ::send(s, buf, len, flags);
531 #else
532 # error send not available
533 #endif
534 }
535
536 inline int os::setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen)
537 {
538 #if defined(HAVE_SETSOCKOPT)
539         return ::setsockopt(s, level, optname, optval, optlen);
540 #else
541 # error setsockopt not available
542 #endif
543 }
544
545 inline int os::shutdown(int s, int how)
546 {
547 #if defined(HAVE_SHUTDOWN)
548         return ::shutdown(s, how);
549 #else
550 # error shutdown not available
551 #endif
552 }
553
554 inline int os::socket(int domain, int type, int protocol)
555 {
556 #if defined(HAVE_SOCKET)
557         return ::socket(domain, type, protocol);
558 #else
559 # error socket not available
560 #endif
561 }
562
563 inline int os::stat(const char* path, struct stat* buf)
564 {
565 #if defined(HAVE_STAT)
566         return ::stat(path, buf);
567 #else
568 # error stat not available
569 #endif
570 }
571
572 #if defined(__SOLARIS__)
573 inline int os::str2sig(const char* str, int* signum)
574 {
575 #if defined(HAVE_STR2SIG)
576         return ::str2sig(str, signum);
577 #else
578 # error str2sig not available
579 #endif
580 }
581 #endif
582
583 inline char* os::strcat(char* dest, const char* src)
584 {
585 #if defined(HAVE_STRCAT)
586         return ::strcat(dest, src);
587 #else
588 # error strcat not available
589 #endif
590 }
591
592 inline int os::strcmp(const char* s1, const char* s2)
593 {
594 #if defined(HAVE_STRCMP)
595         return ::strcmp(s1, s2);
596 #else
597 # error strcmp not available
598 #endif
599 }
600
601 inline char* os::strcpy(char* dest, const char* src)
602 {
603 #if defined(HAVE_STRCPY)
604         return ::strcpy(dest, src);
605 #else
606 # error strcpy not available
607 #endif
608 }
609
610 inline char* os::strdup(const char* s)
611 {
612 #if defined(HAVE_STRDUP)
613         return ::strdup(s);
614 #else
615 # error strdup not available
616 #endif
617 }
618
619 inline char* os::strerror(int errnum)
620 {
621 #if defined(HAVE_STRERROR)
622         return ::strerror(errnum);
623 #else
624 # error strerror not available
625 #endif
626 }
627
628 inline size_t os::strlen(const char* s)
629 {
630 #if defined(HAVE_STRLEN)
631         return ::strlen(s);
632 #else
633 # error strlen not available
634 #endif
635 }
636
637 inline static ssize_t system_write(int fd, const void *buf, size_t count)
638 {
639 #if defined(HAVE_WRITE)
640         return write(fd, buf, count);
641 #else
642 # error write not available
643 #endif
644 }
645
646 #else
647
648 void*  os_mmap_anonymous(void *addr, size_t len, int prot, int flags);
649
650 void   os_abort(void);
651 int    os_access(const char* pathname, int mode);
652 int    os_atoi(const char* nptr);
653 void*  os_calloc(size_t nmemb, size_t size);
654 char*  os_dirname(char* path);
655 char*  os_dlerror(void);
656 void*  os_dlsym(void* handle, const char* symbol);
657 int    os_fclose(FILE* fp);
658 FILE*  os_fopen(const char* path, const char* mode);
659 size_t os_fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
660 void   os_free(void* ptr);
661 int    os_getpagesize(void);
662 void*  os_memcpy(void* dest, const void* src, size_t n);
663 void*  os_memset(void* s, int c, size_t n);
664 int    os_mprotect(void* addr, size_t len, int prot);
665 int    os_scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
666 int    os_stat(const char* path, struct stat* buf);
667 char*  os_strcat(char* dest, const char* src);
668 char*  os_strcpy(char* dest, const char* src);
669 char*  os_strdup(const char* s);
670 int    os_strlen(const char* s);
671
672 #endif
673
674 #endif // _OS_HPP
675
676
677 /*
678  * These are local overrides for various environment variables in Emacs.
679  * Please do not remove this and leave it at the end of the file, where
680  * Emacs will automagically detect them.
681  * ---------------------------------------------------------------------
682  * Local variables:
683  * mode: c++
684  * indent-tabs-mode: t
685  * c-basic-offset: 4
686  * tab-width: 4
687  * End:
688  * vim:noexpandtab:sw=4:ts=4:
689  */