/*
openisis - an open implementation of the CDS/ISIS database
Version 0.8.x (patchlevel see file Version)
Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
see README for more information
EOH */
#ifndef LIO_H
/*
$Id: lio.h,v 1.22 2003/05/29 18:02:54 kripke Exp $
I/O support for the openisis library.
Provides non-blocking, look-ahead network streams and other nice stuff.
*/
#include "luti.h"
#include "lll.h"
/* ************************************************************
time
*/
/* struct wrapper just for struct Tm *Time */
typedef struct Tm {
lll millis;
} Tm;
/**
set Tm to current time, return difference in millis
*/
extern int timeUpd ( Tm * );
/**
print generalized time yyyyMMddHHmmss + 0 byte to buffer
if Tm is 0, current time is used
if Tm.millis is 0, Tm is updated
return buffer, which must have 15 bytes
*/
extern char *timeGtf ( char *buf, Tm * );
/**
like timeAsc, but with additional 3 digits millis
return buffer, which must have 18 bytes
*/
extern char *timeGtfm ( char *buf, Tm * );
/**
nanosl
*/
extern void timeSleep ( Tm * );
/* ************************************************************
system files
*/
/**
system file is a non-negative 32bit int including status bits.
main status bits are LIO_IN and LIO_OUT,
which are set by open and cleared by close.
negative values are reserved for use by non-system based streams.
*/
#define LIO_WANT 0xfff00000 /* what we want: open flags */
#define LIO_FD 0x0000ffff /* what we get: system fd */
#define LIO_STAT 0x000f0000 /* how it's going: it's status */
/* status flags */
#define LIO_IN 0x00010000 /* support input */
#define LIO_OUT 0x00020000 /* support output */
#define LIO_INOUT 0x00030000 /* support both */
#define LIO_ISOPEN( file ) (LIO_INOUT & (file))
/* common requirements that are also used by non-system streams. */
#define LIO_RD 0x00100000 /* shall be opened for input */
#define LIO_WR 0x00200000 /* shall be opened for output */
#define LIO_RDWR 0x00300000 /* shall be opened for both */
#define LIO_SYNC 0x00400000 /* with WR: syncing output */
#define LIO_NBLK 0x00800000 /* non blocking IO (not used) */
/* system files only. */
#define LIO_CREAT 0x01000000 /* with WR: shall be created */
#define LIO_TRY 0x01000000 /* w/o WR: do not complain if open fails */
#define LIO_TRUNC 0x02000000 /* with WR: shall be truncated */
#define LIO_SEEK 0x04000000 /* random access (with WR: else append mode) */
#define LIO_SOCK 0x08000000 /* is a socket (support shutdown) */
/* locking */
#define LIO_TLOCK 0x10000000 /* try locking (EX with WR) */
#define LIO_WLOCK 0x20000000 /* lock waiting (EX with WR) */
#define LIO_FLOCK 0x30000000 /* any locking is set */
/** create a new fid based on name and flags.
name may be &i to use fd i, esp. for i=0,1 or 2.
@return non-negative file or some error code
*/
extern int lio_open ( const char *name, int flags );
extern int lio_close ( int *file, int flags );
extern int lio_size ( int file );
extern unsigned lio_time ( int file ); /* mtime sec */
extern int lio_in;
extern int lio_out;
extern int lio_err;
/*
Like the syscalls, this returns the number of bytes on success.
Unlike the syscalls, it returns 0 rather than an error
when no bytes are available after interrupt (EINTR)
or on non-blocking IO (EAGAIN); i.e. you may try later.
On error, a negative value is returned.
On errors that render the file unusable,
it is closed for input or output, resp.
These are most errors but EFAULT (bad buf)
and ESPIPE (which clears the SEEK bit).
For files that do not have the SEEK bit set,
EOF is considered such an error and -LERR_EOF is returned.
If you want to stream a disk file like 'tail -f', set the SEEK bit.
*/
extern int lio_read ( int *file, void *buf, unsigned count );
extern int lio_write ( int *file, const void *buf, unsigned count );
extern int lio_pread ( int *file, void *buf, unsigned count, int offset );
extern int lio_pwrite ( int *file, const void *buf, unsigned count, int offset );
extern int lio_seek ( int *file, int offset );
extern int lio_trunc ( int *file, int offset );
/**
open, sync or close a memory mapping
@param file pointer to open file handle to map.
if file is NULL, *map is unmapped (and set to NULL)
else if *map is NULL, length bytes are mapped
else *map is synced (flushed)
@param length number of bytes to map; if 0, size will be used
@return mapped length; if <= 0, *map is set to 0, else to memory region
*/
extern int lio_mmap ( int *file, void **map, int length );
/** slurp in a whole file at once.
@param buf points to buffer of size sz.
lio_slurp will allocate one, if *buf is NULL
@param sz maximum number of bytes to read
@param name of file to slurp
@param opt if != 0, do not complain on failure
@return number of bytes read or negative on error
*/
extern int lio_slurp ( char **buf, int sz, const char *name, int opt );
/* ************************************************************
streams
*/
/** an I/O buffered stream similar to stdio's FILE.
Unlike FILE with it's stupid ungetc,
it supports efficient scanning of the whole input buffer without
actually consuming it.
Also unlike at least Linux' glibc's stdio, access is not interlocked.
The buffer is typically used for input OR output.
However, for internal pipes, the same buffer is used from both ends.
High level access functions like printf operate directly on the buffer
and call the stream function on buffer underflow or overflow
(or explicit flush).
*/
typedef int lio_sfunc ( struct Ios *s, int op );
enum {
LIO_BUFSIZ = 8192
};
typedef struct Buf {
/* struct Buf *nxt; chain -- not used */
short fill; /* total #bytes in the buffer */
short done; /* #bytes done */
unsigned char c[LIO_BUFSIZ]; /* actual buffer may be longer */
} Buf;
/* fill - done is the number of available bytes */
#define LIO_BAVAIL( b ) ((b)->fill - (b)->done)
#define LIO_BINIT( b ) do { \
/*(b)->nxt = 0;*/ (b)->fill = 0; (b)->done = 0; \
} while (0)
#define LIO_BINITIALIZER { 0,0,"" }
typedef struct Ios {
lio_sfunc *func;
const char *name; /* stream's name */
int file; /* file "id" and flags as above */
int pos; /* logical position of buffer start within stream */
Buf b;
} Ios;
#define LIO_SISOPEN( s ) LIO_ISOPEN( (s)->file )
#define LIO_SAVAIL( s ) LIO_BAVAIL( &(s)->b )
#define LIO_SINIT( s, fun, nam, fil ) do { \
(s)->func = fun; (s)->name = nam; (s)->file = fil; \
(s)->pos = 0; \
LIO_BINIT( &(s)->b ); \
} while (0)
#define LIO_STDINIT( s, nam, fil ) LIO_SINIT( s, lio_stdio, nam, fil )
#define LIO_SINITIALIZER( fun, nam, fil ) { fun, nam, fil, 0, LIO_BINITIALIZER }
#define LIO_STDINITIALIZER( nam, fil ) LIO_SINITIALIZER( lio_stdio, nam, fil )
/** stream operations.
*/
enum {
LIO_SSIZE, /* tell the size of the stream structure */
LIO_SOPEN, /* initialize the structure */
LIO_SCLOSE, /* close */
LIO_SPURGE, /* kill the done bytes. return fill buffer size */
LIO_SFILL, /* try to refill the buffer (poll input). return # new bytes */
LIO_SFLUSH, /* try to flush the buffer. return # bytes written */
LIO_SPUSH /* push input stream: munge prefilled input */
};
/**
"abstract" base implementation of stream.
not very useful in itself, but used by derived impl.
*/
extern int ioStream ( Ios *s, int op );
/**
stream func based on system file to mimic stdio.
on LIO_SOPEN, the fid is set by lio_open based on name.
other ops used the correponding lio system call.
*/
extern int ioStdio ( Ios *s, int op );
#define LIO_OPEN( s ) (s)->func( (s), LIO_SOPEN )
#define LIO_CLOSE( s ) (s)->func( (s), LIO_SCLOSE )
#define LIO_FILL( s ) (s)->func( (s), LIO_SFILL )
#define LIO_FLUSH( s ) (s)->func( (s), LIO_SFLUSH )
/* ************************************************************
inter process communication
*/
extern CLockFunc *lio_lock;
#define LIO_LOCK() (NULL != lio_lock && lio_lock(OPENISIS_LOCK))
#define LIO_RELE() (NULL != lio_lock && lio_lock(OPENISIS_RELE))
#define LIO_WAIT( c ) (NULL != lio_lock && lio_lock(OPENISIS_WAIT \
| (OPENISIS_COND & (c))))
#define LIO_WAKE( c ) (NULL != lio_lock && lio_lock(OPENISIS_WAKE \
| (OPENISIS_COND & (c))))
#define LIO_H
#endif /* LIO_H */