1<html> 2<head> 3<title>libsm sm_io general overview</title> 4</head> 5<body> 6<a href="index.html">Back to libsm overview</a> 7<center> 8<h1>libsm sm_io general overview</h1> 9<br> $Id: io.html,v 1.3 2001-03-17 03:22:50 gshapiro Exp $ 10</center> 11<h2> Introduction </h2> 12<p> 13The <i>sm_io</i> portion of the <i>libsm</i> library is similar to 14the <i>stdio</i> library. It is derived from the Chris Torek version 15of the <i>stdio</i> library (BSD). There are some key differences 16described below between <i>sm_io</i> and <i>stdio</i> but many 17similarities will be noticed. 18</p> 19<p> 20A key difference between <i>stdio</i> and <i>sm_io</i> is that the 21functional code that does the open, close, read, write, etc. on a file 22can be different for different files. For example, with <i>stdio</i> 23the functional code (read, write) is either the default supplied in the 24library or a "programmer specified" set of functions set via 25<i>sm_io_open()</i>. Whichever set of functions are specified <b>all</b> 26open's, read's, write's, etc use the same set of functions. In contrast, with 27<i>sm_io</i> a different set of functions can be specified with each 28active file for read's, write's, etc. These different function sets 29are identified as <b>file types</b> (see <tt>sm_io_open()</tt>). Each function 30set can handle the actions directly, pass the action request to 31another function set or do some work before passing it on to another function 32set. The setting of a function set for a file type can be done for 33a file type at any time (even after the type is open). 34</p> 35<p> 36A second difference is the use of <a href="rpool.html"><b>rpools</b></a>. 37An <b>rpool</b> is specified with the opening of a file 38(<tt>sm_io_open()</tt>). 39This allows of a file to be associated with an rpool so that when the 40rpool is released the open file will be closed; the <tt>sm_io_open()</tt> 41registers that <tt>sm_io_close()</tt> should be called when the rpool is 42released. 43</p> 44<p> 45A third difference is that the I/O functions take a <i>timeout</i> 46argument. This allows the setting of a maximum amount of time allowable 47for the I/O to be completed. This means the calling program does not need 48to setup it's own timeout mechanism. NOTE: SIGALRM's should not be 49active in the calling program when an I/O function with a <i>timeout</i> 50is used. 51</p> 52<p> 53When converting source code from <i>stdio</i> to <i>sm_io</i> be 54very careful to NOTE: the arguments to functions have been rationalized. 55That is, unlike <i>stdio</i>, all <i>sm_io</i> functions that 56take a file pointer (SM_FILE_T *) argument have the file pointer 57as the first argument. Also not all functions with <i>stdio</i> have 58an identical matching <i>sm_io</i> API: the API list has been thinned 59since a number of <i>stdio</i> API's overlapped in functionality. 60Remember many functions also have a <i>timeout</i> argument added. 61</p> 62<p> 63When a file is going to be opened, the file type is included with 64<tt>sm_io_open()</tt>. 65A file type is either one automatically included with the <i>sm_io</i> 66library or one created by the program at runtime. 67File types can be either buffered or unbuffered. When buffered the buffering 68is either the builtin <i>sm_io</i> buffering or as done by the file type. 69File types can be disk files, strings, TCP/IP connections or whatever 70your imagination can come up with that can be read and/or written to. 71</p> 72<p> 73Information about a particular file type or pointer can be obtained or set with 74the <i>sm_io</i> "info" functions. 75The <tt>sm_io_setinfo()</tt> and <tt>sm_io_getinfo()</tt> functions work on 76an active file pointer. 77</p> 78<h2>Include files</h2> 79<p> 80There is one main include file for use with sm_io: <i>io.h</i>. Since the 81use of <b>rpools</b> is specified with <tt>sm_io_open()</tt> an 82<b>rpool</b> may 83be created and thus <i>rpool.h</i> may need to be included as well 84(before io.h). 85</p> 86<pre> 87#include <rpool.h> 88#include <io.h> 89</pre> 90 91<h2>Functions/API's</h2> 92<p> 93Below is a list of the functions for <i>sm_io</i> listed in 94alphabetical order. Currently these functions return error codes 95and set errno when appropriate. These (may?/will?) change to 96raising exceptions later. 97</p> 98<pre> 99<a href="#sm_io_autoflush">SM_FILE_T *sm_io_autoflush(SM_FILE_T *fp, SM_FILE_T *)</a> 100 101<a href="#sm_io_automode">void sm_io_automode(SM_FILE_T *fp, SM_FILE_T *)</a> 102 103<a href="#defaultapi">void sm_io_clearerr(SM_FILE_T *fp)</a> 104 105<a href="#sm_io_close">int sm_io_close(SM_FILE_T *fp, int timeout)</a> 106 107<a href="#defaultapi">int sm_io_dup(SM_FILE_T *fp)</a> 108 109<a href="#defaultapi">int sm_io_eof(SM_FILE_T *fp)</a> 110 111<a href="#defaultapi">int sm_io_error(SM_FILE_T *fp)</a> 112 113<a href="#defaultapi">char * sm_io_fgets(SM_FILE_T *fp, int timeout, char *buf, int n)</a> 114 115<a href="#defaultapi">int sm_io_flush(SM_FILE_T *fp, int timeout)</a> 116 117<a href="#sm_io_fopen">int sm_io_fopen(char *pathname, int flags [, MODE_T mode])</a> 118 119<a href="#defaultapi">int sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...)</a> 120 121<a href="#defaultapi">int sm_io_fputs(s, int, SM_FILE_T *fp)</a> 122 123<a href="#defaultapi">int sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) </a> 124 125<a href="#defaultapi">int sm_io_getc(SM_FILE_T *fp, int timeout)</a> 126 127<a href="#sm_io_getinfo">void sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)</a> 128 129<a href="#sm_io_open">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a> 130 131<a href="#defaultapi">int sm_io_purge(SM_FILE_T *fp)</a> 132 133<a href="#defaultapi">int sm_io_putc(SM_FILE_T *fp, int timeout, int c)</a> 134 135<a href="#defaultapi">size_t sm_io_read(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a> 136 137<a href="#sm_io_reopen">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a> 138 139<a href="#defaultapi">void sm_io_rewind(SM_FILE_T *fp, int timeout)</a> 140 141<a href="#defaultapi">int sm_io_seek(SM_FILE_T *fp, off_t offset, int timeout, int whence)</a> 142 143<a href="#sm_io_setinfo">void sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)</a> 144 145<a href="#defaultapi">int sm_io_setvbuf(SM_FILE_T *fp, int timeout, char *buf, int mode, size_t size)</a> 146 147<a href="#defaultapi">int sm_io_sscanf(const char *str, char const *fmt, ...)</a> 148 149<a href="#defaultapi">long sm_io_tell(SM_FILE_T *fp, int timeout)</a> 150 151<a href="#defaultapi">int sm_io_ungetc(SM_FILE_T *fp, int timeout, int c)</a> 152 153<a href="#defaultapi">size_t sm_io_write(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a> 154 155<a href="#defaultapi">int sm_snprintf(char *str, size_t n, char const *fmt, ...)</a> 156 157</pre> 158<a name="timeouts"> 159<h2>Timeouts</h2> 160<p> 161For many of the functions a <i>timeout</i> argument is given. This limits 162the amount of time allowed for the function to complete. There are three 163pre-defined values: 164<menu> 165<li> 166SM_TIME_DEFAULT - timeout using the default setting for this file type 167</li> 168<li> 169SM_TIME_FOREVER - timeout will take forever; blocks until task completed 170</li> 171<li> 172SM_TIME_IMMEDIATE - timeout (virtually) now 173</li> 174</menu> 175</p> 176<p> 177A function caller can also specify a positive integer value in milliseconds. 178A function will return with <i>errno</i> set to EINVAL if a bad value 179is given for <i>timeout</i>. 180When a function times out the function returns in error with <i>errno</i> 181set to <b>EAGAIN</b>. In the future this may change to an exception being 182thrown. 183</p> 184<h2>Function Descriptions</h2> 185<dl> 186<!-- SM_IO_FOPEN --> 187<p></p> 188<dt><tt><a name="sm_io_fopen"> 189SM_FILE_T * 190<br> 191sm_io_fopen(char *pathname, int flags) 192<br> 193SM_FILE_T * 194<br> 195sm_io_fopen(char *pathname, int flags, MODE_T mode) 196</a></tt></dt> 197<dd> 198Open the file named by <tt>pathname</tt>, and associate a stream with it. 199The arguments are the same as for the <tt>open(2)</tt> system call. 200<br> 201If memory could not be allocated, an exception is raised. 202If successful, an <tt>SM_FILE_T</tt> pointer is returned. 203Otherwise, <tt>NULL</tt> is returned and <tt>errno</tt> is set. 204<!-- SM_IO_OPEN --> 205<p></p> 206<dt><tt><a name="sm_io_open"> 207SM_FILE_T * 208<br> 209sm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool) 210</a></tt></dt> 211<dd> 212Opens a file by <i>type</i> directed by <i>info</i>. <i>Type</i> is a filled-in 213SM_FILE_T structure from the following builtin list 214(<a href="#builtins"><b>descriptions below</b></a>) 215or one specified by the program. 216<menu> 217<li> 218SmFtString 219</li> 220<li> 221SmFtStdio 222</li> 223<li> 224SmFtStdiofd 225</li> 226<li> 227smioin <b>*</b> 228</li> 229<li> 230smioout <b>*</b> 231</li> 232<li> 233smioerr <b>*</b> 234</li> 235<li> 236smiostdin <b>*</b> 237</li> 238<li> 239smiostdout <b>*</b> 240</li> 241<li> 242smiostderr <b>*</b> 243</li> 244<li> 245SmFtSyslog 246</li> 247</menu> 248<br> 249The above list of file types are already appropriately filled in. Those marked 250with a "<b>*</b>" are already open and may be used directly and immediately. 251For program specified types, to set the <i>type</i> argument easily and with minimal error the macro 252<b>SM_IO_SET_TYPE</b> should be used. The SM_FILE_T structure is fairly 253large, but only a small portion of it need to be initialized for a new 254type. 255See also <a href="#writefunctions">"Writing Functions for a File Type"</a>. 256<menu> 257<pre> 258SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout) 259</pre> 260</menu> 261<br> 262<i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a> 263section. 264<br> 265<i>Info</i> is information that describes for the file type what is 266to be opened and any associated information. 267For a disk file this would be a file path; with a TCP 268connection this could be an a structure containing an IP address and port. 269<br><i>Flags</i> is a 270set of sm_io flags that describes how the file is to be interacted with: 271<menu> 272<li> 273SM_IO_RDWR - read and write 274</li> 275<li> 276SM_IO_RDONLY - read only 277</li> 278<li> 279SM_IO_WRONLY - write only 280</li> 281<li> 282SM_IO_APPEND - allow write to EOF only 283</li> 284<li> 285SM_IO_APPENDRW - allow read-write from EOF only 286</li> 287<li> 288SM_IO_RDWRTR - read and write with truncation of file first 289</li> 290</menu> 291<i>Rpool</i> is the address of the rpool that this open is to be associated 292with. When the rpool is released then the close function for this 293file type will be automatically called to close the file for cleanup. 294If NULL is specified for <i>rpool</i> then the close function is not 295associated (attached) to an rpool. 296<br> 297On cannot allocate memory, an exception is raised. 298If the <i>type</i> is invalid, <tt>sm_io_open</tt> will abort the process. 299On success an SM_FILE_T * pointer is returned. 300On failure the NULL pointer is returned and errno is set. 301</dd> 302<!-- SM_IO_SETINFO --> 303<p></p> 304<dt><tt><a name="sm_io_setinfo"> 305int 306<br> 307sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp) 308</a></tt></dt> 309<dd> 310For the open file <i>sfp</i> set the indicated information (<i>what</i>) 311to the new value <i>(valp</i>). 312This will make the change for this SM_FILE_T only. The file 313type that <i>sfp</i> originally belonged to will still be 314configured the same way (this is to prevent side-effect 315to other open's of the same file type, particularly with threads). 316The value of <i>what</i> will be file-type dependant since this function 317is one of the per file type setable functions. 318One value for <i>what</i> that is valid for all file types is 319SM_WHAT_VECTORS. This sets the currently open file with a new function 320vector set for open, close, etc. The new values are taken from <i>valp</i> 321a SM_FILE_T filled in by the used via the macro SM_IO_SET_TYPE 322(see and <a href="#writefunctions"> 323"Writing Functions for a File Type"</a> for more information). 324<br> 325On success 0 (zero) is returned. On failure -1 is returned and errno is set. 326</dd> 327<!-- SM_IO_GETINFO --> 328<p></p> 329<dt><tt><a name="sm_io_getinfo"> 330int 331<br> 332sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp) 333</a></tt></dt> 334<dd> 335For the open file <i>sfp</i> get the indicated information (<i>what</i>) 336and place the result in <i>(valp</i>). 337This will obtain information for SM_FILE_T only and may be different than 338the information for the file type it was originally opened as. 339The value of <i>what</i> will be file type dependant since this function 340is one of the per file type setable functions. 341One value for <i>what</i> that is valid for all file types is 342SM_WHAT_VECTORS. This gets from the currently open file a copy of 343the function vectors and stores them in <i>valp</i> a SM_FILE_T 344(see <a href="#writefunctions"> 345"Writing Functions for a File Type"</a> for more information). 346<br> 347On success 0 (zero) is returned. On failure -1 is returned and errno is set. 348</dd> 349<!-- SM_IO_AUTOFLUSH --> 350<p></p> 351<dt><tt><a name="sm_io_autoflush"> 352void 353<br> 354sm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2) 355</a></tt></dt> 356<dd> 357Associate a read of <i>fp1</i> with a data flush for <i>fp2</i>. If a read 358of <i>fp1</i> discovers that there is no data available to be read, then 359<i>fp2</i> will have it's data buffer flushed for writable data. It is 360assumed that <i>fp1</i> is open for reading and <i>fp2</i> is open 361for writing. 362<br> 363On return the old file pointer associated with <i>fp1</i> for flushing 364is returned. A return of NULL is no an error; this merely indicates no 365previous association. 366</dd> 367<!-- SM_IO_AUTOMODE --> 368<p></p> 369<dt><tt><a name="sm_io_automode"> 370void 371<br> 372sm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2) 373<dt><tt><a name="sm_io_automode"> 374</a></tt></dt> 375<dd> 376Associate the two file pointers for blocking/non-blocking mode changes. 377In the handling of timeouts <i>sm_io</i> may need to switch the mode of 378a file between blocking and non-blocking. If the underlying file descriptor 379has been duplicated with <tt>dup(2)</tt> and these descriptors are used 380by <i>sm_io</i> (for example with an SmFtStdiofd file type), then this API 381should be called to associate them. Otherwise odd behavior (i.e. errors) 382may result that is not consistently reproducable nor easily identifiable. 383</dd> 384<!-- SM_IO_CLOSE --> 385<p></p> 386<dt><tt><a name="sm_io_close"> 387int 388<br> 389sm_io_close(SM_FILE_T *sfp, int timeout) 390</a></tt></dt> 391<dd> 392Release all resources (file handles, memory, etc.) associated with 393the open SM_FILE_T <i>sfp</i>. If buffering is active then the 394buffer is flushed before any resources are released. 395<i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a> 396section. 397The first resources released after buffer flushing will be the 398buffer itself. Then the <b>close</b> function specified in the 399file type at open will be called. It is the responsibility 400of the <b>close</b> function to release any file type 401specific resources allocated and to call <tt>sm_io_close()</tt> 402for the next file type layer(s) that the current file type uses (if any). 403<br> 404On success 0 (zero) is returned. On failure SM_IO_EOF is returned and 405errno is set. 406</dd> 407</dl> 408<h2> 409<a name="builtins">Description of Builtin File Types</a> 410</h2> 411<p> 412There are several builtin file types as mentioned in <tt>sm_io_open()</tt>. 413More file types may be added later. 414</p> 415<dl> 416<p></p> 417<dt><tt>SmFtString</tt></dt> 418<dd> 419Operates on a character string. <i>SmFtString</i> is a file type only. 420The string starts at the location 0 (zero) 421and ends at the last character. A read will obtain the requested 422number of characters if available; else as many as possible. A read 423will not terminate the read characters with a NULL ('\0'). A write 424will place the number of requested characters at the current location. 425To append to a string either the pointer must currently be at the end 426of the string or a seek done to position the pointer. The file type 427handles the space needed for the string. Thus space needed for the 428string will be grown automagically without the user worrying about 429space management. 430</dd> 431<dt><tt>SmFtStdio</tt></dt> 432<dd> 433A predefined SM_FILE_T structure with function vectors pointing to 434functions that result in the file-type behaving as the system stdio 435normally does. The <i>info</i> portion of the <tt>sm_io_open</tt> 436is the path of the file to be opened. Note that this file type 437does not interact with the system's stdio. Thus a program mixing system 438stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input 439and output. 440</dd> 441<dt><tt>SmFtStdiofd</tt></dt> 442<dd> 443A predefined SM_FILE_T structure with function vectors pointing to 444functions that result in the file-type behaving as the system stdio 445normally does. The <i>info</i> portion of the <tt>sm_io_open</tt> 446is a file descriptor (the value returned by open(2)). Note that this file type 447does not interact with the system's stdio. Thus a program mixing system 448stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input 449and output. 450</dd> 451<dt><tt>smioin</tt></dt> 452<dt><tt>smioout</tt></dt> 453<dt><tt>smioerr</tt></dt> 454<dd> 455The three types <i>smioin</i>, <i>smioout</i> and <i>smioerr</i> are grouped 456together. These three types 457perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i> 458and <i>stderr</i>. These types are both the names and the file pointers. 459They are already open when a program starts (unless the parent explictly 460closed file descriptors 0, 1 and 2). 461Thus <tt>sm_io_open()</tt> should never be called for these types: 462the named file pointers should be used directly. 463<i>Smioin</i> and <i>smioout</i> are buffered 464by default. <i>Smioerr</i> is not buffered by default. Calls to <b>stdio</b> 465are safe to make when using these three<b>sm_io</b> file pointers. 466There is no interaction between <b>sm_io</b> and <b>stdio</b>. Hence, 467due to buffering, the sequence of input and output data from both <b>sm_io</b> 468and <b>stdio</b> at the same time may appear unordered. For 469coordination between <b>sm_io</b> and <b>stdio</b> use the three 470file pointers below (<i>smiostdin, smiostdout, smiostderr</i>). 471</dd> 472<dt><tt>smiostdin</tt></dt> 473<dt><tt>smiostdout</tt></dt> 474<dt><tt>smiostderr</tt></dt> 475<dd> 476The three types <i>smiostdin</i>, <i>smioostdut</i> and <i>smiostderr</i> 477are grouped together. These three types 478perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i> 479and <i>stderr</i>. These types are both the names and file pointers. 480They are already open when a program starts (unless the parent explictly 481close file descriptors 0, 1 and 2). 482Thus <tt>sm_io_open()</tt> should 483never be called: the named file pointers should be used directly. 484Calls to <b>stdio</b> are safe to make when using these three<b>sm_io</b> 485file pointers though no code is shared between the two libaries. 486However, the input and output between <i>sm_io</i> and <i>stdio</i> is 487coordinated for these three file pointers: <i>smiostdin</i>, 488<i>smiostdout</i> and <i>smiostderr</i> are layered on-top-of 489the system's <i>stdio</i>. 490<i>Smiostdin</i>, <i>smiostdout</i> 491and <i>Smiostderr</i> are not buffered by default. 492Hence, due to buffering in <i>stdio</i> only, the sequence of input and 493output data from both <b>sm_io</b> and <b>stdio</b> at the same time will 494appear ordered. If <i>sm_io</i> buffering is turned on then the 495input and output can appear unordered or lost. 496</dd> 497<dt><tt>SmFtSyslog</tt></dt> 498<dd> 499This opens the channel to the system log. Reads are not allowed. Writes 500cannot be undone once they have left the <i>sm_io</i> buffer. 501The man pages for <tt>syslog(3)</tt> should be read for information 502on syslog. 503</dd> 504</dl> 505<p></p> 506<hr> 507<p></p> 508<h2> 509<a name="writefunctions"> 510Writing Functions for a File Type 511</a> 512</h2> 513<p> 514When writing functions to create a file type a function needs to 515be created for each function vector in the SM_FILE_T structure 516that will be passed to <tt>sm_io_open()</tt> or <tt>sm_io_setinfo()</tt>. 517Otherwise the setting will be rejected and <i>errno</i> set to EINVAL. 518Each function should accept and handle the number and types of arguments as 519described in the portion of the SM_FILE_T structure shown below: 520</p> 521<pre> 522 int (*open) __P((SM_FILE_T *fp, const void *, int flags, 523 const void *rpool)); 524 int (*close) __P((SM_FILE_T *fp)); 525 int (*read) __P((SM_FILE_T *fp, char *buf, size_t size)); 526 int (*write) __P((SM_FILE_T *fp, const char *buf, size_t size)); 527 off_t (*seek) __P((SM_FILE_T *fp, off_t offset, int whence)); 528 int (*getinfo) __P((SM_FILE_T *fp, int what, void *valp)); 529 int (*setinfo) __P((SM_FILE_T *fp, int what, void *valp)); 530</pre> 531<p> 532The macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file 533type for an <tt>sm_io_open()</tt>: 534<menu> 535<pre> 536SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout) 537</pre> 538<br> 539where: 540<menu> 541<li> 542type - is the SM_FILE_T being filled-in 543</li> 544<li> 545name - a human readable character string for human identification purposes 546</li> 547<li> 548open - the vector to the open function 549</li> 550<li> 551close - the vector to the close function 552</li> 553<li> 554read - the vector to the read function 555</li> 556<li> 557write - the vector to the write function 558</li> 559<li> 560seek - the vector to the seek function 561</li> 562<li> 563set - the vector to the set function 564</li> 565<li> 566get - the vector to the get function 567</li> 568<li> 569timeout - the default to be used for a timeout when SM_TIME_DEFAULT specified 570</li> 571</menu> 572</menu> 573You should avoid trying to change or use the other structure members of the 574SM_FILE_T. The file pointer content (internal structure members) of an active 575file should only be set and observed with the "info" functions. 576The two exceptions to the above statement are the structure members 577<i>cookie</i> and <i>ival</i>. <i>Cookie</i> is of type <tt>void *</tt> 578while <i>ival</i> is of type <tt>int</tt>. These two structure members exist 579specificly for your created file type to use. The <i>sm_io</i> functions 580will not change or set these two structure members; only specific file type 581will change or set these variables. 582</p> 583<p> 584For maintaining information privately about status for a file type the 585information should be encapsulated in a <i>cookie</i>. A <i>cookie</i> 586is an opaque type that contains information that is only known to 587the file type layer itself. The <i>sm_io</i> package will know 588nothing about the contents of the <i>cookie</i>; <i>sm_io</i> only 589maintains the location of the <i>cookie</i> so that it may be passed 590to the functions of a file type. It is up to the file type to 591determine what to do with the <i>cookie</i>. It is the responsibility 592of the file type's open to create the cookie and point the SM_FILE_T's 593<i>cookie</i> at the address of the cookie. 594It is the responsibility of close to clean up 595any resources that the cookie and instance of the file type have used. 596</p> 597<p> 598For the <i>cookie</i> to be passed to all members of a function type 599cleanly the location of the cookie must assigned during 600the call to open. The file type functions should not attempt to 601maintain the <i>cookie</i> internally since the file type may have 602serveral instances (file pointers). 603</p> 604<p> 605The SM_FILE_T's member <i>ival</i> may be used in a manner similar to 606<i>cookie</i>. It is not to be used for maintaining the file's offset 607or access status (other members do that). It is intended as a "light" 608reference. 609</p> 610<p> 611The file type vector functions are called by the <tt>sm_io_*()</tt> 612functions after <i>sm_io</i> processing has occurred. The <i>sm_io</i> 613processing validates SM_FILE_T's and may then handle the call entirely 614itself or pass the request to the file type vector functions. 615</p> 616<p> 617All of the "int" functions should return -1 (minus one) on failure 618and 0 (zero) or greater on success. <i>Errno</i> should be set to 619provide diagnostic information to the caller if it has not already 620been set by another function the file type function used. 621</p> 622<p> 623Examples are a wonderful manner of clarifying details. Below is an example 624of an open function. 625</p> 626<p> 627This shows the setup. 628<menu> 629<pre> 630SM_FILE_T *fp; 631SM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite, 632 myseek, myget, myset, SM_TIME_FOREVER); 633 634fp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL); 635 636if (fp == NULL) 637 return(-1); 638</pre> 639The above code open's a file of type "my_type". The <i>info</i> is set 640to a string "data". "data" may be the name of a file or have some special 641meaning to the file type. For sake of the example, we will have it be 642the name of a file in the home directory of the user running the program. 643Now the only file type function that is dependent on this information 644will be the open function. 645<br> 646We have also specified read-only access (SM_IO_RDONLY) and that no <i>rpool</i> 647will be used. The <i>timeout</i> has been set to 1000 milliseconds which 648directs that the file and all associated setup should be done within 6491000 milliseconds or return that the function erred (with errno==EAGAIN). 650<pre> 651int myopen(fp, info, flags, rpools) 652 SM_FILE_T *fp; 653 const void *info; 654 int flags; 655 void *rpool; 656{ 657 /* 658 ** now we could do the open raw (i.e with read(2)), but we will 659 ** use file layering instead. We will use the <i>stdio</i> file 660 ** type (different than the system's stdio). 661 */ 662 struct passwd *pw; 663 char path[PATH_MAX]; 664 665 pw = getpwuid(getuid()); 666 sm_io_snprintf(path, PATH_MAX, "%s/%s", pw->pw_dir, info); 667 668 /* 669 ** Okay. Now the path pass-in has been prefixed with the 670 ** user's HOME directory. We'll call the regular stdio (SmFtStdio) 671 ** now to handle the rest of the open. 672 */ 673 fp->cookie = sm_io_open(SmFtStdio, path, flags, rpools); 674 if (fp->cookie == NULL) 675 return(-1) /* errno set by sm_io_open call */ 676 else 677 return(0); 678} 679</pre> 680Later on when a write is performed the function <tt>mywrite</tt> will 681be invoked. To match the above <tt>myopen</tt>, <tt>mywrite</tt> could 682be written as: 683<pre> 684int mywrite(fp, buf, size) 685 SM_FILE_T *fp; 686 char *buf; 687 size_t size; 688{ 689 /* 690 ** As an example, we can change, modify, refuse, filter, etc. 691 ** the content being passed through before we ask the SmFtStdio 692 ** to do the actual write. 693 ** This example is very simple and contrived, but this keeps it 694 ** clear. 695 */ 696 if (size == 0) 697 return(0); /* why waste the cycles? */ 698 if (*buf == 'X') 699 *buf = 'Y'; 700 701 /* 702 ** Note that the file pointer passed to the next level is the 703 ** one that was stored in the cookie during the open. 704 */ 705 return(sm_io_write(fp->cookie, buf, size)); 706} 707</pre> 708As a thought-exercise for the fair reader: how would you modify the 709above two functions to make a "tee". That is the program will call 710<tt>sm_io_open</tt> or <tt>sm_io_write</tt> and two or more files will 711be opened and written to. (Hint: create a cookie to hold two or more 712file pointers). 713</menu> 714</p> 715<p></p> 716<hr> 717<br> 718<hr> 719<p></p> 720<center> 721<h1> 722<a name="defaultapi"> 723libsm sm_io default API definition 724</a> 725</h1> 726</center> 727<h2> Introduction </h2> 728<p> 729A number of <i>sm_io</i> API's perform similar to their <i>stdio</i> 730counterparts (same name as when the "sm_io_" is removed). 731One difference between <i>sm_io</i> and <i>stdio</i> functions is that 732if a "file pointer" (FILE/SM_FILE_T) 733is one of the arguments for the function, then it is now the first 734argument. <i>Sm_io</i> is standardized so that when a file pointer is 735one of the arguments to function then it will always be the first 736arguement. Many of the <i>sm_io</i> function take a <i>timeout</i> 737argument (see <a href="#timeouts"><b>Timeouts</b></a>). 738</p> 739<p> 740The API you have selected is one of these. Please consult the 741appropriate <i>stdio</i> man page for now. 742</p> 743 744</body> 745</html> 746