feat(stat): stat/mkdir/chmod and mode macros
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
#ifndef VLIBC_SYS_STAT_H
|
||||
#define VLIBC_SYS_STAT_H
|
||||
|
||||
/*
|
||||
* vlibc — <sys/stat.h>.
|
||||
*
|
||||
* 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
|
||||
* <fcntl.h> (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 <vlibc/features.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provisional struct timespec definition. The canonical home of struct
|
||||
* timespec is <time.h> (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 <fcntl.h> 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 <time.h>) 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 */
|
||||
Reference in New Issue
Block a user