2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
30 #ifdef HAVE_SYS_TIME_H
36 #define NO_DIR_HANDLES
38 typedef long long os_off_t
;
39 typedef int64_t os_time_t
;
81 typedef struct os2_handle
*handle_t
;
82 #define handle_is_valid(h) ((h) != NULL)
83 #define handle_none NULL
84 uintptr_t os_handle_to_number(handle_t h
);
85 handle_t
os_number_to_handle(uintptr_t n
, bool sckt
, ajla_error_t
*err
);
87 typedef char *dir_handle_t
;
88 #define dir_handle_is_valid(h) ((h) != NULL)
91 typedef unsigned char sig_state_t
;
92 typedef unsigned signal_seq_t
;
96 struct dl_handle_t
*os_dlopen(const char *filename
, ajla_error_t
*err
, char **err_msg
);
97 void os_dlclose(struct dl_handle_t
*dlh
);
98 bool os_dlsym(struct dl_handle_t
*dlh
, const char *symbol
, void **result
);
100 #define os_getaddrinfo_is_thread_safe() false
102 ULONG APIENTRY
os2_exception_handler(PEXCEPTIONREPORTRECORD
, struct _EXCEPTIONREGISTRATIONRECORD
*, PCONTEXTRECORD
, PVOID
);
104 #elif defined(OS_WIN32)
106 #include <sys/stat.h>
109 #define NO_DIR_HANDLES
111 typedef int64_t os_off_t
;
112 typedef int64_t os_time_t
;
139 unsigned long f_fsid
;
155 typedef struct win32_handle
*handle_t
;
156 #define handle_is_valid(h) ((h) != NULL)
157 #define handle_none NULL
158 uintptr_t os_handle_to_number(handle_t h
);
159 handle_t
os_number_to_handle(uintptr_t n
, bool sckt
, ajla_error_t
*err
);
161 typedef char *dir_handle_t
;
162 #define dir_handle_is_valid(h) ((h) != NULL)
163 #define dir_none NULL
165 typedef unsigned char sig_state_t
;
166 typedef uint64_t signal_seq_t
;
169 #define O_NONBLOCK 0x40000000
181 #define S_IFIFO 0010000
182 #define S_IFCHR 0020000
183 #define S_IFDIR 0040000
184 #define S_IFBLK 0060000
185 #define S_IFREG 0100000
186 #define S_IFLNK 0120000
187 #define S_IFSOCK 0140000
188 #define S_IFMT 0170000
189 #define S_ISFIFO(x) (((x) & S_IFMT) == S_IFIFO)
190 #define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
191 #define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
192 #define S_ISBLK(x) (((x) & S_IFMT) == S_IFBLK)
193 #define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
194 #define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
195 #define S_ISSOCK(x) (((x) & S_IFMT) == S_IFSOCK)
199 int os_getpagesize(void);
200 void *os_mmap(void *ptr
, size_t size
, int prot
, int flags
, handle_t h
, os_off_t off
, ajla_error_t
*err
);
201 void os_munmap(void *ptr
, size_t size
, bool file
);
202 bool os_mprotect(void *ptr
, size_t size
, int prot
, ajla_error_t
*err
);
203 #define MAP_FAILED ((void *)-1)
208 #define MAP_ANONYMOUS 1
209 #define MAP_PRIVATE 2
212 #define MAP_NORESERVE 16
213 #define MAP_ALIGNED(x) (32 * (x))
214 #define MAP_ALIGNED_BITS(m) ((m) >> 5)
216 #define OS_HAS_DLOPEN
218 struct dl_handle_t
*os_dlopen(const char *filename
, ajla_error_t
*err
, char **err_msg
);
219 void os_dlclose(struct dl_handle_t
*dlh
);
220 bool os_dlsym(struct dl_handle_t
*dlh
, const char *symbol
, void **result
);
222 bool os_getaddrinfo_is_thread_safe(void);
224 void os_get_environment(char **str
, size_t *l
);
228 #ifdef HAVE_SYS_TIME_H
229 #include <sys/time.h>
234 #ifdef HAVE_UCONTEXT_H
235 #include <ucontext.h>
237 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
238 #include <sys/utsname.h>
240 #include <sys/stat.h>
241 #ifdef HAVE_SYS_STATVFS_H
242 #include <sys/statvfs.h>
243 #elif defined(HAVE_SYS_VFS_H)
248 #if !defined(HAVE_FCHDIR) || defined(OS_DOS) || defined(OS_CYGWIN) || defined(UNUSUAL_NO_DIR_HANDLES)
249 #define NO_DIR_HANDLES
252 #if defined(__hpux) && !defined(__LP64__)
253 #if defined(HAVE_FSTAT64) && defined(HAVE_FSTATVFS64) && defined(HAVE_FTRUNCATE64) && defined(HAVE_LSEEK64) && defined(HAVE_LSTAT64) && defined(HAVE_MMAP64) && defined(HAVE_OPEN64) && defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) && defined(HAVE_STAT64) && defined(HAVE_STATVFS64) && defined(HAVE_TRUNCATE64)
254 #define OS_USE_LARGEFILE64_SOURCE
258 #ifdef OS_USE_LARGEFILE64_SOURCE
259 typedef off64_t os_off_t
;
260 typedef struct stat64 os_stat_t
;
261 typedef struct statvfs64 os_statvfs_t
;
263 typedef off_t os_off_t
;
264 typedef struct stat os_stat_t
;
265 #if defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)
266 typedef struct statvfs os_statvfs_t
;
270 #if !defined(OS_USE_LARGEFILE64_SOURCE) && !defined(HAVE_STATVFS) && !defined(HAVE_FSTATVFS)
280 unsigned long f_fsid
;
286 typedef time_t os_time_t
;
287 typedef struct termios os_termios_t
;
289 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
290 typedef struct utsname os_utsname_t
;
300 typedef int handle_t
;
301 #define handle_is_valid(h) ((h) >= 0)
302 #define handle_none -1
303 #define os_handle_to_number(h) ((uintptr_t)(h))
304 handle_t
os_number_to_handle(uintptr_t n
, bool sckt
, ajla_error_t
*err
);
306 #ifndef NO_DIR_HANDLES
307 typedef int dir_handle_t
;
308 #define dir_handle_is_valid(h) ((h) >= 0)
309 #define dir_none (-1)
311 typedef char *dir_handle_t
;
312 #define dir_handle_is_valid(h) ((h) != NULL)
313 #define dir_none NULL
316 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
317 #include <sys/mman.h>
319 int os_getpagesize(void);
320 void *os_mmap(void *ptr
, size_t size
, int prot
, int flags
, handle_t h
, os_off_t off
, ajla_error_t
*err
);
321 void os_munmap(void *ptr
, size_t size
, bool file
);
322 bool os_mprotect(void *ptr
, size_t size
, int prot
, ajla_error_t
*err
);
324 #define MAP_FAILED ((void *)-1)
326 #ifndef MAP_ANONYMOUS
327 #define MAP_ANONYMOUS MAP_ANON
329 #ifndef MAP_NORESERVE
330 #define MAP_NORESERVE 0
332 #if defined(__linux__) && defined(HAVE_MREMAP)
333 #define OS_HAS_MREMAP
334 void *os_mremap(void *old_ptr
, size_t old_size
, size_t new_size
, int flags
, void *new_ptr
, ajla_error_t
*err
);
338 #if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) && defined(HAVE_SIGFILLSET)
339 typedef sigset_t sig_state_t
;
340 #define USE_SIGPROCMASK
342 typedef int sig_state_t
;
344 typedef sig_atomic_t signal_seq_t
;
345 #ifdef HAVE_SIGACTION
346 #define OS_HAS_SIGNALS
349 #if defined(OS_HAS_SIGNALS) && defined(SA_SIGINFO) && defined(HAVE_UCONTEXT_H)
350 #define OS_SUPPORTS_TRAPS (!dll)
352 #define OS_SUPPORTS_TRAPS 0
355 #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
356 #define OS_HAS_DLOPEN
358 struct dl_handle_t
*os_dlopen(const char *filename
, ajla_error_t
*err
, char **err_msg
);
359 void os_dlclose(struct dl_handle_t
*dlh
);
360 bool os_dlsym(struct dl_handle_t
*dlh
, const char *symbol
, void **result
);
363 #if defined(HAVE_GETADDRINFO) && (defined(HAVE_HAVE_GETNAMEINFO) || !defined(HAVE_GETHOSTBYADDR))
364 #define os_getaddrinfo_is_thread_safe() true
366 #define os_getaddrinfo_is_thread_safe() false
372 uint32_t os_get_last_error(void);
373 uint32_t os_get_last_socket_error(void);
376 void os_code_invalidate_cache(uint8_t *code
, size_t code_size
, bool set_exec
);
377 void *os_code_map(uint8_t *code
, size_t code_size
, ajla_error_t
*err
);
378 void os_code_unmap(void *mapped_code
, size_t code_size
);
381 static inline char os_path_separator(void)
383 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
390 static inline bool os_is_path_separator(char c
)
392 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32) || defined(OS_CYGWIN)
393 if (c
== '\\' || c
== ':')
399 static inline bool os_is_env_separator(char c
)
401 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
407 bool os_path_is_absolute(const char *path
);
410 extern dir_handle_t os_cwd
;
411 bool os_set_cwd(dir_handle_t h
, ajla_error_t
*err
);
412 void os_set_original_cwd(void);
415 void os_block_signals(sig_state_t
*set
);
416 void os_unblock_signals(const sig_state_t
*set
);
418 void os_background(void);
419 bool os_foreground(void);
421 void os_set_cloexec(handle_t h
);
422 handle_t
os_open(dir_handle_t dir
, const char *path
, int flags
, int mode
, ajla_error_t
*err
);
423 bool os_pipe(handle_t result
[2], int nonblock_flags
, ajla_error_t
*err
);
424 void os_close_handle(handle_t h
);
425 void os_close(handle_t h
);
426 unsigned os_n_std_handles(void);
427 handle_t
os_get_std_handle(unsigned p
);
428 #define OS_RW_ERROR -1
429 #define OS_RW_WOULDBLOCK -2
430 ssize_t
os_read(handle_t h
, char *buffer
, int size
, ajla_error_t
*err
);
431 ssize_t
os_write(handle_t h
, const char *buffer
, int size
, ajla_error_t
*err
);
432 ssize_t
os_pread(handle_t h
, char *buffer
, int size
, os_off_t off
, ajla_error_t
*err
);
433 ssize_t
os_pwrite(handle_t h
, const char *buffer
, int size
, os_off_t off
, ajla_error_t
*err
);
434 bool os_lseek(handle_t
, unsigned mode
, os_off_t off
, os_off_t
*result
, ajla_error_t
*err
);
435 bool os_ftruncate(handle_t h
, os_off_t size
, ajla_error_t
*err
);
436 bool os_fallocate(handle_t h
, os_off_t position
, os_off_t size
, ajla_error_t
*err
);
437 bool os_clone_range(handle_t src_h
, os_off_t src_pos
, handle_t dst_h
, os_off_t dst_pos
, os_off_t len
, ajla_error_t
*err
);
438 bool os_fsync(handle_t h
, unsigned mode
, ajla_error_t
*err
);
439 int os_charset(void);
440 int os_charset_console(void);
441 struct console_read_packet
{
452 int32_t prev_buttons
, buttons
;
458 #define CONSOLE_PACKET_ENTRIES (sizeof(struct console_read_packet) / sizeof(int32_t))
459 ssize_t
os_read_console_packet(handle_t h
, struct console_read_packet
*result
, ajla_error_t
*err
);
460 struct console_write_packet
{
466 int32_t data
[FLEXIBLE_ARRAY_GCC
];
478 bool os_write_console_packet(handle_t h
, struct console_write_packet
*packet
, ajla_error_t
*err
);
480 dir_handle_t
os_dir_root(ajla_error_t
*err
);
481 dir_handle_t
os_dir_cwd(ajla_error_t
*err
);
482 dir_handle_t
os_dir_open(dir_handle_t dir
, const char *path
, int flags
, ajla_error_t
*err
);
483 void os_dir_close(dir_handle_t h
);
484 char *os_dir_path(dir_handle_t h
, ajla_error_t
*err
);
486 bool os_dir_read(dir_handle_t h
, char ***files
, size_t *n_files
, ajla_error_t
*err
);
487 void os_dir_free(char **files
, size_t n_files
);
489 unsigned os_dev_t_major(dev_t dev
);
490 unsigned os_dev_t_minor(dev_t dev
);
491 bool os_fstat(handle_t h
, os_stat_t
*st
, ajla_error_t
*err
);
492 bool os_stat(dir_handle_t dir
, const char *path
, bool lnk
, os_stat_t
*st
, ajla_error_t
*err
);
493 char *os_readlink(dir_handle_t dir
, const char *path
, ajla_error_t
*err
);
494 bool os_fstatvfs(handle_t h
, os_statvfs_t
*st
, ajla_error_t
*err
);
495 bool os_dstatvfs(dir_handle_t dir
, os_statvfs_t
*st
, ajla_error_t
*err
);
496 bool os_dir_action(dir_handle_t dir
, const char *path
, int action
, int mode
, ajla_time_t major
, ajla_time_t minor
, const char *syml
, ajla_error_t
*err
);
497 bool os_dir2_action(dir_handle_t dir
, const char *path
, int action
, dir_handle_t src_dir
, const char *src_path
, ajla_error_t
*err
);
498 bool os_drives(char **drives
, size_t *drives_l
, ajla_error_t
*err
);
500 bool os_tcgetattr(handle_t h
, os_termios_t
*t
, ajla_error_t
*err
);
501 bool os_tcsetattr(handle_t h
, const os_termios_t
*t
, ajla_error_t
*err
);
502 void os_tcflags(os_termios_t
*t
, int flags
);
503 bool os_tty_size(handle_t h
, int *nx
, int *ny
, int *ox
, int *oy
, ajla_error_t
*err
);
504 const char *os_get_path_to_exe(void);
506 ajla_time_t
os_time_t_to_ajla_time(os_time_t sec
);
507 #ifdef HAVE_STRUCT_TIMESPEC
508 ajla_time_t
os_timespec_to_ajla_time(const struct timespec
*ts
);
510 ajla_time_t
os_time_real(void);
511 ajla_time_t
os_time_monotonic(void);
512 bool os_time_to_calendar(ajla_time_t t
, bool local
, int *year
, int *month
, int *day
, int *hour
, int *min
, int *sec
, int *usec
, int *yday
, int *wday
, int *is_dst
, ajla_error_t
*err
);
513 bool os_calendar_to_time(bool local
, int year
, int month
, int day
, int hour
, int min
, int sec
, int usec
, int is_dst
, ajla_time_t
*t
, ajla_error_t
*err
);
515 const char *os_get_flavor(void);
516 void os_get_uname(os_utsname_t
*un
);
517 bool os_kernel_version(const char *sys
, const char *vers
);
518 char *os_get_host_name(ajla_error_t
*err
);
522 struct proc_handle
*os_proc_spawn(dir_handle_t wd
, const char *path
, size_t n_handles
, handle_t
*src
, int *target
, char * const args
[], char *envc
, ajla_error_t
*err
);
523 void os_proc_free_handle(struct proc_handle
*ph
);
524 bool os_proc_register_wait(struct proc_handle
*ph
, mutex_t
**mutex_to_lock
, struct list
*list_entry
, int *status
);
525 void os_proc_check_all(void);
527 int os_signal_handle(const char *str
, signal_seq_t
*seq
, ajla_error_t
*err
);
528 void os_signal_unhandle(int sig
);
529 signal_seq_t
os_signal_seq(int sig
);
530 bool os_signal_wait(int sig
, signal_seq_t seq
, mutex_t
**mutex_to_lock
, struct list
*list_entry
);
531 void os_signal_check_all(void);
532 #if defined(OS_HAS_SIGNALS) && defined(SA_SIGINFO)
533 void os_signal_trap(int sig
, void (*handler
)(int, siginfo_t
*, void *));
534 void os_signal_untrap(int sig
);
537 handle_t
os_socket(int domain
, int type
, int protocol
, ajla_error_t
*err
);
538 bool os_bind_connect(bool bnd
, handle_t h
, unsigned char *addr
, size_t addr_len
, ajla_error_t
*err
);
539 bool os_connect_completed(handle_t h
, ajla_error_t
*err
);
540 bool os_listen(handle_t h
, ajla_error_t
*err
);
541 int os_accept(handle_t h
, handle_t
*result
, ajla_error_t
*err
);
542 bool os_getsockpeername(bool peer
, handle_t h
, unsigned char **addr
, size_t *addr_len
, ajla_error_t
*err
);
544 unsigned char *address
;
545 size_t address_length
;
546 struct tree_entry entry
;
548 ssize_t
os_recvfrom(handle_t h
, char *buffer
, size_t len
, int flags
, unsigned char **addr
, size_t *addr_len
, ajla_error_t
*err
);
549 ssize_t
os_sendto(handle_t h
, const char *buffer
, size_t len
, int flags
, unsigned char *addr
, size_t addr_len
, ajla_error_t
*err
);
550 bool os_getsockopt(handle_t h
, int level
, int option
, char **buffer
, size_t *buffer_len
, ajla_error_t
*err
);
551 bool os_setsockopt(handle_t h
, int level
, int option
, const char *buffer
, size_t buffer_len
, ajla_error_t
*err
);
552 bool os_getaddrinfo(const char *host
, int port
, struct address
**result
, size_t *result_l
, ajla_error_t
*err
);
553 char *os_getnameinfo(unsigned char *addr
, size_t addr_len
, ajla_error_t
*err
);
555 const char *os_decode_error(ajla_error_t error
, char *(*tls_buffer
)(void));
558 #define OS_HAVE_NOTIFY_PIPE
559 extern handle_t os_notify_pipe
[2];
560 void os_notify(void);
561 bool os_drain_notify_pipe(void);
562 void os_shutdown_notify_pipe(void);
564 static inline void os_notify(void) { }
565 static inline void os_shutdown_notify_pipe(void) { }
569 bool dos_poll_devices(void);
570 void dos_yield(void);
571 void dos_wait_on_packet(mutex_t
**mutex_to_lock
, struct list
*list_entry
);
577 void os_init_multithreaded(void);
578 void os_done_multithreaded(void);