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)
249 #if !defined(HAVE_FCHDIR) || defined(OS_DOS) || defined(OS_CYGWIN) || defined(UNUSUAL_NO_DIR_HANDLES)
250 #define NO_DIR_HANDLES
253 #if defined(__hpux) && !defined(__LP64__)
254 #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)
255 #define OS_USE_LARGEFILE64_SOURCE
259 #ifdef OS_USE_LARGEFILE64_SOURCE
260 typedef off64_t os_off_t
;
261 typedef struct stat64 os_stat_t
;
262 typedef struct statvfs64 os_statvfs_t
;
264 typedef off_t os_off_t
;
265 typedef struct stat os_stat_t
;
266 #if defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)
267 typedef struct statvfs os_statvfs_t
;
271 #if !defined(OS_USE_LARGEFILE64_SOURCE) && !defined(HAVE_STATVFS) && !defined(HAVE_FSTATVFS)
281 unsigned long f_fsid
;
287 typedef time_t os_time_t
;
288 typedef struct termios os_termios_t
;
290 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
291 typedef struct utsname os_utsname_t
;
301 typedef int handle_t
;
302 #define handle_is_valid(h) ((h) >= 0)
303 #define handle_none -1
304 #define os_handle_to_number(h) ((uintptr_t)(h))
305 handle_t
os_number_to_handle(uintptr_t n
, bool sckt
, ajla_error_t
*err
);
307 #ifndef NO_DIR_HANDLES
308 typedef int dir_handle_t
;
309 #define dir_handle_is_valid(h) ((h) >= 0)
310 #define dir_none (-1)
312 typedef char *dir_handle_t
;
313 #define dir_handle_is_valid(h) ((h) != NULL)
314 #define dir_none NULL
317 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
318 #include <sys/mman.h>
320 int os_getpagesize(void);
321 void *os_mmap(void *ptr
, size_t size
, int prot
, int flags
, handle_t h
, os_off_t off
, ajla_error_t
*err
);
322 void os_munmap(void *ptr
, size_t size
, bool file
);
323 bool os_mprotect(void *ptr
, size_t size
, int prot
, ajla_error_t
*err
);
325 #define MAP_FAILED ((void *)-1)
327 #ifndef MAP_ANONYMOUS
328 #define MAP_ANONYMOUS MAP_ANON
330 #ifndef MAP_NORESERVE
331 #define MAP_NORESERVE 0
333 #if defined(__linux__) && defined(HAVE_MREMAP)
334 #define OS_HAS_MREMAP
335 void *os_mremap(void *old_ptr
, size_t old_size
, size_t new_size
, int flags
, void *new_ptr
, ajla_error_t
*err
);
339 #if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) && defined(HAVE_SIGFILLSET)
340 typedef sigset_t sig_state_t
;
341 #define USE_SIGPROCMASK
343 typedef int sig_state_t
;
345 typedef sig_atomic_t signal_seq_t
;
346 #ifdef HAVE_SIGACTION
347 #define OS_HAS_SIGNALS
350 #if defined(OS_HAS_SIGNALS) && defined(SA_SIGINFO) && defined(HAVE_UCONTEXT_H)
351 #define OS_SUPPORTS_TRAPS (!dll)
353 #define OS_SUPPORTS_TRAPS 0
356 #if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
357 #define OS_HAS_DLOPEN
359 struct dl_handle_t
*os_dlopen(const char *filename
, ajla_error_t
*err
, char **err_msg
);
360 void os_dlclose(struct dl_handle_t
*dlh
);
361 bool os_dlsym(struct dl_handle_t
*dlh
, const char *symbol
, void **result
);
364 #if defined(HAVE_GETADDRINFO) && (defined(HAVE_HAVE_GETNAMEINFO) || !defined(HAVE_GETHOSTBYADDR))
365 #define os_getaddrinfo_is_thread_safe() true
367 #define os_getaddrinfo_is_thread_safe() false
373 uint32_t os_get_last_error(void);
374 uint32_t os_get_last_socket_error(void);
377 void os_code_invalidate_cache(uint8_t *code
, size_t code_size
, bool set_exec
);
378 void *os_code_map(uint8_t *code
, size_t code_size
, ajla_error_t
*err
);
379 void os_code_unmap(void *mapped_code
, size_t code_size
);
382 static inline char os_path_separator(void)
384 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
391 static inline bool os_is_path_separator(char c
)
393 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32) || defined(OS_CYGWIN)
394 if (c
== '\\' || c
== ':')
400 static inline bool os_is_env_separator(char c
)
402 #if defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
408 bool os_path_is_absolute(const char *path
);
411 extern dir_handle_t os_cwd
;
412 bool os_set_cwd(dir_handle_t h
, ajla_error_t
*err
);
413 void os_set_original_cwd(void);
416 void os_block_signals(sig_state_t
*set
);
417 void os_unblock_signals(const sig_state_t
*set
);
419 void os_background(void);
420 bool os_foreground(void);
422 void os_set_cloexec(handle_t h
);
423 handle_t
os_open(dir_handle_t dir
, const char *path
, int flags
, int mode
, ajla_error_t
*err
);
424 bool os_pipe(handle_t result
[2], int nonblock_flags
, ajla_error_t
*err
);
425 void os_close_handle(handle_t h
);
426 void os_close(handle_t h
);
427 unsigned os_n_std_handles(void);
428 handle_t
os_get_std_handle(unsigned p
);
429 #define OS_RW_ERROR -1
430 #define OS_RW_WOULDBLOCK -2
431 ssize_t
os_read(handle_t h
, char *buffer
, int size
, ajla_error_t
*err
);
432 ssize_t
os_write(handle_t h
, const char *buffer
, int size
, ajla_error_t
*err
);
433 ssize_t
os_pread(handle_t h
, char *buffer
, int size
, os_off_t off
, ajla_error_t
*err
);
434 ssize_t
os_pwrite(handle_t h
, const char *buffer
, int size
, os_off_t off
, ajla_error_t
*err
);
435 bool os_lseek(handle_t
, unsigned mode
, os_off_t off
, os_off_t
*result
, ajla_error_t
*err
);
436 bool os_ftruncate(handle_t h
, os_off_t size
, ajla_error_t
*err
);
437 bool os_fallocate(handle_t h
, os_off_t position
, os_off_t size
, ajla_error_t
*err
);
438 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
);
439 bool os_fsync(handle_t h
, unsigned mode
, ajla_error_t
*err
);
440 int os_charset(void);
441 int os_charset_console(void);
442 struct console_read_packet
{
453 int32_t prev_buttons
, buttons
;
459 #define CONSOLE_PACKET_ENTRIES (sizeof(struct console_read_packet) / sizeof(int32_t))
460 ssize_t
os_read_console_packet(handle_t h
, struct console_read_packet
*result
, ajla_error_t
*err
);
461 struct console_write_packet
{
467 int32_t data
[FLEXIBLE_ARRAY_GCC
];
479 bool os_write_console_packet(handle_t h
, struct console_write_packet
*packet
, ajla_error_t
*err
);
481 dir_handle_t
os_dir_root(ajla_error_t
*err
);
482 dir_handle_t
os_dir_cwd(ajla_error_t
*err
);
483 dir_handle_t
os_dir_open(dir_handle_t dir
, const char *path
, int flags
, ajla_error_t
*err
);
484 void os_dir_close(dir_handle_t h
);
485 char *os_dir_path(dir_handle_t h
, ajla_error_t
*err
);
487 bool os_dir_read(dir_handle_t h
, char ***files
, size_t *n_files
, ajla_error_t
*err
);
488 void os_dir_free(char **files
, size_t n_files
);
490 unsigned os_dev_t_major(dev_t dev
);
491 unsigned os_dev_t_minor(dev_t dev
);
492 bool os_fstat(handle_t h
, os_stat_t
*st
, ajla_error_t
*err
);
493 bool os_stat(dir_handle_t dir
, const char *path
, bool lnk
, os_stat_t
*st
, ajla_error_t
*err
);
494 char *os_readlink(dir_handle_t dir
, const char *path
, ajla_error_t
*err
);
495 bool os_fstatvfs(handle_t h
, os_statvfs_t
*st
, ajla_error_t
*err
);
496 bool os_dstatvfs(dir_handle_t dir
, os_statvfs_t
*st
, ajla_error_t
*err
);
497 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
);
498 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
);
499 bool os_drives(char **drives
, size_t *drives_l
, ajla_error_t
*err
);
501 bool os_tcgetattr(handle_t h
, os_termios_t
*t
, ajla_error_t
*err
);
502 bool os_tcsetattr(handle_t h
, const os_termios_t
*t
, ajla_error_t
*err
);
503 void os_tcflags(os_termios_t
*t
, int flags
);
504 bool os_tty_size(handle_t h
, int *nx
, int *ny
, int *ox
, int *oy
, ajla_error_t
*err
);
505 const char *os_get_path_to_exe(void);
507 ajla_time_t
os_time_t_to_ajla_time(os_time_t sec
);
508 #ifdef HAVE_STRUCT_TIMESPEC
509 ajla_time_t
os_timespec_to_ajla_time(const struct timespec
*ts
);
511 ajla_time_t
os_time_real(void);
512 ajla_time_t
os_time_monotonic(void);
513 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
);
514 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
);
516 const char *os_get_flavor(void);
517 void os_get_uname(os_utsname_t
*un
);
518 bool os_kernel_version(const char *sys
, const char *vers
);
519 char *os_get_host_name(ajla_error_t
*err
);
523 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
);
524 void os_proc_free_handle(struct proc_handle
*ph
);
525 bool os_proc_register_wait(struct proc_handle
*ph
, mutex_t
**mutex_to_lock
, struct list
*list_entry
, int *status
);
526 void os_proc_check_all(void);
528 int os_signal_handle(const char *str
, signal_seq_t
*seq
, ajla_error_t
*err
);
529 void os_signal_unhandle(int sig
);
530 signal_seq_t
os_signal_seq(int sig
);
531 bool os_signal_wait(int sig
, signal_seq_t seq
, mutex_t
**mutex_to_lock
, struct list
*list_entry
);
532 void os_signal_check_all(void);
533 #if defined(OS_HAS_SIGNALS) && defined(SA_SIGINFO)
534 void os_signal_trap(int sig
, void (*handler
)(int, siginfo_t
*, void *));
535 void os_signal_untrap(int sig
);
538 handle_t
os_socket(int domain
, int type
, int protocol
, ajla_error_t
*err
);
539 bool os_bind_connect(bool bnd
, handle_t h
, unsigned char *addr
, size_t addr_len
, ajla_error_t
*err
);
540 bool os_connect_completed(handle_t h
, ajla_error_t
*err
);
541 bool os_listen(handle_t h
, ajla_error_t
*err
);
542 int os_accept(handle_t h
, handle_t
*result
, ajla_error_t
*err
);
543 bool os_getsockpeername(bool peer
, handle_t h
, unsigned char **addr
, size_t *addr_len
, ajla_error_t
*err
);
545 unsigned char *address
;
546 size_t address_length
;
547 struct tree_entry entry
;
549 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
);
550 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
);
551 bool os_getsockopt(handle_t h
, int level
, int option
, char **buffer
, size_t *buffer_len
, ajla_error_t
*err
);
552 bool os_setsockopt(handle_t h
, int level
, int option
, const char *buffer
, size_t buffer_len
, ajla_error_t
*err
);
553 bool os_getaddrinfo(const char *host
, int port
, struct address
**result
, size_t *result_l
, ajla_error_t
*err
);
554 char *os_getnameinfo(unsigned char *addr
, size_t addr_len
, ajla_error_t
*err
);
556 const char *os_decode_error(ajla_error_t error
, char *(*tls_buffer
)(void));
559 #define OS_HAVE_NOTIFY_PIPE
560 extern handle_t os_notify_pipe
[2];
561 void os_notify(void);
562 bool os_drain_notify_pipe(void);
563 void os_shutdown_notify_pipe(void);
565 static inline void os_notify(void) { }
566 static inline void os_shutdown_notify_pipe(void) { }
570 bool dos_poll_devices(void);
571 void dos_yield(void);
572 void dos_wait_on_packet(mutex_t
**mutex_to_lock
, struct list
*list_entry
);
578 void os_init_multithreaded(void);
579 void os_done_multithreaded(void);