#ifndef VLIBC_SYS_STAT_H #define VLIBC_SYS_STAT_H /* * vlibc — . * * File status: the x86_64 Linux struct stat layout and the S_* mode-bit * macros, plus the stat/mkdir/chmod/utimensat/chown wrapper families * (POSIX.1-2008 base). Every function is an unbuffered pass-through to the * kernel: failures are reported as -1 with errno set by the syscall layer. * * Level 1 (onlyposix): stat, fstat, lstat, fstatat, mkdir, mkdirat, * mkfifo, mkfifoat, chmod, fchmod, fchmodat, umask, * utimensat, futimens, chown, fchown, lchown, * fchownat (Issue 7 moved lchown from XSI to base). * Level 2 (muslmimic): mknod, mknodat (XSI). * * struct stat matches the x86_64 kernel layout exactly (144 bytes), pinned * by static assertions — the same layout src/stdio/stdio.c transcribed * privately as stdio_stat for its fstat-based isatty(). The * st_atime/st_mtime/st_ctime spellings are glibc-style macros onto * st_atim.tv_sec &c for POSIX source compatibility. * * The AT_* flag constants (AT_FDCWD, AT_SYMLINK_NOFOLLOW, ...) belong to * (todo 21) and are deliberately not defined here; the flag * arguments below are plain int and take their values from that header. * * 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. */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Provisional struct timespec definition. The canonical home of struct * timespec is (todo 41); until it lands, sys/stat.h needs the * definition for the st_*tim members and utimensat/futimens. Todo 41 must * move (or reconcile) this definition — it currently exists nowhere else * (include/threads.h only forward-declares it). */ struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds (0..999999999) */ }; /* * File status, x86_64 Linux kernel layout. Field widths are LP64: the * comment column gives the byte offset of each member. The order and the * two padding areas are kernel-ABI facts, not style choices. */ struct stat { dev_t st_dev; /* 0: device containing the file */ ino_t st_ino; /* 8: inode number */ nlink_t st_nlink; /* 16: hard link count */ mode_t st_mode; /* 24: file type + permissions */ uid_t st_uid; /* 28: owner user id */ gid_t st_gid; /* 32: owner group id */ unsigned int st_pad0; /* 36: kernel padding (int __pad0) */ dev_t st_rdev; /* 40: device id (if device file) */ off_t st_size; /* 48: size in bytes */ blksize_t st_blksize; /* 56: preferred I/O block size */ blkcnt_t st_blocks; /* 64: 512-byte blocks allocated */ struct timespec st_atim; /* 72: last access time */ struct timespec st_mtim; /* 88: last modification time */ struct timespec st_ctim; /* 104: last status change time */ long st_unused[3]; /* 120: kernel padding (__unused) */ }; /* Pin the kernel layout: sizeof and the two offsets stdio consumes. */ _Static_assert(sizeof(struct stat) == 144, "struct stat must match the x86_64 kernel layout"); _Static_assert(offsetof(struct stat, st_mode) == 24, "st_mode must sit at offset 24"); _Static_assert(offsetof(struct stat, st_size) == 48, "st_size must sit at offset 48"); /* File type bits (st_mode & S_IFMT). */ #define S_IFMT 0170000 /* type-of-file mask */ #define S_IFSOCK 0140000 /* socket */ #define S_IFLNK 0120000 /* symbolic link */ #define S_IFREG 0100000 /* regular file */ #define S_IFBLK 0060000 /* block device */ #define S_IFDIR 0040000 /* directory */ #define S_IFCHR 0020000 /* character device */ #define S_IFIFO 0010000 /* FIFO (named pipe) */ /* Special permission bits. */ #define S_ISUID 04000 /* set-user-id on execution */ #define S_ISGID 02000 /* set-group-id on execution */ #define S_ISVTX 01000 /* sticky bit (restricted deletion on dirs) */ /* Owner permission bits. */ #define S_IRWXU 0700 /* read, write, execute/search by owner */ #define S_IRUSR 0400 /* read permission, owner */ #define S_IWUSR 0200 /* write permission, owner */ #define S_IXUSR 0100 /* execute/search permission, owner */ /* Group permission bits. */ #define S_IRWXG 070 /* read, write, execute/search by group */ #define S_IRGRP 040 /* read permission, group */ #define S_IWGRP 020 /* write permission, group */ #define S_IXGRP 010 /* execute/search permission, group */ /* Others permission bits. */ #define S_IRWXO 07 /* read, write, execute/search by others */ #define S_IROTH 04 /* read permission, others */ #define S_IWOTH 02 /* write permission, others */ #define S_IXOTH 01 /* execute/search permission, others */ /* File type predicates over the type bits. */ #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* POSIX compatibility spellings of the struct timespec members. */ #define st_atime st_atim.tv_sec #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec /* Level 1 (POSIX base). */ /* * Store the status of the file named by path into buf. Follows symbolic * links; return 0, or -1 with errno set. */ int stat(const char *path, struct stat *buf); /* * Store the status of the file descriptor fd into buf; return 0, or -1 * with errno set. */ int fstat(int fd, struct stat *buf); /* * Like stat(), but a symbolic link is reported itself, not its target; * return 0, or -1 with errno set. */ int lstat(const char *path, struct stat *buf); /* * Like stat(), but path is relative to the directory named by fd (use * AT_FDCWD from for the current working directory); flag may * hold AT_SYMLINK_NOFOLLOW to report the link itself. Return 0, or -1 * with errno set. */ int fstatat(int fd, const char *path, struct stat *buf, int flag); /* * Create the directory named by path with the access mode mode (masked by * the process umask); return 0, or -1 with errno set. */ int mkdir(const char *path, mode_t mode); /* * Like mkdir(), but path is relative to the directory named by fd (use * AT_FDCWD for the current working directory); return 0, or -1 with errno * set. */ int mkdirat(int fd, const char *path, mode_t mode); /* * Create the FIFO (named pipe) named by path with mode; return 0, or -1 * with errno set. */ int mkfifo(const char *path, mode_t mode); /* * Like mkfifo(), but path is relative to the directory named by fd (use * AT_FDCWD for the current working directory); return 0, or -1 with errno * set. */ int mkfifoat(int fd, const char *path, mode_t mode); /* * Change the access mode of the file named by path to mode; return 0, or * -1 with errno set. */ int chmod(const char *path, mode_t mode); /* * Change the access mode of the file descriptor fd to mode; return 0, or * -1 with errno set. */ int fchmod(int fd, mode_t mode); /* * Like chmod(), but path is relative to the directory named by fd (use * AT_FDCWD for the current working directory); flag may hold * AT_SYMLINK_NOFOLLOW. Return 0, or -1 with errno set. */ int fchmodat(int fd, const char *path, mode_t mode, int flag); /* * Set the process file-mode creation mask to cmask and return the previous * mask. Never fails. */ mode_t umask(mode_t cmask); /* * Set the access and modification times of the file named by path * (relative to fd, or AT_FDCWD) to times[0] (access) and times[1] * (modification). A NULL times sets both to the current time; a tv_nsec * of UTIME_NOW/UTIME_OMIT (from ) selects per-member behavior. * Return 0, or -1 with errno set. */ int utimensat(int fd, const char *path, const struct timespec times[2], int flag); /* * Like utimensat() on the file descriptor fd (the path is implicit); * return 0, or -1 with errno set. */ int futimens(int fd, const struct timespec times[2]); /* * Change the owner and group of the file named by path to owner/group * (a value of (uid_t)-1 leaves the current one unchanged). Follows * symbolic links; return 0, or -1 with errno set. */ int chown(const char *path, uid_t owner, gid_t group); /* * Change the owner and group of the file descriptor fd; return 0, or -1 * with errno set. */ int fchown(int fd, uid_t owner, gid_t group); /* * Like chown(), but a symbolic link is changed itself, not its target; * return 0, or -1 with errno set. */ int lchown(const char *path, uid_t owner, gid_t group); /* * Like chown(), but path is relative to the directory named by fd (use * AT_FDCWD for the current working directory); flag may hold * AT_SYMLINK_NOFOLLOW. Return 0, or -1 with errno set. */ int fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); #if VLIBC_LEVEL_GE(2) /* Level 2 (muslmimic): XSI. */ /* * Create a special file named by path with mode (a file-type bit like * S_IFIFO or S_IFCHR must be set) and device id dev; return 0, or -1 with * errno set. Creating device nodes requires privilege. XSI. */ int mknod(const char *path, mode_t mode, dev_t dev); /* * Like mknod(), but path is relative to the directory named by fd (use * AT_FDCWD for the current working directory); return 0, or -1 with errno * set. XSI. */ int mknodat(int fd, const char *path, mode_t mode, dev_t dev); #endif /* VLIBC_LEVEL_GE(2) */ #ifdef __cplusplus } #endif #endif /* VLIBC_SYS_STAT_H */