Files
vlibc/include/sys/stat.h
T

295 lines
9.5 KiB
C

#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 */