1 /*
2 ** Copyright (C) 2006-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 
9 /*
10 **  skstream.h
11 **
12 **    An interface around file descriptors, which allows for buffered
13 **    reading and writing, as well as compression.
14 **
15 */
16 #ifndef _SKSTREAM_H
17 #define _SKSTREAM_H
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 #include <silk/silk.h>
23 
24 RCSIDENTVAR(rcsID_SKSTREAM_H, "$SiLK: skstream.h ef14e54179be 2020-04-14 21:57:45Z mthomas $");
25 
26 #include <silk/silk_types.h>
27 #include <silk/silk_files.h>
28 #include <silk/skheader.h>
29 
30 /**
31  *  @file
32  *
33  *    An interface around file descriptors, which allows for buffered
34  *    reading and writing, as well as compression.
35  *
36  *    This file is part of libsilk.
37  */
38 
39 
40 /**
41  * Default (uncompressed) block size used when writing/reading: 64k
42  */
43 #define SKSTREAM_DEFAULT_BLOCKSIZE  0x10000
44 
45 
46 /*
47  *    skstream_t, skstream_mode_t, skcontent_t are defined in
48  *    silk_types.h.
49  */
50 
51 
52 /**
53  *    Return values that most skStream*() functions return
54  */
55 typedef enum {
56     /** The last command was completed successfully. */
57     SKSTREAM_OK = 0,
58 
59     /* The following often represent programmer errors */
60 
61     /** Memory could not be allocated. */
62     SKSTREAM_ERR_ALLOC = -64,
63 
64     /** Attempt to operate on a file that is already closed.  Once
65      * closed, a stream can only be destroyed; re-opening is not (yet)
66      * supported. */
67     SKSTREAM_ERR_CLOSED = -65,
68 
69     /** An argument to a function is invalid: passing skStreamFDOpen()
70      * a value of -1, passing too long a pathname ti skStreamBind(),
71      * using an supported SiLK file format. */
72     SKSTREAM_ERR_INVALID_INPUT = -66,
73 
74     /** Attempt to open a stream that is not bound to a pathname. */
75     SKSTREAM_ERR_NOT_BOUND = -67,
76 
77     /** Attempt to read or write from a stream that has not yet been
78      * opened. */
79     SKSTREAM_ERR_NOT_OPEN = -68,
80 
81     /** An argument to the function is NULL or empty */
82     SKSTREAM_ERR_NULL_ARGUMENT = -69,
83 
84     /** The stream is already bound to a pathname. */
85     SKSTREAM_ERR_PREV_BOUND = -70,
86 
87     /** Attempt to operate on a stream in a way that is not support
88      * since data has already been written-to/read-from the stream. */
89     SKSTREAM_ERR_PREV_DATA = -71,
90 
91     /** The stream is already open. */
92     SKSTREAM_ERR_PREV_OPEN = -72,
93 
94     /** The file's content type does not support the action: attempt to
95      * skStreamRead() on a SK_CONTENT_TEXT stream, attempt to
96      * skStreamPrint() to a binary or SiLK stream, etc. */
97     SKSTREAM_ERR_UNSUPPORT_CONTENT = -73,
98 
99     /** The skStreamSetCopyInput() function has already been called on
100      * this stream. */
101     SKSTREAM_ERR_PREV_COPYINPUT = -74,
102 
103 
104     /* Errors due to missing or outdated libraries */
105 
106     /** The stream is compressed with a compression method that SiLK
107      * does not recognize. */
108     SKSTREAM_ERR_COMPRESS_INVALID = -80,
109 
110     /** The stream is compressed with a unavailable compression mode;
111      * for example, you're operating on a gzipped file but SiLK was
112      * not linked with gzip. */
113     SKSTREAM_ERR_COMPRESS_UNAVAILABLE = -81,
114 
115 
116     /* User errors when creating a new stream */
117 
118     /** The file's header does not contain the SiLK magic number---for
119      * files that contain SK_CONTENT_SILK. */
120     SKSTREAM_ERR_BAD_MAGIC = -16,
121 
122     /** Attempt to open a stream for writing that is bound to a file
123      * name that already exists. */
124     SKSTREAM_ERR_FILE_EXISTS = -17,
125 
126     /** Attempt to read or write binary data on a terminal (tty) */
127     SKSTREAM_ERR_ISTERMINAL = -18,
128 
129     /** Attempt to invoke the paging program failed. */
130     SKSTREAM_ERR_NOPAGER = -19,
131 
132     /** Could not get a read lock on the stream. */
133     SKSTREAM_ERR_RLOCK = -20,
134 
135     /** The call to fdopen() failed. */
136     SKSTREAM_ERR_SYS_FDOPEN = -21,
137 
138     /** The call to lseek() failed. */
139     SKSTREAM_ERR_SYS_LSEEK = -22,
140 
141     /** The call to open() failed. */
142     SKSTREAM_ERR_SYS_OPEN = -23,
143 
144     /** The call to mkstemp() failed. */
145     SKSTREAM_ERR_SYS_MKSTEMP = -24,
146 
147     /** The file's read/write status does not support the action: an
148      * attempt to write to "stdin", an attempt to append to a FIFO or
149      * a gzipped file. */
150     SKSTREAM_ERR_UNSUPPORT_IOMODE = -25,
151 
152     /** Could not get a read lock on the stream. */
153     SKSTREAM_ERR_WLOCK = -26,
154 
155     /** The call to fork() failed. */
156     SKSTREAM_ERR_SYS_FORK = -27,
157 
158     /** The call to pipe() failed. */
159     SKSTREAM_ERR_SYS_PIPE = -28,
160 
161     /** The call to mkdir() failed. */
162     SKSTREAM_ERR_SYS_MKDIR = -29,
163 
164     /** The call to fcntl(fd, F_GETFL) failed. */
165     SKSTREAM_ERR_SYS_FCNTL_GETFL = -30,
166 
167     /* Errors that may occur while processing the stream that
168      * typically indicate a fatal condition. */
169 
170     /** Value returned skStreamRead() and skStreamWrite() when an error
171      * has occured. */
172     SKSTREAM_ERR_IO = -1,
173 
174     /** Error with internal buffering. */
175     SKSTREAM_ERR_IOBUF = -2,
176 
177     /** There was an error writing to the stream. */
178     SKSTREAM_ERR_WRITE = -3,
179 
180     /** There was an error reading from the stream. */
181     SKSTREAM_ERR_READ = -4,
182 
183     /** Value returned when the input is exhausted.  Note that reaching
184      * the end of a file is not really an "error". */
185     SKSTREAM_ERR_EOF = -5,
186 
187     /** Error occurred in a gz* function */
188     SKSTREAM_ERR_ZLIB = -6,
189 
190     /** The read returned fewer bytes than required for a complete
191      * record. */
192     SKSTREAM_ERR_READ_SHORT = -7,
193 
194     /** The operation requires the stream to be bound to a seekable
195      * file, and the stream is not. */
196     SKSTREAM_ERR_NOT_SEEKABLE = -8,
197 
198     /** The call to ftruncate() failed. */
199     SKSTREAM_ERR_SYS_FTRUNCATE = -9,
200 
201 
202     /* The following set of errors are general errors that occur when
203      * opening a SiLK file for read, write, or append. */
204 
205     /** The file has a format that does not support this operation.
206      * See also the next error code. */
207     SKSTREAM_ERR_UNSUPPORT_FORMAT = 32,
208 
209     /** An operation that requires SiLK Flow data is attempting to open
210      * a SiLK file that does not contain flows. */
211     SKSTREAM_ERR_REQUIRE_SILK_FLOW = 33,
212 
213     /** The file or record has a version that this version of libsilk
214      * does not know how to handle */
215     SKSTREAM_ERR_UNSUPPORT_VERSION = 34,
216 
217 
218     /* The following set of errors affect only the current record;
219      * they occur when trying to write a record to a stream.  These
220      * are considered non-fatal.  Use the SKSTREAM_ERROR_IS_FATAL()
221      * macro below. */
222 
223     /** The record's start time is less than the file's start time */
224     SKSTREAM_ERR_STIME_UNDRFLO = 64,
225 
226     /** The record's start time at least an hour greater than the
227      * file's start time */
228     SKSTREAM_ERR_STIME_OVRFLO = 65,
229 
230     /** The record's elapsed time is greater than space allocated for
231      * duration in this file format */
232     SKSTREAM_ERR_ELPSD_OVRFLO = 66,
233 
234     /** The record contains more than the number of packets allowed in
235      * this file format */
236     SKSTREAM_ERR_PKTS_OVRFLO = 67,
237 
238     /** The record contains a 0 value in the packets field. */
239     SKSTREAM_ERR_PKTS_ZERO = 68,
240 
241     /** The byte-per-packet value is too large to fit into the space
242      * provided by this file format. */
243     SKSTREAM_ERR_BPP_OVRFLO = 69,
244 
245     /** The records contains an SNMP value too large to fit into the
246      * space allocated in this file format. */
247     SKSTREAM_ERR_SNMP_OVRFLO = 70,
248 
249     /** The records contains a SensorID too large to fit into the space
250      * allocated in this file format. */
251     SKSTREAM_ERR_SENSORID_OVRFLO = 71,
252 
253     /** The record's IP protocol is not supported by the file's format;
254      * for example, trying to store a non-TCP record in a FT_RWWWW
255      * file. */
256     SKSTREAM_ERR_PROTO_MISMATCH = 72,
257 
258     /** The record's "packets" value is greater than the "bytes" value. */
259     SKSTREAM_ERR_PKTS_GT_BYTES = 73,
260 
261     /** The record is an IPv6 record which is not supported. */
262     SKSTREAM_ERR_UNSUPPORT_IPV6 = 74,
263 
264     /** The record contains more than the number of bytes (octets)
265      * allowed in this file format */
266     SKSTREAM_ERR_BYTES_OVRFLO = 75,
267 
268     /* Errors that may occur which indicate an error with one
269      * line/record, but which are normally not fatal */
270 
271     /** Returned by skStreamGetLine() when an input line is longer than
272      * the specified buffer size. */
273     SKSTREAM_ERR_LONG_LINE = 96
274 
275 } skstream_err_t;
276 
277 
278 /**
279  *  SKSTREAM_ERROR_IS_FATAL(err);
280  *
281  *    Evaluates to a true value if error is a fatal error, false otherwise.
282  */
283 #define SKSTREAM_ERROR_IS_FATAL(err) ((err) != SKSTREAM_OK && (err) < 64)
284 
285 
286 /**
287  *    Set 'stream' to operate on the file specified in 'pathname';
288  *    'pathname' may also be one of "stdin", "stdout", or "stderr".
289  *    Return SKSTREAM_OK on success, or one of these error codes:
290  *
291  *    SKSTREAM_ERR_NULL_ARGUMENT
292  *    SKSTREAM_ERR_PREV_BOUND
293  *    SKSTREAM_ERR_INVALID_INPUT
294  *    SKSTREAM_ERR_ISTERMINAL
295  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
296  */
297 int
298 skStreamBind(
299     skstream_t         *stream,
300     const char         *pathname);
301 
302 
303 
304 
305 /**
306  *    Check that the compression method used by 'stream' is known and
307  *    is available.  Return SKSTREAM_OK if it is; otherwise return an
308  *    error code as described below and print an error message using
309  *    the 'err_fn' when it is provided.
310  *
311  *    If the stream uses an unknown compression method, return
312  *    SKSTREAM_ERR_COMPRESS_INVALID.  If the compression method is
313  *    recognized but not available in this compilation of SiLK, return
314  *    SKSTREAM_ERR_COMPRESS_UNAVAILABLE.
315  */
316 int
317 skStreamCheckCompmethod(
318     skstream_t         *stream,
319     sk_msg_fn_t         err_fn);
320 
321 
322 /**
323  *    Check several attributes of the SiLK header on the file
324  *    associated with 'stream'.  If the header passes all tests,
325  *    return SKSTREAM_OK.  If the header fails a test an error code is
326  *    returned; in addtion, if 'err_fn' is provided, that function
327  *    will be called to print an error message.
328  *
329  *    If the stream's format is not 'file_format', return
330  *    SKSTREAM_ERR_UNSUPPORT_FORMAT.
331  *
332  *    If the version of the records in the stream is below
333  *    'min_rec_version' or above 'max_rec_version', return
334  *    SKSTREAM_ERR_UNSUPPORT_VERSION.
335  *
336  *    The skStreamCheckCompmethod() function is also called.
337  */
338 int
339 skStreamCheckSilkHeader(
340     skstream_t         *stream,
341     sk_file_format_t    file_format,
342     sk_file_version_t   min_rec_version,
343     sk_file_version_t   max_rec_version,
344     sk_msg_fn_t         err_fn);
345 
346 
347 /**
348  *    Flush any data on the 'stream' and closes the underlying file
349  *    descriptor.  Return SKSTREAM_OK on success, or one of these
350  *    error codes:
351  *
352  *    SKSTREAM_ERR_NULL_ARGUMENT
353  *    SKSTREAM_ERR_CLOSED
354  *    SKSTREAM_ERR_NOT_OPEN
355  *    SKSTREAM_ERR_WRITE
356  *    SKSTREAM_ERR_IOBUF
357  *    SKSTREAM_ERR_ZLIB
358  */
359 int
360 skStreamClose(
361     skstream_t         *stream);
362 
363 
364 /**
365  *    Create a new stream at the location pointed to by 'new_stream';
366  *    the action to perform on 'new_stream' is determined by
367  *    'read_write_append', and 'content_type' specified the content of
368  *    'new_stream'.  Return SKSTREAM_OK on success, or one of these
369  *    error codes:
370  *
371  *    SKSTREAM_ERR_NULL_ARGUMENT
372  *    SKSTREAM_ERR_ALLOC
373  */
374 int
375 skStreamCreate(
376     skstream_t        **new_stream,
377     skstream_mode_t     read_write_append,
378     skcontent_t         content_type);
379 
380 
381 /**
382  *    Closes the stream at '*stream', if open, destroys the stream
383  *    pointed at by 'stream' and sets '*stream' to NULL.  If 'stream'
384  *    is NULL or its value is NULL, no action is taken and the
385  *    function returns.  Return SKSTREAM_OK on success, or any of the
386  *    error codes listed by skStreamClose().
387  */
388 int
389 skStreamDestroy(
390     skstream_t        **stream);
391 
392 
393 /**
394  *    Associate 'stream' with the previously opened file descriptor
395  *    'file_desc'.  The 'stream' must have been previously bound to a
396  *    filename.  Return SKSTREAM_OK on success, or one of these error
397  *    codes:
398  *
399  *    SKSTREAM_ERR_NULL_ARGUMENT
400  *    SKSTREAM_ERR_NOT_BOUND
401  *    SKSTREAM_ERR_PREV_OPEN
402  *    SKSTREAM_ERR_CLOSED
403  *    SKSTREAM_ERR_INVALID_INPUT
404  *    SKSTREAM_ERR_UNSUPPORT_COMPRESS
405  *    SKSTREAM_ERR_ALLOC
406  */
407 int
408 skStreamFDOpen(
409     skstream_t         *stream,
410     int                 file_desc);
411 
412 
413 /**
414  *    Flush any data in the stream's buffers to disk; has no effect on
415  *    a stream open for reading.  Return SKSTREAM_OK on success, or
416  *    one of these error codes:
417  *
418  *    SKSTREAM_ERR_IOBUF
419  *    SKSTREAM_ERR_NULL_ARGUMENT
420  *    SKSTREAM_ERR_NOT_OPEN
421  *    SKSTREAM_ERR_WRITE
422  */
423 int
424 skStreamFlush(
425     skstream_t         *stream);
426 
427 
428 /**
429  *    Return the type of content associated with the stream.
430  */
431 skcontent_t
432 skStreamGetContentType(
433     const skstream_t   *stream);
434 
435 
436 /**
437  *    Return the file descriptor associated with 'stream'.
438  */
439 int
440 skStreamGetDescriptor(
441     const skstream_t   *stream);
442 
443 
444 /**
445  *    Return the value of errno that is cached on 'stream'.
446  *
447  *    The skstream_t normally only caches errno for failed commands,
448  *    so the returned value may not reflect the errno from the most
449  *    recent command.  See also skStreamGetLastReturnValue().
450  */
451 int
452 skStreamGetLastErrno(
453     const skstream_t   *stream);
454 
455 
456 /**
457  *    Return the result (the error code) that was returned by the most
458  *    recent function that modified 'stream'.
459  *
460  *    Most functions that modify the stream store the return value on
461  *    the stream as well as returning it to the caller.  This function
462  *    returns the stored value.
463  *
464  *    Unlike skStreamGetLastErrno(), nearly all functions store the
465  *    return value before returning it---whether the function was
466  *    successful or reported an error.
467  */
468 ssize_t
469 skStreamGetLastReturnValue(
470     const skstream_t   *stream);
471 
472 
473 /**
474  *    Fill 'value' with the limit implied by the error code given in
475  *    'limit_id', which should be an skstream_err_t.
476  *
477  *    The 'stream' must be a SiLK stream that has a header.  If it is
478  *    not, SKSTREAM_ERR_REQUIRE_SILK_FLOW is returned.
479  *
480  *    The following 'limit_id' values are supported:
481  *
482  *    SKSTREAM_ERR_STIME_UNDRFLO -- Fills 'value' with the minimum
483  *    starting time supported, as milliseconds since the UNIX epoch.
484  *    This is either 0 or the start hour specified in the stream's
485  *    header.
486  *
487  *    SKSTREAM_ERR_STIME_OVRFLO -- Fills 'value' with the maximum
488  *    starting time supported, as milliseconds since the UNIX epoch.
489  *    This will be one hour beyond the starting time in the stream's
490  *    header, or a later time depending on the file format.
491  *
492  *    SKSTREAM_ERR_ELPSD_OVRFLO -- Fills 'value' with the maximum flow
493  *    duration supported, in milliseconds.  This value will be between
494  *    2,047,000 and 4,294,967,295, depending on file format.
495  *
496  *    SKSTREAM_ERR_PKTS_ZERO -- Fills 'value' with 1, which is the
497  *    minimum packet value supported by most formats.
498  *
499  *    SKSTREAM_ERR_PKTS_OVRFLO -- Fills 'value' with the maximum
500  *    packet count supported.  This value will be between 16,777,215
501  *    and 4,294,967,295, depending on file format.
502  *
503  *    SKSTREAM_ERR_BPP_OVRFLO -- Fills 'value' with the maximum
504  *    byte-per-packet ratio supported.  This value will be between
505  *    16,383 and 4,294,967,295, depending on file format.
506  *
507  *    SKSTREAM_ERR_SNMP_OVRFLO -- Fills 'value' with the maximum SNMP
508  *    value supported.  This is 255 for some formats, 65,535 for other
509  *    formats, or 0 if the format ignores SNMP interfaces.
510  *
511  *    SKSTREAM_ERR_SENSORID_OVRFLO -- Fills 'value' with the maximum
512  *    sensor ID value supported.  This is 65,535 for most formats, but
513  *    may be as small as 63 for very old formats.
514  *
515  *    Any other value for 'limit_id' leaves 'value' untouched and
516  *    returns SKSTREAM_ERR_INVALID_INPUT.
517  */
518 int
519 skStreamGetLimit(
520     const skstream_t   *stream,
521     int                 limit_id,
522     int64_t            *value);
523 
524 
525 /**
526  *    Read a line of text from 'stream' and store it in 'out_buffer',
527  *    a character array of buf_size characters.  If 'line_count' is
528  *    non-NULL, it's value will be INCREMENTED by the number of lines
529  *    read, typically 1.  The line will be truncated at the newline
530  *    character---the newline will not be returned.  Return
531  *    SKSTREAM_OK on success, or SKSTREAM_ERR_EOF at the end of file.
532  *
533  *    Lines containing only whitespace are ignored.  If the stream's
534  *    comment character has been set, comments are stripped from the
535  *    input as well, and lines containing only comments are ignored.
536  *
537  *    If a line is longer than 'buf_size', the line is ignored and
538  *    SKSTREAM_ERR_LONG_LINE is returned.  The value in 'out_buffer'
539  *    will be random.
540  *
541  *    This function requires that 'stream' be an SK_IO_READ stream
542  *    that has a content type of SK_CONTENT_TEXT.
543  *
544  *    In addition to the above return values, the function may also
545  *    return:
546  *
547  *    SKSTREAM_ERR_NULL_ARGUMENT
548  *    SKSTREAM_ERR_NOT_OPEN
549  *    SKSTREAM_ERR_CLOSED
550  *    SKSTREAM_ERR_UNSUPPORT_CONTENT
551  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
552  *    SKSTREAM_ERR_SYS_FDOPEN
553  */
554 int
555 skStreamGetLine(
556     skstream_t         *stream,
557     char               *out_buffer,
558     size_t              buf_size,
559     int                *line_count);
560 
561 
562 /**
563  *    Return a value indicating whether the stream is being used for
564  *    reading, writing, or appending.
565  */
566 skstream_mode_t
567 skStreamGetMode(
568     const skstream_t   *stream);
569 
570 
571 /**
572  *    For an open stream, returns the name of the paging program if it
573  *    is being used, or NULL if a pager is not in use.  For a stream
574  *    that is not yet open, returns the name of the paging program
575  *    which MAY be used, or NULL if paging has not been requested.
576  */
577 const char *
578 skStreamGetPager(
579     const skstream_t   *stream);
580 
581 
582 /**
583  *    Return the pathname to which 'stream' has been bound, or NULL if
584  *    the stream is unbound.
585  */
586 const char *
587 skStreamGetPathname(
588     const skstream_t   *stream);
589 
590 
591 /**
592  *    Return the number of SiLK Flow records that have been processed
593  *    by 'stream' since is was opened.  This will be the number of
594  *    records in the file, unless the file was opened for append, in
595  *    which case it is the number of records appeneded.
596  *
597  *    A return value of ((uint64_t)(-1)) indicates that 'stream' does
598  *    not contain SiLK Flow records.
599  */
600 uint64_t
601 skStreamGetRecordCount(
602     const skstream_t   *stream);
603 
604 
605 /**
606  *    Return the SiLK file header for the stream.  Returns NULL if the
607  *    stream is not a SiLK stream.
608  */
609 sk_file_header_t *
610 skStreamGetSilkHeader(
611     const skstream_t   *stream);
612 
613 
614 /**
615  *    Return 1 if 'stream' supports IPv6 addresses, 0 otherwise.
616  */
617 int
618 skStreamGetSupportsIPv6(
619     const skstream_t   *stream);
620 
621 
622 /**
623  *    Return the maximum possible file size that would be created if
624  *    the file were to be flushed.
625  */
626 off_t
627 skStreamGetUpperBound(
628     skstream_t         *stream);
629 
630 
631 /**
632  *    Initialize global state used by the stream library.  For
633  *    example, check environment variables used by the stream library.
634  *
635  *    Application writers do not need to call this function as it is
636  *    called by skAppRegister().
637  */
638 int
639 skStreamInitialize(
640     void);
641 
642 
643 /**
644  *    Return a non-zero value if 'stream' is a seekable stream; return
645  *    0 otherwise.
646  */
647 int
648 skStreamIsSeekable(
649     const skstream_t   *stream);
650 
651 
652 /**
653  *    Return a non-zero value if 'stream' is bound to the standard
654  *    output.
655  */
656 int
657 skStreamIsStdout(
658     const skstream_t   *stream);
659 
660 
661 /**
662  *    Fill 'buffer' with the error message that corresponds to the
663  *    stream error code 'errcode'.  The caller must provide the length
664  *    of 'buffer' in 'buffer_len'.  The 'stream' object may be NULL;
665  *    if non-NULL, it can provide additional context for the error
666  *    message.  Return the value returned by the printf()-like
667  *    function used to format the message.
668  *
669  *    See also skStreamGetLastReturnValue(), skStreamPrintLastErr().
670  */
671 int
672 skStreamLastErrMessage(
673     const skstream_t   *stream,
674     ssize_t             errcode,
675     char               *buffer,
676     size_t              buffer_len);
677 
678 
679 /**
680  *    Block until the stream has a lock on the file associated with
681  *    'stream'.  Return SKSTREAM_OK on success or if the stream is
682  *    not-seekable, or one of the following error codes:
683  *
684  *    SKSTREAM_ERR_NULL_ARGUMENT
685  *    SKSTREAM_ERR_NOT_OPEN
686  *    SKSTREAM_ERR_CLOSED
687  *    SKSTREAM_ERR_RLOCK
688  *    SKSTREAM_ERR_WLOCK
689  */
690 int
691 skStreamLockFile(
692     skstream_t         *stream);
693 
694 
695 /**
696  *    Create any directories that would be required before opening the
697  *    file bound to 'stream'.
698  */
699 int
700 skStreamMakeDirectory(
701     skstream_t         *stream);
702 
703 
704 /**
705  *    Like skStreamOpen(), open the file associated with 'stream'.
706  *    However, this function passes the pathname associated with
707  *    'stream' to the mkstemp() library call to create a temporary
708  *    file, so the pathname associated with the file should be
709  *    suitable for mkstemp()---that is, it should end in 6 or more 'X'
710  *    characters.  Return SKSTREAM_OK on success, or one of the
711  *    following error codes:
712  *
713  *    SKSTREAM_ERR_NULL_ARGUMENT
714  *    SKSTREAM_ERR_NOT_BOUND
715  *    SKSTREAM_ERR_PREV_OPEN
716  *    SKSTREAM_ERR_CLOSED
717  *    SKSTREAM_ERR_ALLOC
718  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
719  *    SKSTREAM_ERR_SYS_MKSTEMP
720  */
721 int
722 skStreamMakeTemp(
723     skstream_t         *stream);
724 
725 
726 /**
727  *    Open the file associated with 'stream'.  Note that
728  *    skStreamOpen() must be called even when the stream has been
729  *    bound to a standard stream, i.e., "stdin", "stdout", or
730  *    "stderr".  For an output stream, the target file must not
731  *    previously exist, unless it is a FIFO or a character special
732  *    file, i.e., "/dev/null".
733  *
734  *    Return SKSTREAM_OK on success, or one of the following error
735  *    codes:
736  *
737  *    SKSTREAM_ERR_NULL_ARGUMENT
738  *    SKSTREAM_ERR_NOT_BOUND
739  *    SKSTREAM_ERR_PREV_OPEN
740  *    SKSTREAM_ERR_CLOSED
741  *    SKSTREAM_ERR_ALLOC
742  *    SKSTREAM_ERR_SYS_OPEN
743  *    SKSTREAM_ERR_FILE_EXISTS
744  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
745  *    SKSTREAM_ERR_UNSUPPORT_COMPRESS
746  */
747 int
748 skStreamOpen(
749     skstream_t         *stream);
750 
751 
752 /**
753  *    A convenience function for creating a stream that processes SiLK
754  *    flow records.  This function will create a stream at the
755  *    location specified by 'stream', set its mode to
756  *    'read_write_append', bind it to 'pathname', and open it.  If the
757  *    'read_write_append' mode is SK_IO_READ or SK_IO_APPEND, this
758  *    function will also read the file's header.
759  *
760  *    Returns SKSTREAM_OK on success.
761  *
762  *    If there is an error opening the stream, 'stream' will be left
763  *    in a partially allocated/opened state.  The caller should invoke
764  *    skStreamDestroy() to destroy the stream.
765  */
766 int
767 skStreamOpenSilkFlow(
768     skstream_t        **stream,
769     const char         *pathname,
770     skstream_mode_t     read_write_append);
771 
772 
773 /**
774  *    Allow 'stream' to display its output a screenful at a time by
775  *    invoking the program named by 'pager' and pass the output of
776  *    'stream' through it.  This function requires that 'stream' be an
777  *    SK_IO_WRITE stream that has a content type of SK_CONTENT_TEXT.
778  *
779  *    'stream' may be open or not-yet-open; if open, no data can have
780  *    been written to 'stream' yet.  If 'stream' is already open, this
781  *    function will invoke the pager; otherwise, the pager will be
782  *    invoked on the first attempt to skStreamPrint() to 'stream'.
783  *
784  *    Return SKSTREAM_OK on success, or one of the following error
785  *    codes:
786  *
787  *    SKSTREAM_ERR_NULL_ARGUMENT
788  *    SKSTREAM_ERR_CLOSED
789  *    SKSTREAM_ERR_ATTRIBUTE_FIXED
790  *    SKSTREAM_ERR_ALLOC
791  *    SKSTREAM_ERR_SYS_FDOPEN
792  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
793  *    SKSTREAM_ERR_UNSUPPORT_CONTENT
794  */
795 int
796 skStreamPageOutput(
797     skstream_t         *stream,
798     const char         *pager);
799 
800 
801 /**
802  *    Perform printf()-style formatting and write the result to
803  *    'stream'.  On the first call to this funtion for 'stream', the
804  *    pager for 'stream' will be invoked if the paging program was set
805  *    and output would be to a terminal.  This function requires that
806  *    'stream' be an SK_IO_WRITE stream that has a content type of
807  *    SK_CONTENT_TEXT.
808  *
809  *    Return SKSTREAM_OK on success, or one of the following error
810  *    codes:
811  *
812  *    SKSTREAM_ERR_NULL_ARGUMENT
813  *    SKSTREAM_ERR_CLOSED
814  *    SKSTREAM_ERR_NOT_OPEN
815  *    SKSTREAM_ERR_WRITE
816  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
817  *    SKSTREAM_ERR_UNSUPPORT_CONTENT
818  */
819 #ifdef TEST_PRINTF_FORMATS
820 #define skStreamPrint(stream, ...) printf(__VA_ARGS__)
821 #else
822 int
823 skStreamPrint(
824     skstream_t         *stream,
825     const char         *format,
826     ...)
827     SK_CHECK_PRINTF(2, 3);
828 #endif
829 
830 
831 /**
832  *    Print, using the function pointed to by err_fn, a description of
833  *    the last error that occured on 'stream', where 'err_code' is the
834  *    return code that a function returned.  'stream' may be NULL.
835  *
836  *    See also skStreamGetLastReturnValue(), skStreamLastErrMessage().
837  */
838 void
839 skStreamPrintLastErr(
840     const skstream_t   *stream,
841     ssize_t             err_code,
842     sk_msg_fn_t         err_fn);
843 
844 
845 /**
846  *    Attempt to read 'count' bytes from 'stream', putting the data
847  *    into 'buf'.  Return the number of bytes actually read, 0 for end
848  *    of file, and -1 on error.
849  *
850  *    When 'buf' is NULL, 'count' bytes are "read" but the data is
851  *    dropped.  The function returns the number of bytes "read", or -1
852  *    for error.
853  *
854  *    The function will use a buffered reader, gzread(), or raw read()
855  *    as appropriate.  For a raw read(), the function continues to call
856  *    read() until it has read 'count' bytes or read() returns 0 or
857  *    -1.
858  *
859  *    When the function returns -1, there is no way to determine how
860  *    many bytes were read prior to the error.
861  */
862 ssize_t
863 skStreamRead(
864     skstream_t         *stream,
865     void               *buf,
866     size_t              count);
867 
868 
869 /**
870  *    Read a single SiLK Flow record from 'stream'.
871  */
872 int
873 skStreamReadRecord(
874     skstream_t         *stream,
875     rwRec              *rec);
876 
877 
878 /**
879  *    Attempt to read the SiLK file header from 'stream', putting the
880  *    data into 'hdr'.  This function requires that 'stream' contain
881  *    SK_CONTENT_SILK or SK_CONTENT_SILK_FLOW and that it's mode be
882  *    either SK_IO_READ or SK_IO_APPEND.
883  *
884  *    An attempt to read the header multiple times will result in
885  *    SKSTREAM_ERR_PREV_DATA.
886  *
887  *    When 'stream' is open for SK_IO_APPEND, this function will seek
888  *    to the end of the file after reading the header.
889  *
890  *    Return SKSTREAM_OK on success, or one of the following error
891  *    codes:
892  *
893  *    SKSTREAM_ERR_NULL_ARGUMENT
894  *    SKSTREAM_ERR_CLOSED
895  *    SKSTREAM_ERR_NOT_OPEN
896  *    SKSTREAM_ERR_READ
897  *    SKSTREAM_ERR_ALLOC
898  *    SKSTREAM_ERR_PREV_DATA
899  *    SKSTREAM_ERR_BAD_MAGIC
900  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
901  *    SKSTREAM_ERR_UNSUPPORT_CONTENT
902  */
903 int
904 skStreamReadSilkHeader(
905     skstream_t         *stream,
906     sk_file_header_t  **hdr);
907 
908 
909 /**
910  *    Attempt to read the first 8 bytes of 'stream'.  (Eight bytes is
911  *    the minimum header size used by all versions of SiLK.)
912  */
913 int
914 skStreamReadSilkHeaderStart(
915     skstream_t         *stream);
916 
917 
918 /**
919  *    Attempt to read all (remaining) data in 'stream', and return
920  *    that content.  Set 'length' to the number of bytes of data from
921  *    from the stream.
922  *
923  *    The caller is responsible for calling free() on the value
924  *    returned from this function.
925  *
926  *    An extra NUL byte is added to the data read from the stream, but
927  *    that byte is not included in 'length'.  (This guarantees that
928  *    textual files are NUL terminated.)
929  *
930  *    On error, NULL is returned. length is indeterminate, and any
931  *    data read from the stream is lost.  You may call
932  *    skStreamPrintLastErr() with an 'err_code' of -1 to find the
933  *    exact error.
934  */
935 void *
936 skStreamReadToEndOfFile(
937     skstream_t         *stream,
938     ssize_t            *length);
939 
940 
941 /**
942  *    Set the comment string for a textual input file to
943  *    'comment_start'.  This function requires that 'stream' be an
944  *    SK_IO_READ stream that contains SK_CONTENT_TEXT.  Return
945  *    SKSTREAM_OK on success, or one of the following error codes:
946  *
947  *    SKSTREAM_ERR_NULL_ARGUMENT
948  *    SKSTREAM_ERR_ALLOC
949  *    SKSTREAM_ERR_UNSUPPORT_CONTENT
950  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
951  */
952 int
953 skStreamSetCommentStart(
954     skstream_t         *stream,
955     const char         *comment_start);
956 
957 
958 /**
959  *    Set the compression method on 'stream' to 'comp_method'.
960  */
961 #define skStreamSetCompressionMethod(stream, comp_method)               \
962     (skHeaderSetCompressionMethod(skStreamGetSilkHeader(stream),        \
963                                   (comp_method)))
964 
965 
966 /**
967  *    Inform 'read_stream' that all records it reads must be written
968  *    to 'write_stream'.  'read_stream' and 'write_stream' must both
969  *    contain SiLK Flow records.  This function must be called before
970  *    data is read from the 'read_stream'.
971  */
972 int
973 skStreamSetCopyInput(
974     skstream_t         *read_stream,
975     skstream_t         *write_stream);
976 
977 
978 /**
979  *    Specify how 'stream' handles IPv6 records, or IPv4 records in a
980  *    mixed IPv4/IPv6 environment.  The 'stream' must represent a SiLK
981  *    stream.
982  */
983 int
984 skStreamSetIPv6Policy(
985     skstream_t         *stream,
986     sk_ipv6policy_t     policy);
987 
988 
989 /**
990  *    Do not use buffering on this stream.  This must be called prior
991  *    to opening the stream.
992  */
993 int
994 skStreamSetUnbuffered(
995     skstream_t         *stream);
996 
997 
998 /**
999  *    Attempt to move forward in 'stream' by 'skip_count' records.  If
1000  *    'records_skipped' is not NULL, the number of records skipped
1001  *    will be recorded in that location.
1002  */
1003 int
1004 skStreamSkipRecords(
1005     skstream_t         *stream,
1006     size_t              skip_count,
1007     size_t             *records_skipped);
1008 
1009 
1010 /**
1011  *    Destroy any global state held by the stream library.
1012  *
1013  *    Application writers do not need to call this function as it is
1014  *    called by skAppUnregister().
1015  */
1016 void
1017 skStreamTeardown(
1018     void);
1019 
1020 
1021 /**
1022  *    Return the current byte offset into the underlying stream.
1023  *    Return -1 if the stream is unopend, is unseekable, or if another
1024  *    error occurs.
1025  */
1026 off_t
1027 skStreamTell(
1028     skstream_t         *stream);
1029 
1030 
1031 /**
1032  *    Set the length of the file bound to 'stream' to 'length'.
1033  *
1034  *    This function will call skStreamFlush() on the stream prior to
1035  *    setting its length.
1036  *
1037  *    The value of 'length' should be a value determined before any
1038  *    new data has been written to the file, or after a call to
1039  *    skStreamFlush() to ensure there is no unsaved data.
1040  *
1041  *    Return SKSTREAM_OK on success.  If 'stream' is not open for
1042  *    writing or appending, return SKSTREAM_ERR_UNSUPPORT_IOMODE.  If
1043  *    stream's content is SK_CONTENT_TEXT, return
1044  *    SKSTREAM_ERR_UNSUPPORT_CONTENT.  If 'stream' is not seekable,
1045  *    return SKSTREAM_ERR_NOT_SEEKABLE.  Return
1046  *    SKSTREAM_ERR_SYS_FTRUNCATE if the call to ftruncate() fails.
1047  *
1048  *    If the call to skStreamFlush() returns an error value, the
1049  *    ftruncate() call is still attempted, and the function will
1050  *    return SKSTREAM_ERR_SYS_FTRUNCATE if the ftruncate() call
1051  *    failed, or the error status from the skStreamFlush() call.  If
1052  *    skStreamFlush() fails, there may be unflushed buffers that the
1053  *    system will attempt to flush when the stream is destroyed,
1054  *    making the file's length different than 'length'.
1055  *
1056  *    In addition, the function may return:
1057  *
1058  *    SKSTREAM_ERR_NULL_ARGUMENT
1059  *    SKSTREAM_ERR_NOT_OPEN
1060  *    SKSTREAM_ERR_CLOSED
1061  */
1062 int
1063 skStreamTruncate(
1064     skstream_t         *stream,
1065     off_t               length);
1066 
1067 
1068 /**
1069  *    Closes the stream at 'stream', if open, and unbinds the stream
1070  *    from the filename.  If 'stream' is NULL, no action is taken and
1071  *    the function returns.  Return SKSTREAM_OK on success, or any of
1072  *    the error codes listed by skStreamClose().
1073  *
1074  *    Currently, a stream cannot be re-bound, so this function is of
1075  *    limited utility.
1076  */
1077 int
1078 skStreamUnbind(
1079     skstream_t         *stream);
1080 
1081 
1082 /**
1083  *    Attempt to write 'count' bytes from 'buf' to 'stream'.  Return
1084  *    the number of bytes actually written or -1 on error.
1085  *
1086  *    The function will use a buffered writer, gzwrite(), or raw
1087  *    write() as appropriate.  For a raw write(), the function
1088  *    continue to call write() until it has written 'count' bytes or
1089  *    write() returns -1.
1090  */
1091 ssize_t
1092 skStreamWrite(
1093     skstream_t         *stream,
1094     const void         *buf,
1095     size_t              count);
1096 
1097 
1098 /**
1099  *    Write the SiLK Flow record 'rec' to 'stream'.
1100  */
1101 int
1102 skStreamWriteRecord(
1103     skstream_t         *stream,
1104     const rwRec        *rec);
1105 
1106 
1107 /**
1108  *    Attempt to write 'hdr_size' bytes from 'buf' to 'stream', with
1109  *    the following caveat: the first eight bytes of 'hdr' will be
1110  *    modified to contain the SiLK magic file number, and the values
1111  *    that were specified in the calls to skStreamSetByteOrder(),
1112  *    skStreamSetSilkFormat(), skStreamSetSilkVersion(), and
1113  *    skStreamSetCompressionMethod().
1114  *
1115  *    If 'hdr' is shorter than eight bytes, return
1116  *    SKSTREAM_ERR_INVALID_INPUT.  If fewer than 'hdr_size' bytes were
1117  *    written, return SKSTREAM_ERR_WRITE.  This function requires that
1118  *    'stream' be an SK_IO_WRITE stream containing SK_CONTENT_SILK or
1119  *    SK_CONTENT_SILK_FLOW.
1120  *
1121  *    An attempt to write the header multiple times will result in
1122  *    SKSTREAM_ERR_PREV_DATA.
1123  *
1124  *    Return SKSTREAM_OK on success, or one of the following error
1125  *    codes:
1126  *
1127  *    SKSTREAM_ERR_NULL_ARGUMENT
1128  *    SKSTREAM_ERR_CLOSED
1129  *    SKSTREAM_ERR_NOT_OPEN
1130  *    SKSTREAM_ERR_INVALID_INPUT
1131  *    SKSTREAM_ERR_WRITE
1132  *    SKSTREAM_ERR_ALLOC
1133  *    SKSTREAM_ERR_PREV_DATA
1134  *    SKSTREAM_ERR_UNSUPPORT_IOMODE
1135  *    SKSTREAM_ERR_UNSUPPORT_CONTENT
1136  */
1137 int
1138 skStreamWriteSilkHeader(
1139     skstream_t         *stream);
1140 
1141 
1142 #ifdef __cplusplus
1143 }
1144 #endif
1145 #endif /* _SKSTREAM_H */
1146 
1147 /*
1148 ** Local Variables:
1149 ** mode:c
1150 ** indent-tabs-mode:nil
1151 ** c-basic-offset:4
1152 ** End:
1153 */
1154