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.1.1.1 2003-04-08 15:12:05 zacheiss Exp $ |
---|
10 | </center> |
---|
11 | <h2> Introduction </h2> |
---|
12 | <p> |
---|
13 | The <i>sm_io</i> portion of the <i>libsm</i> library is similar to |
---|
14 | the <i>stdio</i> library. It is derived from the Chris Torek version |
---|
15 | of the <i>stdio</i> library (BSD). There are some key differences |
---|
16 | described below between <i>sm_io</i> and <i>stdio</i> but many |
---|
17 | similarities will be noticed. |
---|
18 | </p> |
---|
19 | <p> |
---|
20 | A key difference between <i>stdio</i> and <i>sm_io</i> is that the |
---|
21 | functional code that does the open, close, read, write, etc. on a file |
---|
22 | can be different for different files. For example, with <i>stdio</i> |
---|
23 | the functional code (read, write) is either the default supplied in the |
---|
24 | library or a "programmer specified" set of functions set via |
---|
25 | <i>sm_io_open()</i>. Whichever set of functions are specified <b>all</b> |
---|
26 | open'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 |
---|
28 | active file for read's, write's, etc. These different function sets |
---|
29 | are identified as <b>file types</b> (see <tt>sm_io_open()</tt>). Each function |
---|
30 | set can handle the actions directly, pass the action request to |
---|
31 | another function set or do some work before passing it on to another function |
---|
32 | set. The setting of a function set for a file type can be done for |
---|
33 | a file type at any time (even after the type is open). |
---|
34 | </p> |
---|
35 | <p> |
---|
36 | A second difference is the use of <a href="rpool.html"><b>rpools</b></a>. |
---|
37 | An <b>rpool</b> is specified with the opening of a file |
---|
38 | (<tt>sm_io_open()</tt>). |
---|
39 | This allows of a file to be associated with an rpool so that when the |
---|
40 | rpool is released the open file will be closed; the <tt>sm_io_open()</tt> |
---|
41 | registers that <tt>sm_io_close()</tt> should be called when the rpool is |
---|
42 | released. |
---|
43 | </p> |
---|
44 | <p> |
---|
45 | A third difference is that the I/O functions take a <i>timeout</i> |
---|
46 | argument. This allows the setting of a maximum amount of time allowable |
---|
47 | for the I/O to be completed. This means the calling program does not need |
---|
48 | to setup it's own timeout mechanism. NOTE: SIGALRM's should not be |
---|
49 | active in the calling program when an I/O function with a <i>timeout</i> |
---|
50 | is used. |
---|
51 | </p> |
---|
52 | <p> |
---|
53 | When converting source code from <i>stdio</i> to <i>sm_io</i> be |
---|
54 | very careful to NOTE: the arguments to functions have been rationalized. |
---|
55 | That is, unlike <i>stdio</i>, all <i>sm_io</i> functions that |
---|
56 | take a file pointer (SM_FILE_T *) argument have the file pointer |
---|
57 | as the first argument. Also not all functions with <i>stdio</i> have |
---|
58 | an identical matching <i>sm_io</i> API: the API list has been thinned |
---|
59 | since a number of <i>stdio</i> API's overlapped in functionality. |
---|
60 | Remember many functions also have a <i>timeout</i> argument added. |
---|
61 | </p> |
---|
62 | <p> |
---|
63 | When a file is going to be opened, the file type is included with |
---|
64 | <tt>sm_io_open()</tt>. |
---|
65 | A file type is either one automatically included with the <i>sm_io</i> |
---|
66 | library or one created by the program at runtime. |
---|
67 | File types can be either buffered or unbuffered. When buffered the buffering |
---|
68 | is either the builtin <i>sm_io</i> buffering or as done by the file type. |
---|
69 | File types can be disk files, strings, TCP/IP connections or whatever |
---|
70 | your imagination can come up with that can be read and/or written to. |
---|
71 | </p> |
---|
72 | <p> |
---|
73 | Information about a particular file type or pointer can be obtained or set with |
---|
74 | the <i>sm_io</i> "info" functions. |
---|
75 | The <tt>sm_io_setinfo()</tt> and <tt>sm_io_getinfo()</tt> functions work on |
---|
76 | an active file pointer. |
---|
77 | </p> |
---|
78 | <h2>Include files</h2> |
---|
79 | <p> |
---|
80 | There is one main include file for use with sm_io: <i>io.h</i>. Since the |
---|
81 | use of <b>rpools</b> is specified with <tt>sm_io_open()</tt> an |
---|
82 | <b>rpool</b> may |
---|
83 | be 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> |
---|
93 | Below is a list of the functions for <i>sm_io</i> listed in |
---|
94 | alphabetical order. Currently these functions return error codes |
---|
95 | and set errno when appropriate. These (may?/will?) change to |
---|
96 | raising 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> |
---|
161 | For many of the functions a <i>timeout</i> argument is given. This limits |
---|
162 | the amount of time allowed for the function to complete. There are three |
---|
163 | pre-defined values: |
---|
164 | <menu> |
---|
165 | <li> |
---|
166 | SM_TIME_DEFAULT - timeout using the default setting for this file type |
---|
167 | </li> |
---|
168 | <li> |
---|
169 | SM_TIME_FOREVER - timeout will take forever; blocks until task completed |
---|
170 | </li> |
---|
171 | <li> |
---|
172 | SM_TIME_IMMEDIATE - timeout (virtually) now |
---|
173 | </li> |
---|
174 | </menu> |
---|
175 | </p> |
---|
176 | <p> |
---|
177 | A function caller can also specify a positive integer value in milliseconds. |
---|
178 | A function will return with <i>errno</i> set to EINVAL if a bad value |
---|
179 | is given for <i>timeout</i>. |
---|
180 | When a function times out the function returns in error with <i>errno</i> |
---|
181 | set to <b>EAGAIN</b>. In the future this may change to an exception being |
---|
182 | thrown. |
---|
183 | </p> |
---|
184 | <h2>Function Descriptions</h2> |
---|
185 | <dl> |
---|
186 | <!-- SM_IO_FOPEN --> |
---|
187 | <p></p> |
---|
188 | <dt><tt><a name="sm_io_fopen"> |
---|
189 | SM_FILE_T * |
---|
190 | <br> |
---|
191 | sm_io_fopen(char *pathname, int flags) |
---|
192 | <br> |
---|
193 | SM_FILE_T * |
---|
194 | <br> |
---|
195 | sm_io_fopen(char *pathname, int flags, MODE_T mode) |
---|
196 | </a></tt></dt> |
---|
197 | <dd> |
---|
198 | Open the file named by <tt>pathname</tt>, and associate a stream with it. |
---|
199 | The arguments are the same as for the <tt>open(2)</tt> system call. |
---|
200 | <br> |
---|
201 | If memory could not be allocated, an exception is raised. |
---|
202 | If successful, an <tt>SM_FILE_T</tt> pointer is returned. |
---|
203 | Otherwise, <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"> |
---|
207 | SM_FILE_T * |
---|
208 | <br> |
---|
209 | sm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool) |
---|
210 | </a></tt></dt> |
---|
211 | <dd> |
---|
212 | Opens a file by <i>type</i> directed by <i>info</i>. <i>Type</i> is a filled-in |
---|
213 | SM_FILE_T structure from the following builtin list |
---|
214 | (<a href="#builtins"><b>descriptions below</b></a>) |
---|
215 | or one specified by the program. |
---|
216 | <menu> |
---|
217 | <li> |
---|
218 | SmFtString |
---|
219 | </li> |
---|
220 | <li> |
---|
221 | SmFtStdio |
---|
222 | </li> |
---|
223 | <li> |
---|
224 | SmFtStdiofd |
---|
225 | </li> |
---|
226 | <li> |
---|
227 | smioin <b>*</b> |
---|
228 | </li> |
---|
229 | <li> |
---|
230 | smioout <b>*</b> |
---|
231 | </li> |
---|
232 | <li> |
---|
233 | smioerr <b>*</b> |
---|
234 | </li> |
---|
235 | <li> |
---|
236 | smiostdin <b>*</b> |
---|
237 | </li> |
---|
238 | <li> |
---|
239 | smiostdout <b>*</b> |
---|
240 | </li> |
---|
241 | <li> |
---|
242 | smiostderr <b>*</b> |
---|
243 | </li> |
---|
244 | <li> |
---|
245 | SmFtSyslog |
---|
246 | </li> |
---|
247 | </menu> |
---|
248 | <br> |
---|
249 | The above list of file types are already appropriately filled in. Those marked |
---|
250 | with a "<b>*</b>" are already open and may be used directly and immediately. |
---|
251 | For 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 |
---|
253 | large, but only a small portion of it need to be initialized for a new |
---|
254 | type. |
---|
255 | See also <a href="#writefunctions">"Writing Functions for a File Type"</a>. |
---|
256 | <menu> |
---|
257 | <pre> |
---|
258 | SM_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> |
---|
263 | section. |
---|
264 | <br> |
---|
265 | <i>Info</i> is information that describes for the file type what is |
---|
266 | to be opened and any associated information. |
---|
267 | For a disk file this would be a file path; with a TCP |
---|
268 | connection this could be an a structure containing an IP address and port. |
---|
269 | <br><i>Flags</i> is a |
---|
270 | set of sm_io flags that describes how the file is to be interacted with: |
---|
271 | <menu> |
---|
272 | <li> |
---|
273 | SM_IO_RDWR - read and write |
---|
274 | </li> |
---|
275 | <li> |
---|
276 | SM_IO_RDONLY - read only |
---|
277 | </li> |
---|
278 | <li> |
---|
279 | SM_IO_WRONLY - write only |
---|
280 | </li> |
---|
281 | <li> |
---|
282 | SM_IO_APPEND - allow write to EOF only |
---|
283 | </li> |
---|
284 | <li> |
---|
285 | SM_IO_APPENDRW - allow read-write from EOF only |
---|
286 | </li> |
---|
287 | <li> |
---|
288 | SM_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 |
---|
292 | with. When the rpool is released then the close function for this |
---|
293 | file type will be automatically called to close the file for cleanup. |
---|
294 | If NULL is specified for <i>rpool</i> then the close function is not |
---|
295 | associated (attached) to an rpool. |
---|
296 | <br> |
---|
297 | On cannot allocate memory, an exception is raised. |
---|
298 | If the <i>type</i> is invalid, <tt>sm_io_open</tt> will abort the process. |
---|
299 | On success an SM_FILE_T * pointer is returned. |
---|
300 | On 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"> |
---|
305 | int |
---|
306 | <br> |
---|
307 | sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp) |
---|
308 | </a></tt></dt> |
---|
309 | <dd> |
---|
310 | For the open file <i>sfp</i> set the indicated information (<i>what</i>) |
---|
311 | to the new value <i>(valp</i>). |
---|
312 | This will make the change for this SM_FILE_T only. The file |
---|
313 | type that <i>sfp</i> originally belonged to will still be |
---|
314 | configured the same way (this is to prevent side-effect |
---|
315 | to other open's of the same file type, particularly with threads). |
---|
316 | The value of <i>what</i> will be file-type dependant since this function |
---|
317 | is one of the per file type setable functions. |
---|
318 | One value for <i>what</i> that is valid for all file types is |
---|
319 | SM_WHAT_VECTORS. This sets the currently open file with a new function |
---|
320 | vector set for open, close, etc. The new values are taken from <i>valp</i> |
---|
321 | a 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> |
---|
325 | On 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"> |
---|
330 | int |
---|
331 | <br> |
---|
332 | sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp) |
---|
333 | </a></tt></dt> |
---|
334 | <dd> |
---|
335 | For the open file <i>sfp</i> get the indicated information (<i>what</i>) |
---|
336 | and place the result in <i>(valp</i>). |
---|
337 | This will obtain information for SM_FILE_T only and may be different than |
---|
338 | the information for the file type it was originally opened as. |
---|
339 | The value of <i>what</i> will be file type dependant since this function |
---|
340 | is one of the per file type setable functions. |
---|
341 | One value for <i>what</i> that is valid for all file types is |
---|
342 | SM_WHAT_VECTORS. This gets from the currently open file a copy of |
---|
343 | the 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> |
---|
347 | On 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"> |
---|
352 | void |
---|
353 | <br> |
---|
354 | sm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2) |
---|
355 | </a></tt></dt> |
---|
356 | <dd> |
---|
357 | Associate a read of <i>fp1</i> with a data flush for <i>fp2</i>. If a read |
---|
358 | of <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 |
---|
360 | assumed that <i>fp1</i> is open for reading and <i>fp2</i> is open |
---|
361 | for writing. |
---|
362 | <br> |
---|
363 | On return the old file pointer associated with <i>fp1</i> for flushing |
---|
364 | is returned. A return of NULL is no an error; this merely indicates no |
---|
365 | previous association. |
---|
366 | </dd> |
---|
367 | <!-- SM_IO_AUTOMODE --> |
---|
368 | <p></p> |
---|
369 | <dt><tt><a name="sm_io_automode"> |
---|
370 | void |
---|
371 | <br> |
---|
372 | sm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2) |
---|
373 | <dt><tt><a name="sm_io_automode"> |
---|
374 | </a></tt></dt> |
---|
375 | <dd> |
---|
376 | Associate the two file pointers for blocking/non-blocking mode changes. |
---|
377 | In the handling of timeouts <i>sm_io</i> may need to switch the mode of |
---|
378 | a file between blocking and non-blocking. If the underlying file descriptor |
---|
379 | has been duplicated with <tt>dup(2)</tt> and these descriptors are used |
---|
380 | by <i>sm_io</i> (for example with an SmFtStdiofd file type), then this API |
---|
381 | should be called to associate them. Otherwise odd behavior (i.e. errors) |
---|
382 | may 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"> |
---|
387 | int |
---|
388 | <br> |
---|
389 | sm_io_close(SM_FILE_T *sfp, int timeout) |
---|
390 | </a></tt></dt> |
---|
391 | <dd> |
---|
392 | Release all resources (file handles, memory, etc.) associated with |
---|
393 | the open SM_FILE_T <i>sfp</i>. If buffering is active then the |
---|
394 | buffer is flushed before any resources are released. |
---|
395 | <i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a> |
---|
396 | section. |
---|
397 | The first resources released after buffer flushing will be the |
---|
398 | buffer itself. Then the <b>close</b> function specified in the |
---|
399 | file type at open will be called. It is the responsibility |
---|
400 | of the <b>close</b> function to release any file type |
---|
401 | specific resources allocated and to call <tt>sm_io_close()</tt> |
---|
402 | for the next file type layer(s) that the current file type uses (if any). |
---|
403 | <br> |
---|
404 | On success 0 (zero) is returned. On failure SM_IO_EOF is returned and |
---|
405 | errno is set. |
---|
406 | </dd> |
---|
407 | </dl> |
---|
408 | <h2> |
---|
409 | <a name="builtins">Description of Builtin File Types</a> |
---|
410 | </h2> |
---|
411 | <p> |
---|
412 | There are several builtin file types as mentioned in <tt>sm_io_open()</tt>. |
---|
413 | More file types may be added later. |
---|
414 | </p> |
---|
415 | <dl> |
---|
416 | <p></p> |
---|
417 | <dt><tt>SmFtString</tt></dt> |
---|
418 | <dd> |
---|
419 | Operates on a character string. <i>SmFtString</i> is a file type only. |
---|
420 | The string starts at the location 0 (zero) |
---|
421 | and ends at the last character. A read will obtain the requested |
---|
422 | number of characters if available; else as many as possible. A read |
---|
423 | will not terminate the read characters with a NULL ('\0'). A write |
---|
424 | will place the number of requested characters at the current location. |
---|
425 | To append to a string either the pointer must currently be at the end |
---|
426 | of the string or a seek done to position the pointer. The file type |
---|
427 | handles the space needed for the string. Thus space needed for the |
---|
428 | string will be grown automagically without the user worrying about |
---|
429 | space management. |
---|
430 | </dd> |
---|
431 | <dt><tt>SmFtStdio</tt></dt> |
---|
432 | <dd> |
---|
433 | A predefined SM_FILE_T structure with function vectors pointing to |
---|
434 | functions that result in the file-type behaving as the system stdio |
---|
435 | normally does. The <i>info</i> portion of the <tt>sm_io_open</tt> |
---|
436 | is the path of the file to be opened. Note that this file type |
---|
437 | does not interact with the system's stdio. Thus a program mixing system |
---|
438 | stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input |
---|
439 | and output. |
---|
440 | </dd> |
---|
441 | <dt><tt>SmFtStdiofd</tt></dt> |
---|
442 | <dd> |
---|
443 | A predefined SM_FILE_T structure with function vectors pointing to |
---|
444 | functions that result in the file-type behaving as the system stdio |
---|
445 | normally does. The <i>info</i> portion of the <tt>sm_io_open</tt> |
---|
446 | is a file descriptor (the value returned by open(2)). Note that this file type |
---|
447 | does not interact with the system's stdio. Thus a program mixing system |
---|
448 | stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input |
---|
449 | and output. |
---|
450 | </dd> |
---|
451 | <dt><tt>smioin</tt></dt> |
---|
452 | <dt><tt>smioout</tt></dt> |
---|
453 | <dt><tt>smioerr</tt></dt> |
---|
454 | <dd> |
---|
455 | The three types <i>smioin</i>, <i>smioout</i> and <i>smioerr</i> are grouped |
---|
456 | together. These three types |
---|
457 | perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i> |
---|
458 | and <i>stderr</i>. These types are both the names and the file pointers. |
---|
459 | They are already open when a program starts (unless the parent explictly |
---|
460 | closed file descriptors 0, 1 and 2). |
---|
461 | Thus <tt>sm_io_open()</tt> should never be called for these types: |
---|
462 | the named file pointers should be used directly. |
---|
463 | <i>Smioin</i> and <i>smioout</i> are buffered |
---|
464 | by default. <i>Smioerr</i> is not buffered by default. Calls to <b>stdio</b> |
---|
465 | are safe to make when using these three<b>sm_io</b> file pointers. |
---|
466 | There is no interaction between <b>sm_io</b> and <b>stdio</b>. Hence, |
---|
467 | due to buffering, the sequence of input and output data from both <b>sm_io</b> |
---|
468 | and <b>stdio</b> at the same time may appear unordered. For |
---|
469 | coordination between <b>sm_io</b> and <b>stdio</b> use the three |
---|
470 | file 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> |
---|
476 | The three types <i>smiostdin</i>, <i>smioostdut</i> and <i>smiostderr</i> |
---|
477 | are grouped together. These three types |
---|
478 | perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i> |
---|
479 | and <i>stderr</i>. These types are both the names and file pointers. |
---|
480 | They are already open when a program starts (unless the parent explictly |
---|
481 | close file descriptors 0, 1 and 2). |
---|
482 | Thus <tt>sm_io_open()</tt> should |
---|
483 | never be called: the named file pointers should be used directly. |
---|
484 | Calls to <b>stdio</b> are safe to make when using these three<b>sm_io</b> |
---|
485 | file pointers though no code is shared between the two libaries. |
---|
486 | However, the input and output between <i>sm_io</i> and <i>stdio</i> is |
---|
487 | coordinated for these three file pointers: <i>smiostdin</i>, |
---|
488 | <i>smiostdout</i> and <i>smiostderr</i> are layered on-top-of |
---|
489 | the system's <i>stdio</i>. |
---|
490 | <i>Smiostdin</i>, <i>smiostdout</i> |
---|
491 | and <i>Smiostderr</i> are not buffered by default. |
---|
492 | Hence, due to buffering in <i>stdio</i> only, the sequence of input and |
---|
493 | output data from both <b>sm_io</b> and <b>stdio</b> at the same time will |
---|
494 | appear ordered. If <i>sm_io</i> buffering is turned on then the |
---|
495 | input and output can appear unordered or lost. |
---|
496 | </dd> |
---|
497 | <dt><tt>SmFtSyslog</tt></dt> |
---|
498 | <dd> |
---|
499 | This opens the channel to the system log. Reads are not allowed. Writes |
---|
500 | cannot be undone once they have left the <i>sm_io</i> buffer. |
---|
501 | The man pages for <tt>syslog(3)</tt> should be read for information |
---|
502 | on syslog. |
---|
503 | </dd> |
---|
504 | </dl> |
---|
505 | <p></p> |
---|
506 | <hr> |
---|
507 | <p></p> |
---|
508 | <h2> |
---|
509 | <a name="writefunctions"> |
---|
510 | Writing Functions for a File Type |
---|
511 | </a> |
---|
512 | </h2> |
---|
513 | <p> |
---|
514 | When writing functions to create a file type a function needs to |
---|
515 | be created for each function vector in the SM_FILE_T structure |
---|
516 | that will be passed to <tt>sm_io_open()</tt> or <tt>sm_io_setinfo()</tt>. |
---|
517 | Otherwise the setting will be rejected and <i>errno</i> set to EINVAL. |
---|
518 | Each function should accept and handle the number and types of arguments as |
---|
519 | described 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> |
---|
532 | The macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file |
---|
533 | type for an <tt>sm_io_open()</tt>: |
---|
534 | <menu> |
---|
535 | <pre> |
---|
536 | SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout) |
---|
537 | </pre> |
---|
538 | <br> |
---|
539 | where: |
---|
540 | <menu> |
---|
541 | <li> |
---|
542 | type - is the SM_FILE_T being filled-in |
---|
543 | </li> |
---|
544 | <li> |
---|
545 | name - a human readable character string for human identification purposes |
---|
546 | </li> |
---|
547 | <li> |
---|
548 | open - the vector to the open function |
---|
549 | </li> |
---|
550 | <li> |
---|
551 | close - the vector to the close function |
---|
552 | </li> |
---|
553 | <li> |
---|
554 | read - the vector to the read function |
---|
555 | </li> |
---|
556 | <li> |
---|
557 | write - the vector to the write function |
---|
558 | </li> |
---|
559 | <li> |
---|
560 | seek - the vector to the seek function |
---|
561 | </li> |
---|
562 | <li> |
---|
563 | set - the vector to the set function |
---|
564 | </li> |
---|
565 | <li> |
---|
566 | get - the vector to the get function |
---|
567 | </li> |
---|
568 | <li> |
---|
569 | timeout - the default to be used for a timeout when SM_TIME_DEFAULT specified |
---|
570 | </li> |
---|
571 | </menu> |
---|
572 | </menu> |
---|
573 | You should avoid trying to change or use the other structure members of the |
---|
574 | SM_FILE_T. The file pointer content (internal structure members) of an active |
---|
575 | file should only be set and observed with the "info" functions. |
---|
576 | The 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> |
---|
578 | while <i>ival</i> is of type <tt>int</tt>. These two structure members exist |
---|
579 | specificly for your created file type to use. The <i>sm_io</i> functions |
---|
580 | will not change or set these two structure members; only specific file type |
---|
581 | will change or set these variables. |
---|
582 | </p> |
---|
583 | <p> |
---|
584 | For maintaining information privately about status for a file type the |
---|
585 | information should be encapsulated in a <i>cookie</i>. A <i>cookie</i> |
---|
586 | is an opaque type that contains information that is only known to |
---|
587 | the file type layer itself. The <i>sm_io</i> package will know |
---|
588 | nothing about the contents of the <i>cookie</i>; <i>sm_io</i> only |
---|
589 | maintains the location of the <i>cookie</i> so that it may be passed |
---|
590 | to the functions of a file type. It is up to the file type to |
---|
591 | determine what to do with the <i>cookie</i>. It is the responsibility |
---|
592 | of 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. |
---|
594 | It is the responsibility of close to clean up |
---|
595 | any resources that the cookie and instance of the file type have used. |
---|
596 | </p> |
---|
597 | <p> |
---|
598 | For the <i>cookie</i> to be passed to all members of a function type |
---|
599 | cleanly the location of the cookie must assigned during |
---|
600 | the call to open. The file type functions should not attempt to |
---|
601 | maintain the <i>cookie</i> internally since the file type may have |
---|
602 | serveral instances (file pointers). |
---|
603 | </p> |
---|
604 | <p> |
---|
605 | The 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 |
---|
607 | or access status (other members do that). It is intended as a "light" |
---|
608 | reference. |
---|
609 | </p> |
---|
610 | <p> |
---|
611 | The file type vector functions are called by the <tt>sm_io_*()</tt> |
---|
612 | functions after <i>sm_io</i> processing has occurred. The <i>sm_io</i> |
---|
613 | processing validates SM_FILE_T's and may then handle the call entirely |
---|
614 | itself or pass the request to the file type vector functions. |
---|
615 | </p> |
---|
616 | <p> |
---|
617 | All of the "int" functions should return -1 (minus one) on failure |
---|
618 | and 0 (zero) or greater on success. <i>Errno</i> should be set to |
---|
619 | provide diagnostic information to the caller if it has not already |
---|
620 | been set by another function the file type function used. |
---|
621 | </p> |
---|
622 | <p> |
---|
623 | Examples are a wonderful manner of clarifying details. Below is an example |
---|
624 | of an open function. |
---|
625 | </p> |
---|
626 | <p> |
---|
627 | This shows the setup. |
---|
628 | <menu> |
---|
629 | <pre> |
---|
630 | SM_FILE_T *fp; |
---|
631 | SM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite, |
---|
632 | myseek, myget, myset, SM_TIME_FOREVER); |
---|
633 | |
---|
634 | fp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL); |
---|
635 | |
---|
636 | if (fp == NULL) |
---|
637 | return(-1); |
---|
638 | </pre> |
---|
639 | The above code open's a file of type "my_type". The <i>info</i> is set |
---|
640 | to a string "data". "data" may be the name of a file or have some special |
---|
641 | meaning to the file type. For sake of the example, we will have it be |
---|
642 | the name of a file in the home directory of the user running the program. |
---|
643 | Now the only file type function that is dependent on this information |
---|
644 | will be the open function. |
---|
645 | <br> |
---|
646 | We have also specified read-only access (SM_IO_RDONLY) and that no <i>rpool</i> |
---|
647 | will be used. The <i>timeout</i> has been set to 1000 milliseconds which |
---|
648 | directs that the file and all associated setup should be done within |
---|
649 | 1000 milliseconds or return that the function erred (with errno==EAGAIN). |
---|
650 | <pre> |
---|
651 | int 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> |
---|
680 | Later on when a write is performed the function <tt>mywrite</tt> will |
---|
681 | be invoked. To match the above <tt>myopen</tt>, <tt>mywrite</tt> could |
---|
682 | be written as: |
---|
683 | <pre> |
---|
684 | int 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> |
---|
708 | As a thought-exercise for the fair reader: how would you modify the |
---|
709 | above 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 |
---|
711 | be opened and written to. (Hint: create a cookie to hold two or more |
---|
712 | file 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"> |
---|
723 | libsm sm_io default API definition |
---|
724 | </a> |
---|
725 | </h1> |
---|
726 | </center> |
---|
727 | <h2> Introduction </h2> |
---|
728 | <p> |
---|
729 | A number of <i>sm_io</i> API's perform similar to their <i>stdio</i> |
---|
730 | counterparts (same name as when the "sm_io_" is removed). |
---|
731 | One difference between <i>sm_io</i> and <i>stdio</i> functions is that |
---|
732 | if a "file pointer" (FILE/SM_FILE_T) |
---|
733 | is one of the arguments for the function, then it is now the first |
---|
734 | argument. <i>Sm_io</i> is standardized so that when a file pointer is |
---|
735 | one of the arguments to function then it will always be the first |
---|
736 | arguement. Many of the <i>sm_io</i> function take a <i>timeout</i> |
---|
737 | argument (see <a href="#timeouts"><b>Timeouts</b></a>). |
---|
738 | </p> |
---|
739 | <p> |
---|
740 | The API you have selected is one of these. Please consult the |
---|
741 | appropriate <i>stdio</i> man page for now. |
---|
742 | </p> |
---|
743 | |
---|
744 | </body> |
---|
745 | </html> |
---|