295 lines
9.5 KiB
C
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 */
|