Title: Unix Systems Porting Guidelines Status: Work In Progress Author: Guillem Jover Last-Change: 2012-02-29 Documentation ============= Pre-defined C/C++ Compiler Macros --------------------------------- __GNU_LIBRARY__ 1 → 2 → 3 → 4 → 5 → __GLIBC__ == 1 6 → __GLIBC__ == 2 Porting guidelines (to be merged) ------------------ Just a skeleton for now. Porting issues -------------- Functionality Equivalence (organize into sections) ========================= get_current_dir_name() ---------------------- GNU extension, available on GNU/*. On FreeBSD and GNU/* getcwd(NULL, 0) allocates. canonicalize_file_name() ------------------------ GNU extension, available on GNU/*. On FreeBSD and GNU/* realpath(path, NULL) allocates (POSIX.1-2008). fgetln() -------- BSD extension, supported. On GNU/* libbsd provides it. On POSIX.1-2008 or GNU/* getline() can be used instead. timerfd, signalfd, epoll, inotify, fanotify ------------------------------------------- On FreeBSD, GNU/kFreeBSD, DragonflyBSD, NetBSD, OpenBSD and Darwin kqueue . On GNU/Linux and Solaris libkqueue . On GNU/Hurd file and directory notify support. /proc/PID/{stat,comm,cmdline,root,fd/} -------------------------------------- On FreeBSD, GNU/kFreeBSD, DragonflyBSD, NetBSD, OpenBSD and Darwin libkvm . On GNU/Hurd proc_stat . prctl() PR_SET_NAME ------------------- On FreeBSD and GNU/kFreeBSD libkvm or setprogname(). On GNU/* libbsd provides setprogname(). Clearing environ variable ------------------------- libudev ------- On FreeBSD or GNU/kFreeBSD devd's socket (libdevstat, libdevinfo). On OpenBSD hotplugd. On NetBSD devmon (not implemented yet). On Solaris sysevent. setsockopt(IP_FREEBIND) ----------------------- On BSDs setsockopt(IP_BINDANY). setsockopt(IP_TRANSPORT) ------------------------ ?? setsockopt(TCP_KEEPIDLE) ------------------------ On FreeBSD setsockopt(SO_KEEPALIVE). O_CLOEXEC/SOCK_CLOEXEC ---------------------- On POSIX.1-2008 systems, supported. Otherwise fcntl(FD_CLOEXEC), although can be racy on threaded programs, if no precautions are taken. F_SETPIPE_SZ ------------ On FreeBSD and GNU/kFreeBSD, not needed, it uses adaptive pipe sizes. POSIX mqueue as fd ------------------ On FreeBSD and GNU/kFreeBSD, supported. POSIX openat() and friends -------------------------- On FreeBSD and GNU/kFreeBSD, supported. *asprintf() ----------- On GNU/*, BSDs, OpenSolaris, MacOS X, supported. /dev/urandom ------------ On BSDs, supported, just a symlink to /dev/random which never blocks. On GNU/Hurd, supported through random-egd. AF_UNIX/SOCK_SEQPACKET ---------------------- On FreeBSD and GNU/kFreeBSD, supported. Otherwise SOCK_DGRAM might be a viable replacement. Abstract namespace AF_UNIX -------------------------- On non-Linux, either using non abstract AF_UNIX, or AF_INET loopback could be used instead. Resource limits (RLIMIT_RTTIME / RLIMIT_RTPRIO) --------------- Clearly optional. Resource limits (SCHED_RESET_ON_FORK) --------------- ?? Resource limits (ioprio / ionice) --------------- Clearly optional. Resource limits (OOM score adjustment) --------------- Clearly optional. O_DIRECTORY ----------- On POSIX.1-2008 systems, supported. Otherwise can be replaced by standard usage of stat() to verify it's a dir (although racy), or by rmdir() and errno == ENOTDIR followed by unlink(), etc. Console: Setting keyboard mode ------------------------------ On Linux, FreeBSD and GNU/kFreeBSD: ioctl KDSKBMODE Console: Clearing scrollback buffer ----------------------------------- On Linux >= 2.6.40: \033[3J On FreeBSD and GNU/kFreeBSD: ioctl CONS_CLRHIST Terminal: Setting non-exclusive mode ------------------------------------ On Linux, FreeBSD and GNU/kFreeBSD: ioctl TIOCNXCL Console: Managing controlling tty --------------------------------- On Linux, FreeBSD and GNU/kFreeBSD: ioctl TIOCSCTTY/TIOCNOTTY Console: Activate a specific vty -------------------------------- On Linux, FreeBSD and GNU/kFreeBSD: ioctl VT_ACTIVATE Console: Get current active vty ------------------------------- On Linux: /dev/tty0 On FreeBSD and GNU/kFreeBSD: ioctl VT_GETACTIVE Console: Get system console --------------------------- On Linux: /sys/class/tty/console/active Console: Cleanup tty for next login ----------------------------------- On Linux: ioctl TIOCVHANGUP Console: ioctl TIOCLINUX(TIOCL_GETKMSGREDIRECT) ----------------------------------------------- ?? SELinux ------- On FreeBSD the MAC and Audit frameworks. Linux audit ----------- ?? cgroups and /proc/PID/cgroup ---------------------------- On FreeBSD, jail(2). POSIX capabilities (not to be confused with capability-based security) ------------------ On FreeBSD, depending on the usage with jail(2). prctl() PR_CAPBSET_DROP ----------------------- On FreeBSD, depending on the usage with jail(2). waitid() -------- On POSIX.1-2008 systems supported. prctl() PR_SET_PDEATHSIG / PR_GET_PDEATHSIG ------------------------------------------- ?? /proc/cmdline (kernel command line) ------------- On FreeBSD and GNU/kFreeBSD: The boot loader can set arbitrary environment variables. Kernel flags in sysctl debug.boothowto. Other flags passed to init. /sys/class/dmi/id ----------------- On FreeBSD: sysctl smbios.* Oterwise the dmidecode program can be used instead. /dev/rtc -------- On FreeBSD and GNU/kFreeBSD: rtc kernel module from ports collection /dev/char/*, /dev/disk/by-label/*, /dev/disk/by-uuid/* ------------------------------------------------------ ?? autofs4 ------- On FreeBSD: 4.4 BSD automounter (amd) On GNU/Hurd: Can be handled natively with translators, for example with the mux translator. binfmt_misc ----------- ?? Peer credentials ================ Sockets ======= Socket length ------------- The BSDs requires some APIs to get the socklen argument be the exact size of the matching sockaddr_AF for that AF. Socket interface names ---------------------- SIOCGIFCONF has some portability issues. Terminals ========= termio vs termios ----------------- The obsolete System V termio interface is based on direct ioctls, portable applications should switch to termios which is defined by POSIX.1-1990. Some systems (like GNU/Hurd) do not even have the termio interface. (in XPG3 and up as XTI extension, but not in Hurd) TABDLY → TBDELAY TAB3 → XTABS (in Hurd but not in XPG3 and up, from BSD) TBDELAY → XTABS → XCASE, OLCUC, IUCLC → [deprecated] VSWTCH → [deprecated] FIOSNBIO → FIONBIO FIONBIO → fctnl(); O_NDELAY ?? CBAUD → cf[sg]et[io]speed(); tcsetattr(); T{IO,}CGET[AS] → tcgetattr(,); T{IO,}CSET[AS] → tcsetattr(,TCSANOW,); T{IO,}CSET[AS]W → tcsetattr(,TCSADRAIN,); T{IO,}CSET[AS]F → tcsetattr(,TCSAFLUSH,); T{IO,}CSBRK → tcdrain(); tcsendbreak(); TCXONC → tcflow(); TCFLSH → tcflush(); TIOCSPGRP → tcsetpgrp() TIOCGPGRP → tcgetpgrp() Note: TC{IO,}C[SG]ETA[ WF] is for termio TC{IO,}C[SG]ETS[ WF] is for termios Signals ======= RT signals ---------- kFreeBSD doesn't support POSIX RT (realtime) signals. We hope that this functionality is added someday but for now it's a porting issue for us. You can detect wether RT signals are available in the system via the SIGRTMIN and SIGRTMAX macros (which are not defined on kfreebsd-gnu). Time ==== time() ------ For the BSDs, both and need to be included. System information ================== sysinfo(2) ---------- Sizes and limits ================ Portable applications should try not to hardcode size and limits, not only to be future-proof when the limits get rised, but to cope with differences in current systems, either depending on different subsystems or when the limits can change at run-time or on different variations of the same architecture the binary is built for. PAGE_SIZE / PAGESIZE -------------------- Might change at runtime, use sysconf(_SC_PAGESIZE) instead. MAX* ---- Dynamically allocated or sysconf(3). PIPE_BUF ------- pathconf(3) readlink(2) ----------- When reading the symlink contents the most portable and correct way to do it is to retrieve the size of the buffer with lstat(), st_size for the symlink will be the size of the destination buffer. To avoid race conditions and possible truncation one has to use st_size + 1 and verify the readlink() function return size. File Holes ========== On Solaris, FreeBSD and DragonFlyBSD, lseek(SEEK_HOLE/SEEK_DATA). On Linux, FS_IOC_FIEMAP (supported since 2.6.28) FIBMAP (deprecated and requires CAP_CAP_ADMIN), lseek(SEEK_HOLE/SEEK_DATA) (supported since 3.1). On NetBSD, lseek(SEEK_HOLE/SEEK_DATA) being worked on: Running Process Executable Path =============================== On Linux: readlink(2) /proc/self/exe (only from itself) On FreeBSD: sysctl(2) CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1 readlink(2) /proc/curproc/file (with procfs, only from itself) readlink(2) /proc/self/exe (with linprocfs, only from itself) On DragonFlyBSD: readlink(2) /proc/curproc/file (only from itself) On NetBSD: readlink(2) /proc/curproc/exe (only from itself) On Mac OS X: _NSGetExecutablePath(3) (man dyld) On Solaris: getexecname() (only from itself and dynamically linked execs) Standard I/O ============ STDIO_S_EOF_SEEN No longer in libc 4.5.8 Devices ======= Writing to devfs (kFreeBSD) --------------------------- On kFreeBSD's devfs it's only possible to create block/char devices and symlinks. So if you need to create some thing in /dev, like a named pipe create it in another place, then symlink from /dev. Note that the symlink you put in /dev will be removed on next reboot, so make sure the proper init.d script restores it. Generaly, you should use /var/run for your named pipe. The only exception is sysvinit, which can't assume /var is mounted and hence uses /etc. All other daemons can assume /var is mounted, so this shouldn't be an issue. Disk devices (kFreeBSD) ----------------------- On kFreeBSD what usually is a block device on other Unices it's a char device, and as such some operations might not work there.