STAT(3)

πŸ“¦
version 0_git20260208 Β· 5 versions
, in alpine 3.24, arch rolling, nixos 26.05, nixpkgs unstable

STAT(3) β€” get and put file status πŸ’…

okay bestie, welcome to the STAT(3) page from the Library Functions Manual β€” this one is literally all about getting and putting file status, and it's giving β€œfilesystem group chat admin” energy. πŸ’–

✨ NAME ✨

stat, fstat, wstat, fwstat, dirstat, dirfstat, dirwstat, dirfwstat, nulldir β€” get and put file status. periodt.

🌸 SYNOPSIS 🌸

#include <u.h>
#include <libc.h>

int stat(char *name, uchar *edir, int nedir)

int fstat(int fd, uchar *edir, int nedir)

int wstat(char *name, uchar *edir, int nedir)

int fwstat(int fd, uchar *edir, int nedir)

Dir* dirstat(char *name)

Dir* dirfstat(int fd)

int dirwstat(char *name, Dir *dir)

int dirfwstat(int fd, Dir *dir)

void nulldir(Dir *d)

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so picture this: you've got a file's name, or an open file descriptor fd, and these routines are your little messengers for retrieving or modifying file status information. stat, fstat, wstat, and fwstat are the system calls; they deal with machine-independent directory entries. Their format is defined by stat(9p). stat and fstat retrieve information about name or fd into edir, a buffer of length nedir, defined in <libc.h>. wstat and fwstat write information back, thus changing file attributes according to the contents of edir. The data returned from the kernel includes its leading 16-bit length field as described in intro(9p). For symmetry, this field must also be present when passing data to the kernel in a call to wstat and fwstat, but its value is ignored. slay for symmetry, I guess πŸ’…

dirstat, dirfstat, dirwstat, and dirfwstat are similar to their counterparts, except that they operate on Dir structures:

typedef
struct Dir {
      /* system-modified data */
      uint  type;    /* server type */
      uint  dev;     /* server subtype */
      /* file data */
      Qid   qid;     /* unique id from server */
      ulong mode;    /* permissions */
      ulong atime;   /* last read time */
      ulong mtime;   /* last write time */
      vlong length;  /* file length: see <u.h> */
      char  *name;   /* last element of path */
      char  *uid;    /* owner name */
      char  *gid;    /* group name */
      char  *muid;   /* last modifier name */
} Dir;

The returned structure is allocated by malloc(3); freeing it also frees the associated strings. convenient, iconic, no leaks in the group chat πŸ’œ

This structure and the Qid structure are defined in <libc.h>. If the file resides on permanent storage and is not a directory, the length returned by stat is the number of bytes in the file. For directories, the length returned is zero. For files that are streams (e.g., pipes and network connections), the length is the number of bytes that can be read without blocking. yes bestie, pipes and network connections count as streams here β€” noted.

Each file is the responsibility of some server: it could be a file server, a kernel device, or a user process. type identifies the server type, and dev says which of a group of servers of the same type is the one responsible for this file. Qid is a structure containing path and vers fields: path is guaranteed to be unique among all path names currently on the file server, and vers changes each time the file is modified. The path is a long long (64 bits, vlong) and the vers is an unsigned long (32 bits, ulong). Thus, if two files have the same type, dev, and qid they are the same file. same type, same dev, same qid = same file. iykyk πŸ’š

The bits in mode are defined by

0x80000000   directory
0x40000000   append only
0x20000000   exclusive use (locked)
0x00800000   Unix device file
0x02000000   symbolic link
0x00200000   named pipe
0x00100000   socket

     0400   read permission by owner
     0200   write permission by owner
     0100   execute permission (search on directory) by owner
     0070   read, write, execute (search) by group
     0007   read, write, execute (search) by others

There are constants defined in <libc.h> for these bits: DMDIR, DMAPPEND, and DMEXCL for the first three; and DMREAD, DMWRITE, and DMEXEC for the read, write, and execute bits for others. cute little permission icons, honestly.

The two time fields are measured in seconds since the epoch (Jan 1 00:00 1970 GMT). mtime is the time of the last change of content. Similarly, atime is set whenever the contents are accessed; also, it is set whenever mtime is set. timestamps stay booked and busy πŸ•°οΈ

uid and gid are the names of the owner and group of the file; muid is the name of the user that last modified the file (setting mtime). Groups are also users, but each server is free to associate a list of users with any user name g, and that list is the set of users in the group g. When an initial attachment is made to a server, the user string in the process group is communicated to the server. Thus, the server knows, for any given file access, whether the accessing process is the owner of, or in the group of, the file. This selects which sets of three bits in mode is used to check permissions. server knows the vibes: owner? group? permission check says hello πŸ’…

Only some of the fields may be changed with the wstat calls. The name can be changed by anyone with write permission in the parent directory. The mode and mtime can be changed by the owner or the group leader of the file's current group. The gid can be changed: by the owner if also a member of the new group; or by the group leader of the file's current group if also leader of the new group (see intro(9p) for more information about permissions, users, and groups). The length can be changed by anyone with write permission, provided the operation is implemented by the server. (See intro(9p) for permission, user, and group information). so yes, there are rules β€” read them, bestie, don't just yolo a wstat 🫢

Special values in the fields of the Dir passed to wstat indicate that the field is not intended to be changed by the call. The values are the maximum unsigned integer of appropriate size for integral values (usually ~0, but beware of conversions and size mismatches when comparing values) and the empty or nil string for string values. The routine nulldir initializes all the elements of d to these ``don't care'' values. Thus one may change the mode, for example, by using nulldir to initialize a Dir, then setting the mode, and then doing wstat; it is not necessary to use stat to retrieve the initial values first. nulldir is the β€œdon't care” reset button of this whole situation β€” love that for us.

πŸŽ€ SOURCE πŸŽ€

/src/lib9/dirstat.c

πŸ‘‘ SEE ALSO πŸ‘‘

πŸ’€ DIAGNOSTICS πŸ’€

The dir functions return a pointer to the data for a successful call, or nil on error. The others return the number of bytes copied on success, or -1 on error. All set errstr. error era, but at least errstr tells you what's tea β˜•

If the buffer for stat or fstat is too short for the returned data, the return value will be BIT16SZ (see fcall(3)) and the two bytes returned will contain the initial count field of the returned data; retrying with nedir equal to that value plus BIT16SZ (for the count itself) should succeed. so if it's too short, you get BIT16SZ, you read the count, you add BIT16SZ, you try again β€” literally the glow-up retry arc ✨


✨ STAT(3) Β· source: /src/lib9/dirstat.c Β· date: not shown in this copy β€” bye bestie, slay your file status πŸ’…πŸ«Ά