xref: /freebsd/stand/libsa/libsa.3 (revision 24e4dcf4ba5e9dedcf89efd358ea3e1fe5867020)
1.\" Copyright (c) Michael Smith
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\"    notice, this list of conditions and the following disclaimer in the
11.\"    documentation and/or other materials provided with the distribution.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.\"
25.Dd September 9, 2022
26.Dt LIBSA 3
27.Os
28.Sh NAME
29.Nm libsa
30.Nd support library for standalone executables
31.Sh SYNOPSIS
32.In stand.h
33.Sh DESCRIPTION
34The
35.Nm
36library provides a set of supporting functions for standalone
37applications, mimicking where possible the standard
38.Bx
39programming
40environment.
41The following sections group these functions by kind.
42Unless specifically described here, see the corresponding section 3
43manpages for the given functions.
44.Sh STRING FUNCTIONS
45String functions are available as documented in
46.Xr string 3
47and
48.Xr bstring 3 .
49.Sh MEMORY ALLOCATION
50.Bl -hang -width 10n
51.It Xo
52.Ft "void *"
53.Fn malloc "size_t size"
54.Xc
55.Pp
56Allocate
57.Fa size
58bytes of memory from the heap using a best-fit algorithm.
59.It Xo
60.Ft void
61.Fn free "void *ptr"
62.Xc
63.Pp
64Free the allocated object at
65.Fa ptr .
66.It Xo
67.Ft void
68.Fn setheap "void *start" "void *limit"
69.Xc
70.Pp
71Initialise the heap.
72This function must be called before calling
73.Fn alloc
74for the first time.
75The region between
76.Fa start
77and
78.Fa limit
79will be used for the heap; attempting to allocate beyond this will result
80in a panic.
81.It Xo
82.Ft "char *"
83.Fn sbrk "int junk"
84.Xc
85.Pp
86Provides the behaviour of
87.Fn sbrk 0 ,
88i.e., returns the highest point that the heap has reached.
89This value can
90be used during testing to determine the actual heap usage.
91The
92.Fa junk
93argument is ignored.
94.El
95.Sh ENVIRONMENT
96A set of functions are provided for manipulating a flat variable space similar
97to the traditional shell-supported environment.
98Major enhancements are support
99for set/unset hook functions.
100.Bl -hang -width 10n
101.It Xo
102.Ft "char *"
103.Fn getenv "const char *name"
104.Xc
105.It Xo
106.Ft int
107.Fn setenv "const char *name" "const char *value" "int overwrite"
108.Xc
109.It Xo
110.Ft int
111.Fn putenv "char *string"
112.Xc
113.It Xo
114.Ft int
115.Fn unsetenv "const char *name"
116.Xc
117.Pp
118These functions behave similarly to their standard library counterparts.
119.It Xo
120.Ft "struct env_var *"
121.Fn env_getenv "const char *name"
122.Xc
123.Pp
124Looks up a variable in the environment and returns its entire
125data structure.
126.It Xo
127.Ft int
128.Fn env_setenv "const char *name" "int flags" "const void *value" "ev_sethook_t sethook" "ev_unsethook_t unsethook"
129.Xc
130.Pp
131Creates a new or sets an existing environment variable called
132.Fa name .
133If creating a new variable, the
134.Fa sethook
135and
136.Fa unsethook
137arguments may be specified.
138.Pp
139The set hook is invoked whenever an attempt
140is made to set the variable, unless the EV_NOHOOK flag is set.
141Typically
142a set hook will validate the
143.Fa value
144argument, and then call
145.Fn env_setenv
146again with EV_NOHOOK set to actually save the value.
147The predefined function
148.Fn env_noset
149may be specified to refuse all attempts to set a variable.
150.Pp
151The unset hook is invoked when an attempt is made to unset a variable.
152If it
153returns zero, the variable will be unset.
154The predefined function
155.Fa env_nounset
156may be used to prevent a variable being unset.
157.El
158.Sh STANDARD LIBRARY SUPPORT
159.Bl -hang -width 10n
160.It Xo
161.Ft int
162.Fn abs "int i"
163.Xc
164.It Xo
165.Ft int
166.Fn getopt "int argc" "char * const *argv" "const char *optstring"
167.Xc
168.It Xo
169.Ft long
170.Fn strtol "const char *nptr" "char **endptr" "int base"
171.Xc
172.It Xo
173.Ft long long
174.Fn strtoll "const char *nptr" "char **endptr" "int base"
175.Xc
176.It Xo
177.Ft long
178.Fn strtoul "const char *nptr" "char **endptr" "int base"
179.Xc
180.It Xo
181.Ft long long
182.Fn strtoull "const char *nptr" "char **endptr" "int base"
183.Xc
184.It Xo
185.Ft void
186.Fn srandom "unsigned int seed"
187.Xc
188.It Xo
189.Ft "long"
190.Fn random void
191.Xc
192.It Xo
193.Ft "char *"
194.Fn strerror "int error"
195.Xc
196.Pp
197Returns error messages for the subset of errno values supported by
198.Nm .
199.It Fn assert expression
200.Pp
201Requires
202.In assert.h .
203.It Xo
204.Ft int
205.Fn setjmp "jmp_buf env"
206.Xc
207.It Xo
208.Ft void
209.Fn longjmp "jmp_buf env" "int val"
210.Xc
211.Pp
212Defined as
213.Fn _setjmp
214and
215.Fn _longjmp
216respectively as there is no signal state to manipulate.
217Requires
218.In setjmp.h .
219.El
220.Sh CHARACTER I/O
221.Bl -hang -width 10n
222.It Xo
223.Ft void
224.Fn gets "char *buf"
225.Xc
226.Pp
227Read characters from the console into
228.Fa buf .
229All of the standard cautions apply to this function.
230.It Xo
231.Ft void
232.Fn ngets "char *buf" "int size"
233.Xc
234.Pp
235Read at most
236.Fa size
237- 1 characters from the console into
238.Fa buf .
239If
240.Fa size
241is less than 1, the function's behaviour is as for
242.Fn gets .
243.It Xo
244.Ft int
245.Fn fgetstr "char *buf" "int size" "int fd"
246.Xc
247.Pp
248Read a line of at most
249.Fa size
250characters into
251.Fa buf .
252Line terminating characters are stripped, and the buffer is always
253.Dv NUL
254terminated.
255Returns the number of characters in
256.Fa buf
257if successful, or -1 if a read error occurs.
258.It Xo
259.Ft int
260.Fn printf "const char *fmt" "..."
261.Xc
262.It Xo
263.Ft void
264.Fn vprintf "const char *fmt" "va_list ap"
265.Xc
266.It Xo
267.Ft int
268.Fn sprintf "char *buf" "const char *fmt" "..."
269.Xc
270.It Xo
271.Ft void
272.Fn vsprintf "char *buf" "const char *fmt" "va_list ap"
273.Xc
274.Pp
275The *printf functions implement a subset of the standard
276.Fn printf
277family functionality and some extensions.
278The following standard conversions
279are supported: c,d,n,o,p,s,u,x.
280The following modifiers are supported:
281+,-,#,*,0,field width,precision,l.
282.Pp
283The
284.Li b
285conversion is provided to decode error registers.
286Its usage is:
287.Bd -ragged -offset indent
288printf(
289.Qq reg=%b\en ,
290regval,
291.Qq <base><arg>*
292);
293.Ed
294.Pp
295where <base> is the output expressed as a control character, e.g.\& \e10 gives
296octal, \e20 gives hex.
297Each <arg> is a sequence of characters, the first of
298which gives the bit number to be inspected (origin 1) and the next characters
299(up to a character less than 32) give the text to be displayed if the bit is set.
300Thus
301.Bd -ragged -offset indent
302printf(
303.Qq reg=%b\en ,
3043,
305.Qq \e10\e2BITTWO\e1BITONE
306);
307.Ed
308.Pp
309would give the output
310.Bd -ragged -offset indent
311reg=3<BITTWO,BITONE>
312.Ed
313.Pp
314The
315.Li D
316conversion provides a hexdump facility, e.g.
317.Bd -ragged -offset indent
318printf(
319.Qq %6D ,
320ptr,
321.Qq \&:
322); gives
323.Qq XX:XX:XX:XX:XX:XX
324.Ed
325.Bd -ragged -offset indent
326printf(
327.Qq %*D ,
328len,
329ptr,
330.Qq "\ "
331); gives
332.Qq XX XX XX ...
333.Ed
334.El
335.Sh CHARACTER TESTS AND CONVERSIONS
336.Bl -hang -width 10n
337.It Xo
338.Ft int
339.Fn isupper "int c"
340.Xc
341.It Xo
342.Ft int
343.Fn islower "int c"
344.Xc
345.It Xo
346.Ft int
347.Fn isspace "int c"
348.Xc
349.It Xo
350.Ft int
351.Fn isdigit "int c"
352.Xc
353.It Xo
354.Ft int
355.Fn isxdigit "int c"
356.Xc
357.It Xo
358.Ft int
359.Fn isascii "int c"
360.Xc
361.It Xo
362.Ft int
363.Fn isalpha "int c"
364.Xc
365.It Xo
366.Ft int
367.Fn isalnum "int c"
368.Xc
369.It Xo
370.Ft int
371.Fn iscntrl "int c"
372.Xc
373.It Xo
374.Ft int
375.Fn isgraph "int c"
376.Xc
377.It Xo
378.Ft int
379.Fn ispunct "int c"
380.Xc
381.It Xo
382.Ft int
383.Fn toupper "int c"
384.Xc
385.It Xo
386.Ft int
387.Fn tolower "int c"
388.Xc
389.El
390.Sh FILE I/O
391.Bl -hang -width 10n
392.It Xo
393.Ft int
394.Fn open "const char *path" "int flags"
395.Xc
396.Pp
397Similar to the behaviour as specified in
398.Xr open 2 ,
399except that file creation is not supported, so the mode parameter is not
400required.
401The
402.Fa flags
403argument may be one of O_RDONLY, O_WRONLY and O_RDWR.
404Only UFS currently supports writing.
405.It Xo
406.Ft int
407.Fn close "int fd"
408.Xc
409.It Xo
410.Ft void
411.Fn closeall void
412.Xc
413.Pp
414Close all open files.
415.It Xo
416.Ft ssize_t
417.Fn read "int fd" "void *buf" "size_t len"
418.Xc
419.It Xo
420.Ft ssize_t
421.Fn write "int fd" "void *buf" "size_t len"
422.Xc
423.Pp
424(No file systems currently support writing.)
425.It Xo
426.Ft off_t
427.Fn lseek "int fd" "off_t offset" "int whence"
428.Xc
429.Pp
430Files being automatically uncompressed during reading cannot seek backwards
431from the current point.
432.It Xo
433.Ft int
434.Fn stat "const char *path" "struct stat *sb"
435.Xc
436.It Xo
437.Ft int
438.Fn fstat "int fd" "struct stat *sb"
439.Xc
440.Pp
441The
442.Fn stat
443and
444.Fn fstat
445functions only fill out the following fields in the
446.Fa sb
447structure: st_mode,st_nlink,st_uid,st_gid,st_size.
448The
449.Nm tftp
450file system cannot provide meaningful values for this call, and the
451.Nm cd9660
452file system always reports files having uid/gid of zero.
453.El
454.Sh PAGER
455The
456.Nm
457library supplies a simple internal pager to ease reading the output of large
458commands.
459.Bl -hang -width 10n
460.It Xo
461.Ft void
462.Fn pager_open
463.Xc
464.Pp
465Initialises the pager and tells it that the next line output will be the top of the
466display.
467The environment variable LINES is consulted to determine the number of
468lines to be displayed before pausing.
469.It Xo
470.Ft void
471.Fn pager_close void
472.Xc
473.Pp
474Closes the pager.
475.It Xo
476.Ft int
477.Fn pager_output "const char *lines"
478.Xc
479.Pp
480Sends the lines in the
481.Dv NUL Ns
482-terminated buffer at
483.Fa lines
484to the pager.
485Newline characters are counted in order to determine the number
486of lines being output (wrapped lines are not accounted for).
487The
488.Fn pager_output
489function will return zero when all of the lines have been output, or nonzero
490if the display was paused and the user elected to quit.
491.It Xo
492.Ft int
493.Fn pager_file "const char *fname"
494.Xc
495.Pp
496Attempts to open and display the file
497.Fa fname .
498Returns -1 on error, 0 at EOF, or 1 if the user elects to quit while reading.
499.El
500.Sh FEATURE SUPPORT
501A set of functions are provided to communicate support of features from the
502loader binary to the interpreter.
503These are used to do something sensible if we are still operating with a loader
504binary that behaves differently than expected.
505.Bl -hang -width 10n
506.It Xo
507.Ft void
508.Fn feature_enable "uint32_t mask"
509.Xc
510.Pp
511Enable the referenced
512.Fa mask
513feature, which should be one of the
514.Li FEATURE_*
515macros defined in
516.In stand.h .
517.It Xo
518.Ft bool
519.Fn feature_name_is_enabled "const char *name"
520.Xc
521.Pp
522Check if the referenced
523.Fa name
524feature is enabled.
525The
526.Fa name
527is usually the same name as the
528.Li FEATURE_*
529macro, but with the FEATURE_ prefix stripped off.
530The authoritative source of feature names is the mapping table near the top in
531.Pa stand/libsa/features.c .
532.It Xo
533.Ft void
534.Fn "(feature_iter_fn)" "void *cookie" "const char *name" "const char *desc" "bool enabled"
535.Xc
536.Pp
537The
538.Fa cookie
539argument is passed as-is from the argument of the same name to
540.Fn feature_iter .
541The
542.Fa name
543and
544.Fa desc
545arguments are defined in the mapping table in
546.Pa stand/libsa/features.c .
547The
548.Fa enabled
549argument indicates the current status of the feature, though one could
550theoretically turn a feature off in later execution.
551As such, this should likely not be trusted if it is needed after the iteration
552has finished.
553.It Xo
554.Ft void
555.Fn "feature_iter" "feature_iter_fn *iter_fn" "void *cookie"
556.Xc
557.Pp
558Iterate over the current set of features.
559.El
560.Sh MISC
561.Bl -hang -width 10n
562.It Xo
563.Ft char *
564.Fn devformat "struct devdesc *"
565.Xc
566.Pp
567Format the specified device as a string.
568.It Xo
569.Ft int
570.Fn devparse "struct devdesc **dev" "const char *devdesc" "const char **path"
571.Xc
572.Pp
573Parse the
574.Dv devdesc
575string of the form
576.Sq device:[/path/to/file] .
577The
578.Dv devsw
579table is used to match the start of the
580.Sq device
581string with
582.Fa dv_name .
583If
584.Fa dv_parsedev
585is non-NULL, then it will be called to parse the rest of the string and allocate
586the
587.Dv struct devdesc
588for this path.
589If NULL, then a default routine will be called that will allocate a simple
590.Dv struct devdesc ,
591parse a unit number and ensure there's no trailing characters.
592If
593.Dv path
594is non-NULL, then a pointer to the remainder of the
595.Dv devdesc
596string after the device specification is written.
597.It Xo
598.Ft int
599.Fn devinit void
600.Xc
601.Pp
602Calls all the
603.Fa dv_init
604routines in the
605.Dv devsw
606array, returning the number of routines that returned an error.
607.It Xo
608.Ft void
609.Fn twiddle void
610.Xc
611.Pp
612Successive calls emit the characters in the sequence |,/,-,\\ followed by a
613backspace in order to provide reassurance to the user.
614.El
615.Sh REQUIRED LOW-LEVEL SUPPORT
616The following resources are consumed by
617.Nm
618- stack, heap, console and devices.
619.Pp
620The stack must be established before
621.Nm
622functions can be invoked.
623Stack requirements vary depending on the functions
624and file systems used by the consumer and the support layer functions detailed
625below.
626.Pp
627The heap must be established before calling
628.Fn alloc
629or
630.Fn open
631by calling
632.Fn setheap .
633Heap usage will vary depending on the number of simultaneously open files,
634as well as client behaviour.
635Automatic decompression will allocate more
636than 64K of data per open file.
637.Pp
638Console access is performed via the
639.Fn getchar ,
640.Fn putchar
641and
642.Fn ischar
643functions detailed below.
644.Pp
645Device access is initiated via
646.Fn devopen
647and is performed through the
648.Fn dv_strategy ,
649.Fn dv_ioctl
650and
651.Fn dv_close
652functions in the device switch structure that
653.Fn devopen
654returns.
655.Pp
656The consumer must provide the following support functions:
657.Bl -hang -width 10n
658.It Xo
659.Ft int
660.Fn getchar void
661.Xc
662.Pp
663Return a character from the console, used by
664.Fn gets ,
665.Fn ngets
666and pager functions.
667.It Xo
668.Ft int
669.Fn ischar void
670.Xc
671.Pp
672Returns nonzero if a character is waiting from the console.
673.It Xo
674.Ft void
675.Fn putchar int
676.Xc
677.Pp
678Write a character to the console, used by
679.Fn gets ,
680.Fn ngets ,
681.Fn *printf ,
682.Fn panic
683and
684.Fn twiddle
685and thus by many other functions for debugging and informational output.
686.It Xo
687.Ft int
688.Fn devopen "struct open_file *of" "const char *name" "const char **file"
689.Xc
690.Pp
691Open the appropriate device for the file named in
692.Fa name ,
693returning in
694.Fa file
695a pointer to the remaining body of
696.Fa name
697which does not refer to the device.
698The
699.Va f_dev
700field in
701.Fa of
702will be set to point to the
703.Vt devsw
704structure for the opened device if successful.
705Device identifiers must
706always precede the path component, but may otherwise be arbitrarily formatted.
707Used by
708.Fn open
709and thus for all device-related I/O.
710.It Xo
711.Ft int
712.Fn devclose "struct open_file *of"
713.Xc
714.Pp
715Close the device allocated for
716.Fa of .
717The device driver itself will already have been called for the close; this call
718should clean up any allocation made by devopen only.
719.It Xo
720.Ft void
721.Fn __abort
722.Xc
723.Pp
724Calls
725.Fn panic
726with a fixed string.
727.It Xo
728.Ft void
729.Fn panic "const char *msg" "..."
730.Xc
731.Pp
732Signal a fatal and unrecoverable error condition.
733The
734.Fa msg ...
735arguments are as for
736.Fn printf .
737.El
738.Sh INTERNAL FILE SYSTEMS
739Internal file systems are enabled by the consumer exporting the array
740.Vt struct fs_ops *file_system[] ,
741which should be initialised with pointers
742to
743.Vt struct fs_ops
744structures.
745The following file system handlers are supplied by
746.Nm ,
747the consumer may supply other file systems of their own:
748.Bl -hang -width ".Va cd9660_fsops"
749.It Va ufs_fsops
750The
751.Bx
752UFS.
753.It Va ext2fs_fsops
754Linux ext2fs file system.
755.It Va tftp_fsops
756File access via TFTP.
757.It Va nfs_fsops
758File access via NFS.
759.It Va cd9660_fsops
760ISO 9660 (CD-ROM) file system.
761.It Va gzipfs_fsops
762Stacked file system supporting gzipped files.
763When trying the gzipfs file system,
764.Nm
765appends
766.Li .gz
767to the end of the filename, and then tries to locate the file using the other
768file systems.
769Placement of this file system in the
770.Va file_system[]
771array determines whether gzipped files will be opened in preference to non-gzipped
772files.
773It is only possible to seek a gzipped file forwards, and
774.Fn stat
775and
776.Fn fstat
777on gzipped files will report an invalid length.
778.It Va bzipfs_fsops
779The same as
780.Va gzipfs_fsops ,
781but for
782.Xr bzip2 1 Ns -compressed
783files.
784.It Va pkgfs_fsops
785File access from a tar file typically streamed via TFTP.
786The order of files in the tar file must match the order they are
787to be consumed as rewind is not practical.
788.El
789.Pp
790The array of
791.Vt struct fs_ops
792pointers should be terminated with a NULL.
793.Sh DEVICES
794Devices are exported by the supporting code via the array
795.Vt struct devsw *devsw[]
796which is a NULL terminated array of pointers to device switch structures.
797.Sh DRIVER INTERFACE
798The driver needs to provide a common set of entry points that are
799used by
800.Nm libsa
801to interface with the device.
802.Bd -literal
803struct devsw {
804    const char	dv_name[DEV_NAMLEN];
805    int		dv_type;
806    int		(*dv_init)(void);
807    int		(*dv_strategy)(void *devdata, int rw, daddr_t blk,
808			size_t size, char *buf, size_t *rsize);
809    int		(*dv_open)(struct open_file *f, ...);
810    int		(*dv_close)(struct open_file *f);
811    int		(*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
812    int		(*dv_print)(int verbose);
813    void	(*dv_cleanup)(void);
814    char *	(*dv_fmtdev)(struct devdesc *);
815    int		(*dv_parsedev)(struct devdesc **dev, const char *devpart,
816    		const char **path);
817    bool	(*dv_match)(struct devsw *dv, const char *devspec);
818};
819.Ed
820.Bl -tag -width ".Fn dv_strategy"
821.It Fn dv_name
822The device's name.
823.It Fn dv_type
824Type of device.
825The supported types are:
826.Bl -tag -width "DEVT_NONE"
827.It DEVT_NONE
828.It DEVT_DISK
829.It DEVT_NET
830.It DEVT_CD
831.It DEVT_ZFS
832.It DEVT_FD
833.El
834Each type may have its own associated (struct type_devdesc),
835which has the generic (struct devdesc) as its first member.
836.It Fn dv_init
837Driver initialization routine.
838This routine should probe for available units.
839Drivers are responsible for maintaining lists of units for later enumeration.
840No other driver routines may be called before
841.Fn dv_init
842returns.
843.It Fn dv_open
844The driver open routine.
845.It Fn dv_close
846The driver close routine.
847.It Fn dv_ioctl
848The driver ioctl routine.
849.It Fn dv_print
850Prints information about the available devices.
851Information should be presented with
852.Fn pager_output .
853.It Fn dv_cleanup
854Cleans up any memory used by the device before the next stage is run.
855.It Fn dv_fmtdev
856Converts the specified devdesc to the canonical string representation
857for that device.
858.It Fn dv_parsedev
859Parses the device portion of a file path.
860The
861.Dv devpart
862will point to the
863.Sq tail
864of device name, possibly followed by a colon and a path within the device.
865The
866.Sq tail
867is, by convention, the part of the device specification that follows the
868.Fa dv_name
869part of the string.
870So when
871.Fa devparse
872is parsing the string
873.Dq disk3p5:/xxx ,
874.Dv devpart
875will point to the
876.Sq 3
877in that string.
878The parsing routine is expected to allocate a new
879.Dv struct devdesc
880or subclass and return it in
881.Dv dev
882when successful.
883This routine should set
884.Dv path
885to point to the portion of the string after device specification, or
886.Dq /xxx
887in the earlier example.
888Generally, code needing to parse a path will use
889.Fa devparse
890instead of calling this routine directly.
891.It Fn dv_match
892.Dv NULL
893to specify that all device paths starting with
894.Fa dv_name
895match.
896Otherwise, this function returns 0 for a match and a non-zero
897.Dv errno
898to indicate why it didn't match.
899This is helpful when you claim the device path after using it to query
900properties on systems that have uniform naming for different types of
901devices.
902.El
903.Sh HISTORY
904The
905.Nm
906library contains contributions from many sources, including:
907.Bl -bullet -compact
908.It
909.Nm libsa
910from
911.Nx
912.It
913.Nm libc
914and
915.Nm libkern
916from
917.Fx 3.0 .
918.It
919.Nm zalloc
920from
921.An Matthew Dillon Aq Mt dillon@backplane.com
922.El
923.Pp
924The reorganisation and port to
925.Fx 3.0 ,
926the environment functions and this manpage were written by
927.An Mike Smith Aq Mt msmith@FreeBSD.org .
928.Sh BUGS
929The lack of detailed memory usage data is unhelpful.
930