190792Sgshapiro<html>
290792Sgshapiro<head>
390792Sgshapiro<title>libsm sm_io general overview</title>
490792Sgshapiro</head>
590792Sgshapiro<body>
690792Sgshapiro<a href="index.html">Back to libsm overview</a>
790792Sgshapiro<center>
890792Sgshapiro<h1>libsm sm_io general overview</h1>
9266711Sgshapiro<br> $Id: io.html,v 1.3 2001-03-17 03:22:50 gshapiro Exp $
1090792Sgshapiro</center>
1190792Sgshapiro<h2> Introduction </h2>
1290792Sgshapiro<p>
1390792SgshapiroThe <i>sm_io</i> portion of the <i>libsm</i> library is similar to
1490792Sgshapirothe <i>stdio</i> library. It is derived from the Chris Torek version
1590792Sgshapiroof the <i>stdio</i> library (BSD). There are some key differences
1690792Sgshapirodescribed below between <i>sm_io</i> and <i>stdio</i> but many
1790792Sgshapirosimilarities will be noticed.
1890792Sgshapiro</p>
1990792Sgshapiro<p>
2090792SgshapiroA key difference between <i>stdio</i> and <i>sm_io</i> is that the
2190792Sgshapirofunctional code that does the open, close, read, write, etc. on a file
2290792Sgshapirocan be different for different files. For example, with <i>stdio</i>
2390792Sgshapirothe functional code (read, write) is either the default supplied in the
2490792Sgshapirolibrary or a "programmer specified" set of functions set via
2590792Sgshapiro<i>sm_io_open()</i>. Whichever set of functions are specified <b>all</b>
2690792Sgshapiroopen's, read's, write's, etc use the same set of functions. In contrast, with
2790792Sgshapiro<i>sm_io</i> a different set of functions can be specified with each
2890792Sgshapiroactive file for read's, write's, etc. These different function sets
2990792Sgshapiroare identified as <b>file types</b> (see <tt>sm_io_open()</tt>). Each function
3090792Sgshapiroset can handle the actions directly, pass the action request to
3190792Sgshapiroanother function set or do some work before passing it on to another function
3290792Sgshapiroset. The setting of a function set for a file type can be done for
3390792Sgshapiroa file type at any time (even after the type is open).
3490792Sgshapiro</p>
3590792Sgshapiro<p>
3690792SgshapiroA second difference is the use of <a href="rpool.html"><b>rpools</b></a>.
3790792SgshapiroAn <b>rpool</b> is specified with the opening of a file
3890792Sgshapiro(<tt>sm_io_open()</tt>).
3990792SgshapiroThis allows of a file to be associated with an rpool so that when the
4090792Sgshapirorpool is released the open file will be closed; the <tt>sm_io_open()</tt>
4190792Sgshapiroregisters that <tt>sm_io_close()</tt> should be called when the rpool is
4290792Sgshapiroreleased.
4390792Sgshapiro</p>
4490792Sgshapiro<p>
4590792SgshapiroA third difference is that the I/O functions take a <i>timeout</i>
4690792Sgshapiroargument. This allows the setting of a maximum amount of time allowable
4790792Sgshapirofor the I/O to be completed. This means the calling program does not need
4890792Sgshapiroto setup it's own timeout mechanism. NOTE: SIGALRM's should not be
4990792Sgshapiroactive in the calling program when an I/O function with a <i>timeout</i>
5090792Sgshapirois used.
5190792Sgshapiro</p>
5290792Sgshapiro<p>
5390792SgshapiroWhen converting source code from <i>stdio</i> to <i>sm_io</i> be
5490792Sgshapirovery careful to NOTE: the arguments to functions have been rationalized.
5590792SgshapiroThat is, unlike <i>stdio</i>, all <i>sm_io</i> functions that
5690792Sgshapirotake a file pointer (SM_FILE_T *) argument have the file pointer
5790792Sgshapiroas the first argument. Also not all functions with <i>stdio</i> have
5890792Sgshapiroan identical matching <i>sm_io</i> API: the API list has been thinned
5990792Sgshapirosince a number of <i>stdio</i> API's overlapped in functionality.
6090792SgshapiroRemember many functions also have a <i>timeout</i> argument added.
6190792Sgshapiro</p>
6290792Sgshapiro<p>
6390792SgshapiroWhen a file is going to be opened, the file type is included with
6490792Sgshapiro<tt>sm_io_open()</tt>.
6590792SgshapiroA file type is either one automatically included with the <i>sm_io</i>
6690792Sgshapirolibrary or one created by the program at runtime.
6790792SgshapiroFile types can be either buffered or unbuffered. When buffered the buffering
6890792Sgshapirois either the builtin <i>sm_io</i> buffering or as done by the file type.
6990792SgshapiroFile types can be disk files, strings, TCP/IP connections or whatever
7090792Sgshapiroyour imagination can come up with that can be read and/or written to.
7190792Sgshapiro</p>
7290792Sgshapiro<p>
7390792SgshapiroInformation about a particular file type or pointer can be obtained or set with
7490792Sgshapirothe <i>sm_io</i> "info" functions.
7590792SgshapiroThe <tt>sm_io_setinfo()</tt> and <tt>sm_io_getinfo()</tt> functions work on
7690792Sgshapiroan active file pointer.
7790792Sgshapiro</p>
7890792Sgshapiro<h2>Include files</h2>
7990792Sgshapiro<p>
8090792SgshapiroThere is one main include file for use with sm_io: <i>io.h</i>. Since the
8190792Sgshapirouse of <b>rpools</b> is specified with <tt>sm_io_open()</tt> an
8290792Sgshapiro<b>rpool</b> may
8390792Sgshapirobe created and thus <i>rpool.h</i> may need to be included as well
8490792Sgshapiro(before io.h).
8590792Sgshapiro</p>
8690792Sgshapiro<pre>
8790792Sgshapiro#include &lt;rpool.h&gt;
8890792Sgshapiro#include &lt;io.h&gt;
8990792Sgshapiro</pre>
9090792Sgshapiro
9190792Sgshapiro<h2>Functions/API's</h2>
9290792Sgshapiro<p>
9390792SgshapiroBelow is a list of the functions for <i>sm_io</i> listed in
9490792Sgshapiroalphabetical order. Currently these functions return error codes
9590792Sgshapiroand set errno when appropriate. These (may?/will?) change to
9690792Sgshapiroraising exceptions later.
9790792Sgshapiro</p>
9890792Sgshapiro<pre>
9990792Sgshapiro<a href="#sm_io_autoflush">SM_FILE_T *sm_io_autoflush(SM_FILE_T *fp, SM_FILE_T *)</a>
10090792Sgshapiro
10190792Sgshapiro<a href="#sm_io_automode">void sm_io_automode(SM_FILE_T *fp, SM_FILE_T *)</a>
10290792Sgshapiro
10390792Sgshapiro<a href="#defaultapi">void sm_io_clearerr(SM_FILE_T *fp)</a>
10490792Sgshapiro
10590792Sgshapiro<a href="#sm_io_close">int sm_io_close(SM_FILE_T *fp, int timeout)</a>
10690792Sgshapiro
10790792Sgshapiro<a href="#defaultapi">int sm_io_dup(SM_FILE_T *fp)</a>
10890792Sgshapiro
10990792Sgshapiro<a href="#defaultapi">int sm_io_eof(SM_FILE_T *fp)</a>
11090792Sgshapiro
11190792Sgshapiro<a href="#defaultapi">int sm_io_error(SM_FILE_T *fp)</a>
11290792Sgshapiro
11390792Sgshapiro<a href="#defaultapi">char * sm_io_fgets(SM_FILE_T *fp, int timeout, char *buf, int n)</a>
11490792Sgshapiro
11590792Sgshapiro<a href="#defaultapi">int sm_io_flush(SM_FILE_T *fp, int timeout)</a>
11690792Sgshapiro
11790792Sgshapiro<a href="#sm_io_fopen">int sm_io_fopen(char *pathname, int flags [, MODE_T mode])</a>
11890792Sgshapiro
11990792Sgshapiro<a href="#defaultapi">int sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...)</a>
12090792Sgshapiro
12190792Sgshapiro<a href="#defaultapi">int sm_io_fputs(s, int, SM_FILE_T *fp)</a>
12290792Sgshapiro
12390792Sgshapiro<a href="#defaultapi">int sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) </a>
12490792Sgshapiro
12590792Sgshapiro<a href="#defaultapi">int sm_io_getc(SM_FILE_T *fp, int timeout)</a>
12690792Sgshapiro
12790792Sgshapiro<a href="#sm_io_getinfo">void sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)</a>
12890792Sgshapiro
12990792Sgshapiro<a href="#sm_io_open">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a>
13090792Sgshapiro
13190792Sgshapiro<a href="#defaultapi">int sm_io_purge(SM_FILE_T *fp)</a>
13290792Sgshapiro
13390792Sgshapiro<a href="#defaultapi">int sm_io_putc(SM_FILE_T *fp, int timeout, int c)</a>
13490792Sgshapiro
13590792Sgshapiro<a href="#defaultapi">size_t sm_io_read(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a>
13690792Sgshapiro
13790792Sgshapiro<a href="#sm_io_reopen">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a>
13890792Sgshapiro
13990792Sgshapiro<a href="#defaultapi">void sm_io_rewind(SM_FILE_T *fp, int timeout)</a>
14090792Sgshapiro
14190792Sgshapiro<a href="#defaultapi">int sm_io_seek(SM_FILE_T *fp, off_t offset, int timeout, int whence)</a>
14290792Sgshapiro
14390792Sgshapiro<a href="#sm_io_setinfo">void sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)</a>
14490792Sgshapiro
14590792Sgshapiro<a href="#defaultapi">int sm_io_setvbuf(SM_FILE_T *fp, int timeout, char *buf, int mode, size_t size)</a>
14690792Sgshapiro
14790792Sgshapiro<a href="#defaultapi">int sm_io_sscanf(const char *str, char const *fmt, ...)</a>
14890792Sgshapiro
14990792Sgshapiro<a href="#defaultapi">long sm_io_tell(SM_FILE_T *fp, int timeout)</a>
15090792Sgshapiro
15190792Sgshapiro<a href="#defaultapi">int sm_io_ungetc(SM_FILE_T *fp, int timeout, int c)</a>
15290792Sgshapiro
15390792Sgshapiro<a href="#defaultapi">size_t sm_io_write(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a>
15490792Sgshapiro
15590792Sgshapiro<a href="#defaultapi">int sm_snprintf(char *str, size_t n, char const *fmt, ...)</a>
15690792Sgshapiro
15790792Sgshapiro</pre>
15890792Sgshapiro<a name="timeouts">
15990792Sgshapiro<h2>Timeouts</h2>
16090792Sgshapiro<p>
16190792SgshapiroFor many of the functions a <i>timeout</i> argument is given. This limits
16290792Sgshapirothe amount of time allowed for the function to complete. There are three
16390792Sgshapiropre-defined values:
16490792Sgshapiro<menu>
16590792Sgshapiro<li>
16690792SgshapiroSM_TIME_DEFAULT - timeout using the default setting for this file type
16790792Sgshapiro</li>
16890792Sgshapiro<li>
16990792SgshapiroSM_TIME_FOREVER - timeout will take forever; blocks until task completed
17090792Sgshapiro</li>
17190792Sgshapiro<li>
17290792SgshapiroSM_TIME_IMMEDIATE - timeout (virtually) now
17390792Sgshapiro</li>
17490792Sgshapiro</menu>
17590792Sgshapiro</p>
17690792Sgshapiro<p>
17790792SgshapiroA function caller can also specify a positive integer value in milliseconds.
17890792SgshapiroA function will return with <i>errno</i> set to EINVAL if a bad value
17990792Sgshapirois given for <i>timeout</i>.
18090792SgshapiroWhen a function times out the function returns in error with <i>errno</i>
18190792Sgshapiroset to <b>EAGAIN</b>. In the future this may change to an exception being
18290792Sgshapirothrown.
18390792Sgshapiro</p>
18490792Sgshapiro<h2>Function Descriptions</h2>
18590792Sgshapiro<dl>
18690792Sgshapiro<!-- SM_IO_FOPEN -->
18790792Sgshapiro<p></p>
18890792Sgshapiro<dt><tt><a name="sm_io_fopen">
18990792SgshapiroSM_FILE_T *
19090792Sgshapiro<br>
19190792Sgshapirosm_io_fopen(char *pathname, int flags)
19290792Sgshapiro<br>
19390792SgshapiroSM_FILE_T *
19490792Sgshapiro<br>
19590792Sgshapirosm_io_fopen(char *pathname, int flags, MODE_T mode)
19690792Sgshapiro</a></tt></dt>
19790792Sgshapiro<dd>
19890792SgshapiroOpen the file named by <tt>pathname</tt>, and associate a stream with it.
19990792SgshapiroThe arguments are the same as for the <tt>open(2)</tt> system call.
20090792Sgshapiro<br>
20190792SgshapiroIf memory could not be allocated, an exception is raised.
20290792SgshapiroIf successful, an <tt>SM_FILE_T</tt> pointer is returned.
20390792SgshapiroOtherwise, <tt>NULL</tt> is returned and <tt>errno</tt> is set.
20490792Sgshapiro<!-- SM_IO_OPEN -->
20590792Sgshapiro<p></p>
20690792Sgshapiro<dt><tt><a name="sm_io_open">
20790792SgshapiroSM_FILE_T *
20890792Sgshapiro<br>
20990792Sgshapirosm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool)
21090792Sgshapiro</a></tt></dt>
21190792Sgshapiro<dd>
21290792SgshapiroOpens a file by <i>type</i> directed by <i>info</i>. <i>Type</i> is a filled-in
21390792SgshapiroSM_FILE_T structure from the following builtin list
21490792Sgshapiro(<a href="#builtins"><b>descriptions below</b></a>)
21590792Sgshapiroor one specified by the program. 
21690792Sgshapiro<menu>
21790792Sgshapiro<li>
21890792SgshapiroSmFtString
21990792Sgshapiro</li>
22090792Sgshapiro<li>
22190792SgshapiroSmFtStdio
22290792Sgshapiro</li>
22390792Sgshapiro<li>
22490792SgshapiroSmFtStdiofd
22590792Sgshapiro</li>
22690792Sgshapiro<li>
22790792Sgshapirosmioin <b>*</b>
22890792Sgshapiro</li>
22990792Sgshapiro<li>
23090792Sgshapirosmioout <b>*</b>
23190792Sgshapiro</li>
23290792Sgshapiro<li>
23390792Sgshapirosmioerr <b>*</b>
23490792Sgshapiro</li>
23590792Sgshapiro<li>
23690792Sgshapirosmiostdin <b>*</b>
23790792Sgshapiro</li>
23890792Sgshapiro<li>
23990792Sgshapirosmiostdout <b>*</b>
24090792Sgshapiro</li>
24190792Sgshapiro<li>
24290792Sgshapirosmiostderr <b>*</b>
24390792Sgshapiro</li>
24490792Sgshapiro<li>
24590792SgshapiroSmFtSyslog
24690792Sgshapiro</li>
24790792Sgshapiro</menu>
24890792Sgshapiro<br>
24990792SgshapiroThe above list of file types are already appropriately filled in. Those marked
25090792Sgshapirowith a "<b>*</b>" are already open and may be used directly and immediately.
25190792SgshapiroFor program specified types, to set the <i>type</i> argument easily and with minimal error the macro
25290792Sgshapiro<b>SM_IO_SET_TYPE</b> should be used. The SM_FILE_T structure is fairly
25390792Sgshapirolarge, but only a small portion of it need to be initialized for a new
25490792Sgshapirotype.
25590792SgshapiroSee also <a href="#writefunctions">"Writing Functions for a File Type"</a>.
25690792Sgshapiro<menu>
25790792Sgshapiro<pre>
25890792SgshapiroSM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
25990792Sgshapiro</pre>
26090792Sgshapiro</menu>
26190792Sgshapiro<br>
26290792Sgshapiro<i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a>
26390792Sgshapirosection.
26490792Sgshapiro<br>
26590792Sgshapiro<i>Info</i> is information that describes for the file type what is
26690792Sgshapiroto be opened and any associated information.
26790792SgshapiroFor a disk file this would be a file path; with a TCP
26890792Sgshapiroconnection this could be an a structure containing an IP address and port.
26990792Sgshapiro<br><i>Flags</i> is a
27090792Sgshapiroset of sm_io flags that describes how the file is to be interacted with:
27190792Sgshapiro<menu>
27290792Sgshapiro<li>
27390792SgshapiroSM_IO_RDWR	- read and write
27490792Sgshapiro</li>
27590792Sgshapiro<li>
27690792SgshapiroSM_IO_RDONLY	- read only
27790792Sgshapiro</li>
27890792Sgshapiro<li>
27990792SgshapiroSM_IO_WRONLY	- write only
28090792Sgshapiro</li>
28190792Sgshapiro<li>
28290792SgshapiroSM_IO_APPEND	- allow write to EOF only
28390792Sgshapiro</li>
28490792Sgshapiro<li>
28590792SgshapiroSM_IO_APPENDRW	- allow read-write from EOF only
28690792Sgshapiro</li>
28790792Sgshapiro<li>
28890792SgshapiroSM_IO_RDWRTR	- read and write with truncation of file first
28990792Sgshapiro</li>
29090792Sgshapiro</menu>
29190792Sgshapiro<i>Rpool</i> is the address of the rpool that this open is to be associated
29290792Sgshapirowith. When the rpool is released then the close function for this
29390792Sgshapirofile type will be automatically called to close the file for cleanup.
29490792SgshapiroIf NULL is specified for <i>rpool</i> then the close function is not
29590792Sgshapiroassociated (attached) to an rpool.
29690792Sgshapiro<br>
29790792SgshapiroOn cannot allocate memory, an exception is raised.
29890792SgshapiroIf the <i>type</i> is invalid, <tt>sm_io_open</tt> will abort the process.
29990792SgshapiroOn success an SM_FILE_T * pointer is returned.
30090792SgshapiroOn failure the NULL pointer is returned and errno is set.
30190792Sgshapiro</dd>
30290792Sgshapiro<!-- SM_IO_SETINFO -->
30390792Sgshapiro<p></p>
30490792Sgshapiro<dt><tt><a name="sm_io_setinfo">
30590792Sgshapiroint
30690792Sgshapiro<br>
30790792Sgshapirosm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)
30890792Sgshapiro</a></tt></dt>
30990792Sgshapiro<dd>
31090792SgshapiroFor the open file <i>sfp</i> set the indicated information (<i>what</i>)
31190792Sgshapiroto the new value <i>(valp</i>).
31290792SgshapiroThis will make the change for this SM_FILE_T only. The file
31390792Sgshapirotype that <i>sfp</i> originally belonged to will still be
31490792Sgshapiroconfigured the same way (this is to prevent side-effect
31590792Sgshapiroto other open's of the same file type, particularly with threads).
31690792SgshapiroThe value of <i>what</i> will be file-type dependant since this function
31790792Sgshapirois one of the per file type setable functions.
31890792SgshapiroOne value for <i>what</i> that is valid for all file types is
31990792SgshapiroSM_WHAT_VECTORS. This sets the currently open file with a new function
32090792Sgshapirovector set for open, close, etc. The new values are taken from <i>valp</i>
32190792Sgshapiroa SM_FILE_T filled in by the used via the macro SM_IO_SET_TYPE
32290792Sgshapiro(see and <a href="#writefunctions">
32390792Sgshapiro"Writing Functions for a File Type"</a> for more information).
32490792Sgshapiro<br>
32590792SgshapiroOn success 0 (zero) is returned. On failure -1 is returned and errno is set.
32690792Sgshapiro</dd>
32790792Sgshapiro<!-- SM_IO_GETINFO -->
32890792Sgshapiro<p></p>
32990792Sgshapiro<dt><tt><a name="sm_io_getinfo">
33090792Sgshapiroint
33190792Sgshapiro<br>
33290792Sgshapirosm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)
33390792Sgshapiro</a></tt></dt>
33490792Sgshapiro<dd>
33590792SgshapiroFor the open file <i>sfp</i> get the indicated information (<i>what</i>)
33690792Sgshapiroand place the result in <i>(valp</i>).
33790792SgshapiroThis will obtain information for SM_FILE_T only and may be different than
33890792Sgshapirothe information for the file type it was originally opened as.
33990792SgshapiroThe value of <i>what</i> will be file type dependant since this function
34090792Sgshapirois one of the per file type setable functions.
34190792SgshapiroOne value for <i>what</i> that is valid for all file types is
34290792SgshapiroSM_WHAT_VECTORS. This gets from the currently open file a copy of
34390792Sgshapirothe function vectors and stores them in <i>valp</i> a SM_FILE_T
34490792Sgshapiro(see <a href="#writefunctions">
34590792Sgshapiro"Writing Functions for a File Type"</a> for more information).
34690792Sgshapiro<br>
34790792SgshapiroOn success 0 (zero) is returned. On failure -1 is returned and errno is set.
34890792Sgshapiro</dd>
34990792Sgshapiro<!-- SM_IO_AUTOFLUSH -->
35090792Sgshapiro<p></p>
35190792Sgshapiro<dt><tt><a name="sm_io_autoflush">
35290792Sgshapirovoid
35390792Sgshapiro<br>
35490792Sgshapirosm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2)
35590792Sgshapiro</a></tt></dt>
35690792Sgshapiro<dd>
35790792SgshapiroAssociate a read of <i>fp1</i> with a data flush for <i>fp2</i>. If a read
35890792Sgshapiroof <i>fp1</i> discovers that there is no data available to be read, then
35990792Sgshapiro<i>fp2</i> will have it's data buffer flushed for writable data. It is
36090792Sgshapiroassumed that <i>fp1</i> is open for reading and <i>fp2</i> is open
36190792Sgshapirofor writing.
36290792Sgshapiro<br>
36390792SgshapiroOn return the old file pointer associated with <i>fp1</i> for flushing
36490792Sgshapirois returned. A return of NULL is no an error; this merely indicates no
36590792Sgshapiroprevious association.
36690792Sgshapiro</dd>
36790792Sgshapiro<!-- SM_IO_AUTOMODE -->
36890792Sgshapiro<p></p>
36990792Sgshapiro<dt><tt><a name="sm_io_automode">
37090792Sgshapirovoid
37190792Sgshapiro<br>
37290792Sgshapirosm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2)
37390792Sgshapiro<dt><tt><a name="sm_io_automode">
37490792Sgshapiro</a></tt></dt>
37590792Sgshapiro<dd>
37690792SgshapiroAssociate the two file pointers for blocking/non-blocking mode changes.
37790792SgshapiroIn the handling of timeouts <i>sm_io</i> may need to switch the mode of
37890792Sgshapiroa file between blocking and non-blocking. If the underlying file descriptor
37990792Sgshapirohas been duplicated with <tt>dup(2)</tt> and these descriptors are used
38090792Sgshapiroby <i>sm_io</i> (for example with an SmFtStdiofd file type), then this API
38190792Sgshapiroshould be called to associate them. Otherwise odd behavior (i.e. errors)
38290792Sgshapiromay result that is not consistently reproducable nor easily identifiable.
38390792Sgshapiro</dd>
38490792Sgshapiro<!-- SM_IO_CLOSE -->
38590792Sgshapiro<p></p>
38690792Sgshapiro<dt><tt><a name="sm_io_close">
38790792Sgshapiroint
38890792Sgshapiro<br>
38990792Sgshapirosm_io_close(SM_FILE_T *sfp, int timeout)
39090792Sgshapiro</a></tt></dt>
39190792Sgshapiro<dd>
39290792SgshapiroRelease all resources (file handles, memory, etc.) associated with
39390792Sgshapirothe open SM_FILE_T <i>sfp</i>. If buffering is active then the
39490792Sgshapirobuffer is flushed before any resources are released.
39590792Sgshapiro<i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a>
39690792Sgshapirosection.
39790792SgshapiroThe first resources released after buffer flushing will be the
39890792Sgshapirobuffer itself. Then the <b>close</b> function specified in the
39990792Sgshapirofile type at open will be called. It is the responsibility
40090792Sgshapiroof the <b>close</b> function to release any file type
40190792Sgshapirospecific resources allocated and to call <tt>sm_io_close()</tt>
40290792Sgshapirofor the next file type layer(s) that the current file type uses (if any).
40390792Sgshapiro<br>
40490792SgshapiroOn success 0 (zero) is returned. On failure SM_IO_EOF is returned and
40590792Sgshapiroerrno is set.
40690792Sgshapiro</dd>
40790792Sgshapiro</dl>
40890792Sgshapiro<h2>
40990792Sgshapiro<a name="builtins">Description of Builtin File Types</a>
41090792Sgshapiro</h2>
41190792Sgshapiro<p>
41290792SgshapiroThere are several builtin file types as mentioned in <tt>sm_io_open()</tt>.
41390792SgshapiroMore file types may be added later.
41490792Sgshapiro</p>
41590792Sgshapiro<dl>
41690792Sgshapiro<p></p>
41790792Sgshapiro<dt><tt>SmFtString</tt></dt>
41890792Sgshapiro<dd>
41990792SgshapiroOperates on a character string. <i>SmFtString</i> is a file type only.
42090792SgshapiroThe string starts at the location 0 (zero)
42190792Sgshapiroand ends at the last character. A read will obtain the requested
42290792Sgshapironumber of characters if available; else as many as possible. A read
42390792Sgshapirowill not terminate the read characters with a NULL ('\0'). A write
42490792Sgshapirowill place the number of requested characters at the current location.
42590792SgshapiroTo append to a string either the pointer must currently be at the end
42690792Sgshapiroof the string or a seek done to position the pointer. The file type
42790792Sgshapirohandles the space needed for the string. Thus space needed for the
42890792Sgshapirostring will be grown automagically without the user worrying about
42990792Sgshapirospace management.
43090792Sgshapiro</dd>
43190792Sgshapiro<dt><tt>SmFtStdio</tt></dt>
43290792Sgshapiro<dd>
43390792SgshapiroA predefined SM_FILE_T structure with function vectors pointing to
43490792Sgshapirofunctions that result in the file-type behaving as the system stdio
43590792Sgshapironormally does. The <i>info</i> portion of the <tt>sm_io_open</tt>
43690792Sgshapirois the path of the file to be opened. Note that this file type
43790792Sgshapirodoes not interact with the system's stdio. Thus a program mixing system
43890792Sgshapirostdio and sm_io stdio (SmFtStdio) will result in uncoordinated input
43990792Sgshapiroand output.
44090792Sgshapiro</dd>
44190792Sgshapiro<dt><tt>SmFtStdiofd</tt></dt>
44290792Sgshapiro<dd>
44390792SgshapiroA predefined SM_FILE_T structure with function vectors pointing to
44490792Sgshapirofunctions that result in the file-type behaving as the system stdio
44590792Sgshapironormally does. The <i>info</i> portion of the <tt>sm_io_open</tt>
44690792Sgshapirois a file descriptor (the value returned by open(2)).  Note that this file type
44790792Sgshapirodoes not interact with the system's stdio. Thus a program mixing system
44890792Sgshapirostdio and sm_io stdio (SmFtStdio) will result in uncoordinated input
44990792Sgshapiroand output.
45090792Sgshapiro</dd>
45190792Sgshapiro<dt><tt>smioin</tt></dt>
45290792Sgshapiro<dt><tt>smioout</tt></dt>
45390792Sgshapiro<dt><tt>smioerr</tt></dt>
45490792Sgshapiro<dd>
45590792SgshapiroThe three types <i>smioin</i>, <i>smioout</i> and <i>smioerr</i> are grouped
45690792Sgshapirotogether. These three types
45790792Sgshapiroperform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i>
45890792Sgshapiroand <i>stderr</i>.  These types are both the names and the file pointers.
45990792SgshapiroThey are already open when a program starts (unless the parent explictly
46090792Sgshapiroclosed file descriptors 0, 1 and 2).
46190792SgshapiroThus <tt>sm_io_open()</tt> should never be called for these types:
46290792Sgshapirothe named file pointers should be used directly.
46390792Sgshapiro<i>Smioin</i> and <i>smioout</i> are buffered
46490792Sgshapiroby default. <i>Smioerr</i> is not buffered by default. Calls to <b>stdio</b>
46590792Sgshapiroare safe to make when using these three<b>sm_io</b> file pointers.
46690792SgshapiroThere is no interaction between <b>sm_io</b> and <b>stdio</b>. Hence,
46790792Sgshapirodue to buffering, the sequence of input and output data from both <b>sm_io</b>
46890792Sgshapiroand <b>stdio</b> at the same time may appear unordered. For
46990792Sgshapirocoordination between <b>sm_io</b> and <b>stdio</b> use the three
47090792Sgshapirofile pointers below (<i>smiostdin, smiostdout, smiostderr</i>).
47190792Sgshapiro</dd>
47290792Sgshapiro<dt><tt>smiostdin</tt></dt>
47390792Sgshapiro<dt><tt>smiostdout</tt></dt>
47490792Sgshapiro<dt><tt>smiostderr</tt></dt>
47590792Sgshapiro<dd>
47690792SgshapiroThe three types <i>smiostdin</i>, <i>smioostdut</i> and <i>smiostderr</i>
47790792Sgshapiroare grouped together. These three types
47890792Sgshapiroperform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i>
47990792Sgshapiroand <i>stderr</i>.  These types are both the names and file pointers.
48090792SgshapiroThey are already open when a program starts (unless the parent explictly
48190792Sgshapiroclose file descriptors 0, 1 and 2).
48290792SgshapiroThus <tt>sm_io_open()</tt> should
48390792Sgshapironever be called: the named file pointers should be used directly.
48490792SgshapiroCalls to <b>stdio</b> are safe to make when using these three<b>sm_io</b>
48590792Sgshapirofile pointers though no code is shared between the two libaries.
48690792SgshapiroHowever, the input and output between <i>sm_io</i> and <i>stdio</i> is
48790792Sgshapirocoordinated for these three file pointers: <i>smiostdin</i>,
48890792Sgshapiro<i>smiostdout</i> and <i>smiostderr</i> are layered on-top-of
48990792Sgshapirothe system's <i>stdio</i>.
49090792Sgshapiro<i>Smiostdin</i>, <i>smiostdout</i>
49190792Sgshapiroand <i>Smiostderr</i> are not buffered by default.
49290792SgshapiroHence, due to buffering in <i>stdio</i> only, the sequence of input and
49390792Sgshapirooutput data from both <b>sm_io</b> and <b>stdio</b> at the same time will
49490792Sgshapiroappear ordered. If <i>sm_io</i> buffering is turned on then the
49590792Sgshapiroinput and output can appear unordered or lost.
49690792Sgshapiro</dd>
49790792Sgshapiro<dt><tt>SmFtSyslog</tt></dt>
49890792Sgshapiro<dd>
49990792SgshapiroThis opens the channel to the system log. Reads are not allowed. Writes
50090792Sgshapirocannot be undone once they have left the <i>sm_io</i> buffer.
50190792SgshapiroThe man pages for <tt>syslog(3)</tt> should be read for information
50290792Sgshapiroon syslog.
50390792Sgshapiro</dd>
50490792Sgshapiro</dl>
50590792Sgshapiro<p></p>
50690792Sgshapiro<hr>
50790792Sgshapiro<p></p>
50890792Sgshapiro<h2>
50990792Sgshapiro<a name="writefunctions">
51090792SgshapiroWriting Functions for a File Type
51190792Sgshapiro</a>
51290792Sgshapiro</h2>
51390792Sgshapiro<p>
51490792SgshapiroWhen writing functions to create a file type a function needs to
51590792Sgshapirobe created for each function vector in the SM_FILE_T structure
51690792Sgshapirothat will be passed to <tt>sm_io_open()</tt> or <tt>sm_io_setinfo()</tt>.
51790792SgshapiroOtherwise the setting will be rejected and <i>errno</i> set to EINVAL.
51890792SgshapiroEach function should accept and handle the number and types of arguments as
51990792Sgshapirodescribed in the portion of the SM_FILE_T structure shown below:
52090792Sgshapiro</p>
52190792Sgshapiro<pre>
52290792Sgshapiro        int      (*open) __P((SM_FILE_T *fp, const void *, int flags,
52390792Sgshapiro                              const void *rpool));
52490792Sgshapiro        int      (*close) __P((SM_FILE_T *fp));
52590792Sgshapiro        int      (*read)  __P((SM_FILE_T *fp, char *buf, size_t size));
52690792Sgshapiro        int      (*write) __P((SM_FILE_T *fp, const char *buf, size_t size));
52790792Sgshapiro        off_t    (*seek)  __P((SM_FILE_T *fp, off_t offset, int whence));
52890792Sgshapiro        int      (*getinfo) __P((SM_FILE_T *fp, int what, void *valp));
52990792Sgshapiro        int      (*setinfo) __P((SM_FILE_T *fp, int what, void *valp));
53090792Sgshapiro</pre>
53190792Sgshapiro<p>
53290792SgshapiroThe macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file
53390792Sgshapirotype for an <tt>sm_io_open()</tt>:
53490792Sgshapiro<menu>
53590792Sgshapiro<pre>
53690792SgshapiroSM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
53790792Sgshapiro</pre>
53890792Sgshapiro<br>
53990792Sgshapirowhere:
54090792Sgshapiro<menu>
54190792Sgshapiro<li>
54290792Sgshapirotype	- is the SM_FILE_T being filled-in
54390792Sgshapiro</li>
54490792Sgshapiro<li>
54590792Sgshapironame	- a human readable character string for human identification purposes
54690792Sgshapiro</li>
54790792Sgshapiro<li>
54890792Sgshapiroopen	- the vector to the open function
54990792Sgshapiro</li>
55090792Sgshapiro<li>
55190792Sgshapiroclose	- the vector to the close function
55290792Sgshapiro</li>
55390792Sgshapiro<li>
55490792Sgshapiroread	- the vector to the read function
55590792Sgshapiro</li>
55690792Sgshapiro<li>
55790792Sgshapirowrite	- the vector to the write function
55890792Sgshapiro</li>
55990792Sgshapiro<li>
56090792Sgshapiroseek	- the vector to the seek function
56190792Sgshapiro</li>
56290792Sgshapiro<li>
56390792Sgshapiroset	- the vector to the set function
56490792Sgshapiro</li>
56590792Sgshapiro<li>
56690792Sgshapiroget	- the vector to the get function
56790792Sgshapiro</li>
56890792Sgshapiro<li>
56990792Sgshapirotimeout	- the default to be used for a timeout when SM_TIME_DEFAULT specified
57090792Sgshapiro</li>
57190792Sgshapiro</menu>
57290792Sgshapiro</menu>
57390792SgshapiroYou should avoid trying to change or use the other structure members of the
57490792SgshapiroSM_FILE_T. The file pointer content (internal structure members) of an active
57590792Sgshapirofile should only be set and observed with the "info" functions.
57690792SgshapiroThe two exceptions to the above statement are the structure members
57790792Sgshapiro<i>cookie</i> and <i>ival</i>. <i>Cookie</i> is of type <tt>void *</tt>
57890792Sgshapirowhile <i>ival</i> is of type <tt>int</tt>. These two structure members exist
57990792Sgshapirospecificly for your created file type to use. The <i>sm_io</i> functions
58090792Sgshapirowill not change or set these two structure members; only specific file type
58190792Sgshapirowill change or set these variables.
58290792Sgshapiro</p>
58390792Sgshapiro<p>
58490792SgshapiroFor maintaining information privately about status for a file type the
58590792Sgshapiroinformation should be encapsulated in a <i>cookie</i>. A <i>cookie</i>
58690792Sgshapirois an opaque type that contains information that is only known to
58790792Sgshapirothe file type layer itself. The <i>sm_io</i> package will know
58890792Sgshapironothing about the contents of the <i>cookie</i>; <i>sm_io</i> only
58990792Sgshapiromaintains the location of the <i>cookie</i> so that it may be passed
59090792Sgshapiroto the functions of a file type. It is up to the file type to
59190792Sgshapirodetermine what to do with the <i>cookie</i>. It is the responsibility
59290792Sgshapiroof the file type's open to create the cookie and point the SM_FILE_T's
59390792Sgshapiro<i>cookie</i> at the address of the cookie.
59490792SgshapiroIt is the responsibility of close to clean up
59590792Sgshapiroany resources that the cookie and instance of the file type have used.
59690792Sgshapiro</p>
59790792Sgshapiro<p>
59890792SgshapiroFor the <i>cookie</i> to be passed to all members of a function type
59990792Sgshapirocleanly the location of the cookie must assigned during
60090792Sgshapirothe call to open. The file type functions should not attempt to
60190792Sgshapiromaintain the <i>cookie</i> internally since the file type may have
60290792Sgshapiroserveral instances (file pointers).
60390792Sgshapiro</p>
60490792Sgshapiro<p>
60590792SgshapiroThe SM_FILE_T's member <i>ival</i> may be used in a manner similar to
60690792Sgshapiro<i>cookie</i>. It is not to be used for maintaining the file's offset
60790792Sgshapiroor access status (other members do that). It is intended as a "light"
60890792Sgshapiroreference.
60990792Sgshapiro</p>
61090792Sgshapiro<p>
61190792SgshapiroThe file type vector functions are called by the <tt>sm_io_*()</tt>
61290792Sgshapirofunctions after <i>sm_io</i> processing has occurred. The <i>sm_io</i>
61390792Sgshapiroprocessing validates SM_FILE_T's and may then handle the call entirely
61490792Sgshapiroitself or pass the request to the file type vector functions.
61590792Sgshapiro</p>
61690792Sgshapiro<p>
61790792SgshapiroAll of the "int" functions should return -1 (minus one) on failure
61890792Sgshapiroand 0 (zero) or greater on success. <i>Errno</i> should be set to
61990792Sgshapiroprovide diagnostic information to the caller if it has not already
62090792Sgshapirobeen set by another function the file type function used.
62190792Sgshapiro</p>
62290792Sgshapiro<p>
62390792SgshapiroExamples are a wonderful manner of clarifying details. Below is an example
62490792Sgshapiroof an open function.
62590792Sgshapiro</p>
62690792Sgshapiro<p>
62790792SgshapiroThis shows the setup.
62890792Sgshapiro<menu>
62990792Sgshapiro<pre>
63090792SgshapiroSM_FILE_T *fp;
63190792SgshapiroSM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite,
63290792Sgshapiro				myseek, myget, myset, SM_TIME_FOREVER);
63390792Sgshapiro
63490792Sgshapirofp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL);
63590792Sgshapiro
63690792Sgshapiroif (fp == NULL)
63790792Sgshapiro	return(-1);
63890792Sgshapiro</pre>
63990792SgshapiroThe above code open's a file of type "my_type". The <i>info</i> is set
64090792Sgshapiroto a string "data". "data" may be the name of a file or have some special
64190792Sgshapiromeaning to the file type. For sake of the example, we will have it be
64290792Sgshapirothe name of a file in the home directory of the user running the program.
64390792SgshapiroNow the only file type function that is dependent on this information
64490792Sgshapirowill be the open function.
64590792Sgshapiro<br>
64690792SgshapiroWe have also specified read-only access (SM_IO_RDONLY) and that no <i>rpool</i>
64790792Sgshapirowill be used. The <i>timeout</i> has been set to 1000 milliseconds which
64890792Sgshapirodirects that the file and all associated setup should be done within
64990792Sgshapiro1000 milliseconds or return that the function erred (with errno==EAGAIN).
65090792Sgshapiro<pre>
65190792Sgshapiroint myopen(fp, info, flags, rpools)
65290792Sgshapiro	SM_FILE_T *fp;
65390792Sgshapiro        const void *info; 
65490792Sgshapiro        int flags;
65590792Sgshapiro        void *rpool;
65690792Sgshapiro{
65790792Sgshapiro	/*
65890792Sgshapiro	**  now we could do the open raw (i.e with read(2)), but we will
65990792Sgshapiro	**  use file layering instead. We will use the <i>stdio</i> file
66090792Sgshapiro	**  type (different than the system's stdio).
66190792Sgshapiro	*/
66290792Sgshapiro	struct passwd *pw;
66390792Sgshapiro	char path[PATH_MAX];
66490792Sgshapiro
66590792Sgshapiro	pw = getpwuid(getuid());
66690792Sgshapiro	sm_io_snprintf(path, PATH_MAX, "%s/%s", pw->pw_dir, info);
66790792Sgshapiro
66890792Sgshapiro	/*
66990792Sgshapiro	**  Okay. Now the path pass-in has been prefixed with the
67090792Sgshapiro	**  user's HOME directory. We'll call the regular stdio (SmFtStdio)
67190792Sgshapiro	**  now to handle the rest of the open.
67290792Sgshapiro	*/
67390792Sgshapiro	fp->cookie = sm_io_open(SmFtStdio, path, flags, rpools);
67490792Sgshapiro	if (fp->cookie == NULL)
67590792Sgshapiro		return(-1) /* errno set by sm_io_open call */
67690792Sgshapiro	else
67790792Sgshapiro		return(0);
67890792Sgshapiro}
67990792Sgshapiro</pre>
68090792SgshapiroLater on when a write is performed the function <tt>mywrite</tt> will
68190792Sgshapirobe invoked. To match the above <tt>myopen</tt>, <tt>mywrite</tt> could
68290792Sgshapirobe written as:
68390792Sgshapiro<pre>
68490792Sgshapiroint mywrite(fp, buf, size)
68590792Sgshapiro	SM_FILE_T *fp;
68690792Sgshapiro        char *buf;
68790792Sgshapiro        size_t size;
68890792Sgshapiro{
68990792Sgshapiro	/*
69090792Sgshapiro	**  As an example, we can change, modify, refuse, filter, etc.
69190792Sgshapiro	**  the content being passed through before we ask the SmFtStdio
69290792Sgshapiro	**  to do the actual write.
69390792Sgshapiro	**  This example is very simple and contrived, but this keeps it
69490792Sgshapiro	**  clear.
69590792Sgshapiro	*/
69690792Sgshapiro	if (size == 0)
69790792Sgshapiro		return(0); /* why waste the cycles? */
69890792Sgshapiro	if (*buf == 'X')
69990792Sgshapiro		*buf = 'Y';
70090792Sgshapiro
70190792Sgshapiro	/*
70290792Sgshapiro	**  Note that the file pointer passed to the next level is the
70390792Sgshapiro	**  one that was stored in the cookie during the open.
70490792Sgshapiro	*/
70590792Sgshapiro	return(sm_io_write(fp->cookie, buf, size));
70690792Sgshapiro}
70790792Sgshapiro</pre>
70890792SgshapiroAs a thought-exercise for the fair reader: how would you modify the
70990792Sgshapiroabove two functions to make a "tee". That is the program will call
71090792Sgshapiro<tt>sm_io_open</tt> or <tt>sm_io_write</tt> and two or more files will
71190792Sgshapirobe opened and written to. (Hint: create a cookie to hold two or more
71290792Sgshapirofile pointers).
71390792Sgshapiro</menu>
71490792Sgshapiro</p>
71590792Sgshapiro<p></p>
71690792Sgshapiro<hr>
71790792Sgshapiro<br>
71890792Sgshapiro<hr>
71990792Sgshapiro<p></p>
72090792Sgshapiro<center>
72190792Sgshapiro<h1>
72290792Sgshapiro<a name="defaultapi">
72390792Sgshapirolibsm sm_io default API definition
72490792Sgshapiro</a>
72590792Sgshapiro</h1>
72690792Sgshapiro</center>
72790792Sgshapiro<h2> Introduction </h2>
72890792Sgshapiro<p>
72990792SgshapiroA number of <i>sm_io</i> API's perform similar to their <i>stdio</i>
73090792Sgshapirocounterparts (same name as when the "sm_io_" is removed).
73190792SgshapiroOne difference between <i>sm_io</i> and <i>stdio</i> functions is that
73290792Sgshapiroif a "file pointer" (FILE/SM_FILE_T)
73390792Sgshapirois one of the arguments for the function, then it is now the first
73490792Sgshapiroargument. <i>Sm_io</i> is standardized so that when a file pointer is
73590792Sgshapiroone of the arguments to function then it will always be the first
73690792Sgshapiroarguement. Many of the <i>sm_io</i> function take a <i>timeout</i>
73790792Sgshapiroargument (see <a href="#timeouts"><b>Timeouts</b></a>).
73890792Sgshapiro</p>
73990792Sgshapiro<p>
74090792SgshapiroThe API you have selected is one of these. Please consult the
74190792Sgshapiroappropriate <i>stdio</i> man page for now.
74290792Sgshapiro</p>
74390792Sgshapiro
74490792Sgshapiro</body>
74590792Sgshapiro</html>
746