LIBSA(3)
π NAME π
libsa β support library for standalone executables. Yep bestie, this is the libsa(3) page, and it's giving βsupport squad for standalone appsβ energy. π
π SYNOPSIS π
#include <stand.h>
π DESCRIPTION π
Okay so the libsa library provides a set of supporting functions for standalone applications, mimicking the standard BSD programming environment where possible. The sections below group these functions by kind. Unless something is specifically described here, go see the corresponding section 3 manpages for the given functions. π
β¨ STRING FUNCTIONS β¨
String functions are available exactly as documented in string(3) and bstring(3). No cap, the string docs already ate β go read those. π
π§ MEMORY ALLOCATION π§
void * malloc(size_t size)β allocatessizebytes of memory from the heap using a best-fit algorithm. πvoid free(void *ptr)β frees the allocated object atptr.void setheap(void *start, void *limit)β initialises the heap. This function must be called before callingalloc()for the first time. The region betweenstartandlimitwill be used for the heap; attempting to allocate beyond this will result in a panic. πchar * sbrk(int junk)β provides the behaviour ofsbrk(0), i.e., returns the highest point that the heap has reached. This value can be used during testing to determine the actual heap usage. Thejunkargument is ignored. π«Ά
πΏ ENVIRONMENT πΏ
A set of functions are provided for manipulating a flat variable space similar to the traditional shell-supported environment. Major enhancements are support for set/unset hook functions. Periodt, hooks are the main character energy here. π
char * getenv(const char *name)int setenv(const char *name, const char *value, int overwrite)int putenv(char *string)int unsetenv(const char *name)
All four behave similarly to their standard library counterparts.
struct env_var * env_getenv(const char *name)β looks up a variable in the environment and returns its entire data structure. πint env_setenv(const char *name, int flags, const void *value, ev_sethook_t sethook, ev_unsethook_t unsethook)β creates a new environment variable calledname, or sets an existing one. If creating a new variable, thesethookandunsethookarguments may be specified.
The set hook is invoked whenever an attempt is made to set the variable, unless the EV_NOHOOK flag is set. Typically a set hook will validate the value argument, and then call env_setenv() again with EV_NOHOOK set to actually save the value. The predefined function env_noset() may be specified to refuse all attempts to set a variable.
The unset hook is invoked when an attempt is made to unset a variable. If it returns zero, the variable will be unset. The predefined function env_nounset may be used to prevent a variable being unset. π«
π STANDARD LIBRARY SUPPORT π
int abs(int i)int getopt(int argc, char * const *argv, const char *optstring)long strtol(const char *nptr, char **endptr, int base)long long strtoll(const char *nptr, char **endptr, int base)long strtoul(const char *nptr, char **endptr, int base)long long strtoull(const char *nptr, char **endptr, int base)void srandom(unsigned int seed)long random(void)char * strerror(int error)β returns error messages for the subset oferrnovalues supported bylibsa. πassert(expression)β requires<assert.h>.int setjmp(jmp_buf env)void longjmp(jmp_buf env, int val)
These are defined as _setjmp() and _longjmp() respectively as there is no signal state to manipulate. Requires <setjmp.h>.
π CHARACTER I/O π
void gets(char *buf)β reads characters from the console intobuf. All of the standard cautions apply to this function. β οΈvoid ngets(char *buf, int size)β reads at mostsize - 1characters from the console intobuf. Ifsizeis less than 1, the function's behaviour is as forgets().int fgetstr(char *buf, int size, int fd)β reads a line of at mostsizecharacters intobuf. Line terminating characters are stripped, and the buffer is always NUL terminated. Returns the number of characters inbufif successful, or-1if a read error occurs.int printf(const char *fmt, ...)void vprintf(const char *fmt, va_list ap)int sprintf(char *buf, const char *fmt, ...)void vsprintf(char *buf, const char *fmt, va_list ap)
The *printf functions implement a subset of the standard printf() family functionality and some extensions. The following standard conversions are supported: c,d,n,o,p,s,u,x. The following modifiers are supported: +,-,#,*,0,field width,precision,l.
The b conversion is provided to decode error registers. Its usage is:
printf( "reg=%b\n", regval, "<base><arg>*" );
where <base> is the output expressed as a control character, e.g. \10 gives octal, \20 gives hex. Each <arg> is a sequence of characters, the first of which gives the bit number to be inspected (origin 1) and the next characters (up to a character less than 32) give the text to be displayed if the bit is set. Thus
printf( "reg=%b\n", 3, "\10\2BITTWO\1BITONE" );
would give the output
reg=3<BITTWO,BITONE>
The D conversion provides a hexdump facility, e.g.
printf( "%6D", ptr, ":" ); gives "XX:XX:XX:XX:XX:XX"
printf( "%*D", len, ptr, " " ); gives "XX XX XX ..."
π§ͺ CHARACTER TESTS AND CONVERSIONS π§ͺ
int isupper(int c)int islower(int c)int isspace(int c)int isdigit(int c)int isxdigit(int c)int isascii(int c)int isalpha(int c)int isalnum(int c)int iscntrl(int c)int isgraph(int c)int ispunct(int c)int toupper(int c)int tolower(int c)
π FILE I/O π
int open(const char *path, int flags)β similar to the behaviour as specified inopen(2), except that file creation is not supported, so themodeparameter is not required. Theflagsargument may be one ofO_RDONLY,O_WRONLYandO_RDWR. Only UFS currently supports writing. πint close(int fd)void closeall(void)β closes all open files.ssize_t read(int fd, void *buf, size_t len)ssize_t write(int fd, void *buf, size_t len)β (No file systems currently support writing.) πoff_t lseek(int fd, off_t offset, int whence)β files being automatically uncompressed during reading cannot seek backwards from the current point.int stat(const char *path, struct stat *sb)int fstat(int fd, struct stat *sb)
The stat() and fstat() functions only fill out the following fields in the sb structure: st_mode,st_nlink,st_uid,st_gid,st_size. The tftp file system cannot provide meaningful values for this call, and the cd9660 file system always reports files having uid/gid of zero.
π PAGER π
The libsa library supplies a simple internal pager to ease reading the output of large commands. Built-in pager? Obsessed, honestly. π
void pager_open()β initialises the pager and tells it that the next line output will be the top of the display. The environment variableLINESis consulted to determine the number of lines to be displayed before pausing.void pager_close(void)β closes the pager.int pager_output(const char *lines)β sends the lines in the NUL-terminated buffer atlinesto the pager. Newline characters are counted in order to determine the number of lines being output (wrapped lines are not accounted for). Thepager_output()function will return zero when all of the lines have been output, or nonzero if the display was paused and the user elected to quit. πint pager_file(const char *fname)β attempts to open and display the filefname. Returns-1on error,0at EOF, or1if the user elects to quit while reading.
π FEATURE SUPPORT π
A set of functions are provided to communicate support of features from the loader binary to the interpreter. These are used to do something sensible if we are still operating with a loader binary that behaves differently than expected. π
void feature_enable(uint32_t mask)β enable the referencedmaskfeature, which should be one of theFEATURE_*macros defined in<stand.h>.bool feature_name_is_enabled(const char *name)β check if the referencednamefeature is enabled. Thenameis usually the same name as theFEATURE_*macro, but with theFEATURE_prefix stripped off. The authoritative source of feature names is the mapping table near the top instand/libsa/features.c. πvoid (feature_iter_fn)(void *cookie, const char *name, const char *desc, bool enabled)β thecookieargument is passed as-is from the argument of the same name tofeature_iter(). Thenameanddescarguments are defined in the mapping table instand/libsa/features.c. Theenabledargument indicates the current status of the feature, though one could theoretically turn a feature off in later execution. As such, this should likely not be trusted if it is needed after the iteration has finished. πvoid feature_iter(feature_iter_fn *iter_fn, void *cookie)β iterate over the current set of features.
β¨ MISC β¨
char * devformat(struct devdesc *)β Formats the specified device as a string. Cute little dev-to-string converter, no cap πint devparse(struct devdesc **dev, const char *devdesc, const char **path)β Parses thedevdescstring of the formdevice:[/path/to/file]. Thedevswtable is used to match the start of thedevicestring withdv_name. Ifdv_parsedevis non-NULL, then it will be called to parse the rest of the string and allocate thestruct devdescfor this path. If NULL, then a default routine will be called that will allocate a simplestruct devdesc, parse a unit number and ensure thereβs no trailing characters. Ifpathis non-NULL, then a pointer to the remainder of thedevdescstring after the device specification is written.int devinit(void)β Calls all thedv_initroutines in thedevswarray, returning the number of routines that returned an error. Bestie, itβs literally counting the Ls πvoid twiddle(void)β Successive calls emit the characters in the sequence|,/,-,\followed by a backspace in order to provide reassurance to the user. Tiny spinny guy, doing emotional support π
π οΈ REQUIRED LOW-LEVEL SUPPORT π οΈ
The following resources are consumed by libsa β stack, heap, console and devices. Yes, all four. The whole support system, okay? π«Ά
The stack must be established before libsa functions can be invoked. Stack requirements vary depending on the functions and file systems used by the consumer and the support layer functions detailed below.
The heap must be established before calling alloc() or open() by calling setheap(). Heap usage will vary depending on the number of simultaneously open files, as well as client behaviour. Automatic decompression will allocate more than 64K of data per open file. So yeah, sheβs hungry π
Console access is performed via the getchar(), putchar() and ischar() functions detailed below.
Device access is initiated via devopen() and is performed through the dv_strategy(), dv_ioctl() and dv_close() functions in the device switch structure that devopen() returns.
The consumer must provide the following support functions:
int getchar(void)β Return a character from the console, used bygets(),ngets()and pager functions.int ischar(void)β Returns nonzero if a character is waiting from the console.void putchar(int)β Write a character to the console, used bygets(),ngets(),*printf(),panic()andtwiddle()and thus by many other functions for debugging and informational output.int devopen(struct open_file *of, const char *name, const char **file)β Open the appropriate device for the file named inname, returning infilea pointer to the remaining body ofnamewhich does not refer to the device. Thef_devfield inofwill be set to point to thedevswstructure for the opened device if successful. Device identifiers must always precede the path component, but may otherwise be arbitrarily formatted. Used byopen()and thus for all device-related I/O.int devclose(struct open_file *of)β Close the device allocated forof. The device driver itself will already have been called for the close; this call should clean up any allocation made bydevopenonly.void __abort()β Callspanic()with a fixed string.void panic(const char *msg, ...)β Signal a fatal and unrecoverable error condition. Themsg ...arguments are as forprintf().
ποΈ INTERNAL FILE SYSTEMS ποΈ
Internal file systems are enabled by the consumer exporting the array struct fs_ops *file_system[], which should be initialised with pointers to struct fs_ops structures. The following file system handlers are supplied by libsa, the consumer may supply other file systems of their own:
ufs_fsopsβ The BSD UFS.ext2fs_fsopsβ Linux ext2fs file system.tftp_fsopsβ File access via TFTP.nfs_fsopsβ File access via NFS.cd9660_fsopsβ ISO 9660 (CD-ROM) file system.gzipfs_fsopsβ Stacked file system supporting gzipped files. When trying thegzipfsfile system,libsaappends.gzto the end of the filename, and then tries to locate the file using the other file systems. Placement of this file system in thefile_system[]array determines whether gzipped files will be opened in preference to non-gzipped files. It is only possible to seek a gzipped file forwards, andstat()andfstat()on gzipped files will report an invalid length.bzipfs_fsopsβ The same asgzipfs_fsops, but forbzip2(1)-compressed files.pkgfs_fsopsβ File access from a tar file typically streamed via TFTP. The order of files in the tar file must match the order they are to be consumed as rewind is not practical.
The array of struct fs_ops pointers should be terminated with a NULL.
π DEVICES π
Devices are exported by the supporting code via the array struct devsw *devsw[] which is a NULL terminated array of pointers to device switch structures. Slay, very pointer, very array β¨
π§© DRIVER INTERFACE π§©
The driver needs to provide a common set of entry points that are used by libsa to interface with the device.
struct devsw {
const char dv_name[DEV_NAMLEN];
int dv_type;
int (*dv_init)(void);
int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
size_t size, char *buf, size_t *rsize);
int (*dv_open)(struct open_file *f, ...);
int (*dv_close)(struct open_file *f);
int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
int (*dv_print)(int verbose);
void (*dv_cleanup)(void);
char * (*dv_fmtdev)(struct devdesc *);
int (*dv_parsedev)(struct devdesc **dev, const char *devpart,
const char **path);
bool (*dv_match)(struct devsw *dv, const char *devspec);
};
dv_name()β The deviceβs name.dv_type()β Type of device. The supported types are:DEVT_NONEDEVT_DISKDEVT_NETDEVT_CDDEVT_ZFSDEVT_FD
Each type may have its own associated (struct type_devdesc), which has the generic (struct devdesc) as its first member.
dv_init()β Driver initialization routine. This routine should probe for available units. Drivers are responsible for maintaining lists of units for later enumeration. No other driver routines may be called beforedv_init()returns.dv_open()β The driver open routine.dv_close()β The driver close routine.dv_ioctl()β The driver ioctl routine.dv_print()β Prints information about the available devices. Information should be presented withpager_output().dv_cleanup()β Cleans up any memory used by the device before the next stage is run.dv_fmtdev()β Converts the specifieddevdescto the canonical string representation for that device.dv_parsedev()β Parses the device portion of a file path. Thedevpartwill point to the βtailβ of device name, possibly followed by a colon and a path within the device. The βtailβ is, by convention, the part of the device specification that follows thedv_namepart of the string. So whendevparseis parsing the string"disk3p5:/xxx",devpartwill point to the β3β in that string. The parsing routine is expected to allocate a newstruct devdescor subclass and return it indevwhen successful. This routine should setpathto point to the portion of the string after device specification, or"/xxx"in the earlier example. Generally, code needing to parse a path will usedevparseinstead of calling this routine directly.dv_match()βNULLto specify that all device paths starting withdv_namematch. Otherwise, this function returns 0 for a match and a non-zeroerrnoto indicate why it didnβt match. This is helpful when you claim the device path after using it to query properties on systems that have uniform naming for different types of devices.
π HISTORY π
The libsa library contains contributions from many sources, including:
libsafrom NetBSDlibcandlibkernfrom FreeBSD 3.0.zallocfromMatthew Dillon <dillon@backplane.com>
The reorganisation and port to FreeBSD 3.0, the environment functions and this manpage were written by Mike Smith <msmith@FreeBSD.org>.
π BUGS π
The lack of detailed memory usage data is unhelpful. Yeah, she said it. Weβre all just vibing without the receipts π
Thatβs the Debian version, dated September 9, 2022 β page LIBSA(3), bye bestie π
π
π¦ where this page comes from
- freebsd 15.1: base 15.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms