#ifndef VLIBC_UNISTD_H #define VLIBC_UNISTD_H /* * vlibc — . * * File descriptors, file I/O, and the access/whence symbolic constants * (POSIX.1-2008). Every function here is an unbuffered pass-through to the * kernel: failures are reported as -1 (or the fd/offset on success) with * errno set by the syscall layer. * * Level 1 (onlyposix): read, write, pread, pwrite, open, openat, close, * lseek, dup, dup2, pipe, fsync, fdatasync, ftruncate, * sync, access, faccessat. * Level 2 (muslmimic): dup3, pipe2 (Linux extensions), truncate (XSI), * lseek64 (glibc LFS alias of lseek on x86_64). * * Process control (todo 20) is declared further down: * * Level 1 (onlyposix): fork, exec family (execl/execlp/execle/execv/ * execvp/execve/fexecve), getpid, getppid, getuid, * geteuid, getgid, getegid, setuid, seteuid, setgid, * setegid, getgroups, setpgid, getpgrp, setsid. * Level 2 (muslmimic): vfork, setpgrp (obsolescent), setgroups, getpgid, * getsid, tcgetpgrp, tcsetpgrp (XSI). * * The open-flag constants (O_RDONLY, O_CREAT, O_CLOEXEC, ...) belong to * and are deliberately not defined here; the oflag arguments below * are plain int and take their values from that header. The optional mode * argument of open/openat is a mode_t supplied only when oflag contains * O_CREAT or O_TMPFILE. * * None of these declarations carry an intent attribute: every function * performs I/O with side effects and reports failures through errno, so * const/pure would be unsound. The process functions additionally must not * be const/pure because their results are process state — marking getpid * const, for example, would let the compiler hoist it across fork() and * observe the parent's pid inside the child. */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Level 1 (POSIX base). */ /* Access-check modes for access() and faccessat(). */ #define F_OK 0 /* existence only */ #define X_OK 1 /* execute (search for a directory) */ #define W_OK 2 /* write */ #define R_OK 4 /* read */ /* whence values for lseek() and lseek64() (also defined by ). */ #define SEEK_SET 0 /* from the beginning of the file */ #define SEEK_CUR 1 /* from the current position */ #define SEEK_END 2 /* from the end of the file */ /* * Read up to nbyte bytes from fildes into buf and return the number of * bytes read, 0 at end of file, or -1 with errno set on error. Unbuffered. */ ssize_t read(int fildes, void *buf, size_t nbyte); /* * Write up to nbyte bytes from buf to fildes and return the number of * bytes written, or -1 with errno set on error. Unbuffered. */ ssize_t write(int fildes, const void *buf, size_t nbyte); /* * Read nbyte bytes from fildes starting at offset, without changing the * file position; return the number of bytes read, or -1 with errno set. */ ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); /* * Write nbyte bytes from buf to fildes starting at offset, without * changing the file position; return the number of bytes written, or -1 * with errno set. */ ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); /* * Open path with the oflag access mode (from ) and return a file * descriptor, or -1 with errno set. A mode argument is required — and read * from the varargs — only when oflag contains O_CREAT or O_TMPFILE. */ int open(const char *path, int oflag, ...); /* * Like open(), but path is relative to the directory named by fd (use * AT_FDCWD from for the current working directory). The mode * varargs rule is the same as open(). */ int openat(int fd, const char *path, int oflag, ...); /* * Close the file descriptor fildes; return 0, or -1 with errno set. */ int close(int fildes); /* * Reposition the file offset of fildes to offset per whence (SEEK_SET, * SEEK_CUR, SEEK_END) and return the resulting offset, or (off_t)-1 with * errno set. The full 64-bit offset is returned; errno is untouched on * success. */ off_t lseek(int fildes, off_t offset, int whence); /* * Duplicate fildes to the lowest-numbered free descriptor; return it, or * -1 with errno set. The copy shares the file description (position, * flags, locks) with the original. */ int dup(int fildes); /* * Duplicate fildes onto fildes2, closing fildes2 first if it was open; * return fildes2, or -1 with errno set. dup2(f, f) returns f without * doing anything (POSIX). */ int dup2(int fildes, int fildes2); /* * Create a pipe: fildes[0] becomes the read end, fildes[1] the write end. * Return 0, or -1 with errno set. No descriptor flags are set (unlike * pipe2, this is plain POSIX). */ int pipe(int fildes[2]); /* * Flush all buffered modifications of fildes and its metadata to stable * storage; return 0, or -1 with errno set. */ int fsync(int fildes); /* * Like fsync(), but may skip the metadata work needed only to preserve * file contents; return 0, or -1 with errno set. */ int fdatasync(int fildes); /* * Truncate fildes to length bytes; return 0, or -1 with errno set. */ int ftruncate(int fildes, off_t length); /* * Flush all filesystem caches to stable storage. Returns nothing. */ void sync(void); /* * Check accessibility of path under amode (R_OK, W_OK, X_OK, F_OK); return * 0, or -1 with errno set. Uses the real IDs of the calling process. */ int access(const char *path, int amode); /* * Like access(), but path is relative to the directory named by fd (use * AT_FDCWD for the current working directory) and flag may hold * AT_EACCESS; return 0, or -1 with errno set. */ int faccessat(int fd, const char *path, int amode, int flag); /* Level 1 (POSIX base): process control. */ /* * Create a child process that is a copy of the caller: fork() returns 0 * in the child, the child's pid in the parent, and -1 with errno set on * failure. * * Around the fork, the atfork hook table runs: the prepare handlers in * reverse registration order before the fork, then the child handlers in * the child and the parent handlers in the parent, both in registration * order (POSIX pthread_atfork protocol). The table is registered by * pthread_atfork() (todo 45) and is empty — a no-op — in a process * without threads. */ pid_t fork(void); /* * Replace the calling process image. Success never returns; -1 with * errno set otherwise. execl/execle/execlp take the arguments as a * varargs list terminated by (char *)NULL (execle is followed by one * final char *const envp[] argument); execv/execvp take an argv array. * execvp and execlp search the PATH environment variable (default * "/bin:/usr/bin") when file contains no '/'. execv/execvp/execl/execlp * use the caller's environment; execve/execle/fexecve take envp. */ // NOLINTBEGIN(bugprone-easily-swappable-parameters) int execl(const char *path, const char *arg0, ...); int execle(const char *path, const char *arg0, ...); int execlp(const char *file, const char *arg0, ...); // NOLINTEND(bugprone-easily-swappable-parameters) int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execve(const char *path, char *const argv[], char *const envp[]); /* * Like execve, but the image is the open descriptor fd. */ int fexecve(int fd, char *const argv[], char *const envp[]); /* * Process ids. getpid/getppid/getuid/geteuid/getgid/getegid read the * kernel's per-process ids; setuid/seteuid/setgid/setegid change them. * seteuid/setegid change only the effective id (setresuid/setresgid * underneath: Linux has no seteuid/setegid syscall). */ pid_t getpid(void); pid_t getppid(void); uid_t getuid(void); uid_t geteuid(void); gid_t getgid(void); gid_t getegid(void); int setuid(uid_t uid); int seteuid(uid_t euid); int setgid(gid_t gid); int setegid(gid_t egid); /* * Supplementary groups: getgroups fills grouplist with up to gidsetsize * group ids and returns the total count (0 can be passed to count only); * setgroups (level 2, XSI) installs the list. */ int getgroups(int gidsetsize, gid_t grouplist[]); /* * Session control: setpgid moves pid into process group pgid (0 means * the caller / the caller's pid); getpgrp returns the caller's process * group; setsid creates a new session with the caller as leader and * returns the new session id. */ int setpgid(pid_t pid, pid_t pgid); pid_t getpgrp(void); pid_t setsid(void); #if VLIBC_LEVEL_GE(2) /* Level 2 (muslmimic): Linux extensions + XSI + obsolescent. */ /* * Like dup2(), but with descriptor flags (O_CLOEXEC from ) applied * atomically; return fildes2, or -1 with errno set. Linux-specific. */ int dup3(int fildes, int fildes2, int flags); /* * Like pipe(), but with descriptor flags (e.g. O_CLOEXEC) applied * atomically; return 0, or -1 with errno set. Linux-specific. */ int pipe2(int fildes[2], int flags); /* * Truncate the file named by path to length bytes; return 0, or -1 with * errno set. XSI. */ int truncate(const char *path, off_t length); /* * glibc LFS alias of lseek(): on x86_64 the LFS and non-LFS off_t are * identical (both 64-bit), so this simply calls lseek(). Provided for * source compatibility only. */ off_t lseek64(int fildes, off_t offset, int whence); /* * vfork (obsolescent): like fork(), but the child borrows the parent's * address space until it execs or exits. */ pid_t vfork(void); /* * setpgrp (obsolescent): setpgid(0, 0) — the caller becomes the leader * of its own process group. */ int setpgrp(void); /* * setgroups (XSI): install the supplementary group list of gidsetsize * entries. Requires privilege. */ int setgroups(size_t gidsetsize, const gid_t *grouplist); /* * getpgid/getsid (XSI): the process group / session of pid (0 = the * caller). */ pid_t getpgid(pid_t pid); pid_t getsid(pid_t pid); /* * Controlling-terminal foreground process group (XSI): tcgetpgrp reads * the foreground group of the terminal on fildes; tcsetpgrp makes pgid * the foreground group. */ pid_t tcgetpgrp(int fildes); int tcsetpgrp(int fildes, pid_t pgid); #endif /* VLIBC_LEVEL_GE(2) */ #ifdef __cplusplus } #endif #endif /* VLIBC_UNISTD_H */