/* ** Copyright (C) 2005-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ /* ** Functions to support binary output: opening binary SiLK files for ** writing or appending. ** */ #include "silk.h" RCSIDENT("$SiLK: rwio.c 7614 2007-06-21 20:25:10Z mthomas $"); #include "librw_priv.h" /* * status = _ioAssertModifiable(rwIOS); * * Return LIBRW_OK if the caller is still allowed to set aspects of * the rwIOStream 'rwIOS'; otherwise return the reason why rwIOS * cannot be modified. Only rwIOStreams that are creating new * output files which have not yet been opened may be modified. */ static int _ioAssertModifiable( const rwIOStruct_t *rwIOS) { if (rwIOS == NULL) { return LIBRW_ERR_NULL_ARGUMENT; } if (rwIOS->didHdrFlag) { return LIBRW_ERR_ATTRIBUTE_FIXED; } if (rwIOS->isOpenFlag) { return LIBRW_ERR_ATTRIBUTE_FIXED; } if (rwIOS->io_mode == SK_RWIO_CLOSED) { return LIBRW_ERR_STREAM_CLOSED; } if (rwIOS->io_mode != SK_RWIO_WRITE) { return LIBRW_ERR_ATTRIBUTE_FIXED; } return LIBRW_OK; } /* * status = _ioAssertOpen(rwIOS); * * Call this function on an rwIOStream which you expect to be open, * i.e., non-null and not-closed. It will return LIBRW_OK if the * rwIOStream is opened, or an error code explaining why the stream * is not considered open. * * A rwIOStream that has been opened and closed is neither open nor * unopened. */ static int _ioAssertOpen( const rwIOStruct_t *rwIOS) { if (rwIOS == NULL) { return LIBRW_ERR_NULL_ARGUMENT; } if (rwIOS->io_mode == SK_RWIO_CLOSED) { return LIBRW_ERR_STREAM_CLOSED; } if (rwIOS->isOpenFlag != 1) { return LIBRW_ERR_STREAM_NOT_OPEN; } return LIBRW_OK; } /* * status = _ioAssertNotOpen(rwIOS); * * Call this function on an rwIOStream which you expect to be * unopened---i.e., not yet open. It will return LIBRW_OK if the * rwIOStream is unopened, or an error code explaining why the * it is not unopened. * * A rwIOStream that has been opened and closed is neither open nor * unopened. */ static int _ioAssertNotOpen( const rwIOStruct_t *rwIOS) { if (rwIOS == NULL) { return LIBRW_ERR_NULL_ARGUMENT; } if (rwIOS->io_mode == SK_RWIO_CLOSED) { return LIBRW_ERR_STREAM_CLOSED; } if (rwIOS->isOpenFlag) { return LIBRW_ERR_STREAM_OPEN; } return LIBRW_OK; } /* * status = _ioAssertHeaderNotWritten(rwIOS); * * Call this function on an rwIOStream which you expect has not yet * had its header written. It will return LIBRW_OK if the header * has not been written, or an error code explaining why the header * is considered "written". */ static int _ioAssertHeaderNotWritten( const rwIOStruct_t *rwIOS) { if (rwIOS == NULL) { return LIBRW_ERR_NULL_ARGUMENT; } if (rwIOS->io_mode == SK_RWIO_CLOSED) { return LIBRW_ERR_STREAM_CLOSED; } if (rwIOS->io_mode != SK_RWIO_WRITE) { return LIBRW_ERR_UNSUPPORT_STREAM; } if (rwIOS->didHdrFlag == 1) { return LIBRW_ERR_ATTRIBUTE_FIXED; } return LIBRW_OK; } /* * status = _ioSetFileFormat(rwIOS, file_format); * * Set the output file format on 'rwIOS' to 'file_format'. */ static int _ioSetFileFormat( rwIOStruct_t *rwIOS, uint8_t file_format) { assert(rwIOS); assert(rwGetHeader(rwIOS)); ((genericHeader*)rwGetHeader(rwIOS))->type = file_format; return LIBRW_OK; } /* * status = _ioSetFileVersion(rwIOS, file_version); * * Set the version of the output file format on 'rwIOS' to * 'file_version'. */ static int _ioSetFileVersion( rwIOStruct_t *rwIOS, fileVersion_t file_version) { assert(rwIOS); assert(rwGetHeader(rwIOS)); ((genericHeader*)rwGetHeader(rwIOS))->version = file_version; return LIBRW_OK; } /* * status = _ioSetCompMethod(rwIOS, method); * * Set the compression method on 'rwIOS' to 'method'. */ static int _ioSetCompMethod( rwIOStruct_t *rwIOS, sk_compmethod_t method) { assert(rwIOS); assert(rwGetHeader(rwIOS)); ((genericHeader*)rwGetHeader(rwIOS))->compMethod = method; return LIBRW_OK; } /* * status = _ioSetSwapFlag(rwIOS); * * Set the swapFlag on rwIOS based on the byte order of the file * and the byte order of the machine. */ static int _ioSetSwapFlag( rwIOStruct_t *rwIOS) { assert(rwIOS); assert(rwGetHeader(rwIOS)); /* Do we swap the bytes on write? */ #if IS_LITTLE_ENDIAN rwIOS->swapFlag = rwGetIsBigEndian(rwIOS); #else rwIOS->swapFlag = !rwGetIsBigEndian(rwIOS); #endif return LIBRW_OK; } /* * status = _ioSetFileByteOrder(rwIOS, byte_order); * * Set the 'isBigEndian' flag on 'rwIOS' to so that the file will * have the designated 'byte_order'. */ static int _ioSetFileByteorder( rwIOStruct_t *rwIOS, silk_endian_t byte_order) { genericHeader *gHdr; assert(rwIOS); assert(rwGetHeader(rwIOS)); gHdr = (genericHeader*)rwGetHeader(rwIOS); switch (byte_order) { case SILK_ENDIAN_BIG: #if !IS_LITTLE_ENDIAN case SILK_ENDIAN_NATIVE: case SILK_ENDIAN_ANY: #endif gHdr->isBigEndian = 1; break; case SILK_ENDIAN_LITTLE: #if IS_LITTLE_ENDIAN case SILK_ENDIAN_NATIVE: case SILK_ENDIAN_ANY: #endif gHdr->isBigEndian = 0; break; } return _ioSetSwapFlag(rwIOS); } /* * is_compressed = _ioPathnameIsCompressed(pathname, io_mode); * * Return TRUE if 'pathname' should be considered a compressed file * for the given IO mode---that is, where the entire file is * compressed---or FALSE otherwise. * * Basically, returns TRUE when 'pathname' ends in ".gz" or when it * is open for reading and contains the substring ".gz."---assuming * the pathname has had a mkstemp() suffix added to it. In all * other cases, it returns FALSE. */ static int _ioPathnameIsCompressed( const char *pathname, rwio_mode_t read_write_append) { const char *gz; gz = strstr(pathname, ".gz"); if (gz != NULL) { switch (read_write_append) { case SK_RWIO_CLOSED: /* should never happen */ assert(read_write_append != SK_RWIO_CLOSED); abort(); case SK_RWIO_READ: case SK_RWIO_APPEND: if (gz[3] == '.') { return 1; } /* FALLTHROUGH */ case SK_RWIO_WRITE: if (gz[3] == '\0') { return 1; } } } return 0; } /* * filedesc = _ioPathnameIsFiledesc(pathname); * * If 'pathname' matches "\[[0-9]+\]"---i.e., digits surrounded by * a pair or brackets---return the number within the brackets, * otherwise, return -1. */ static int _ioPathnameIsFiledesc( const char *pathname) { int fildes; if (1 == sscanf(pathname, "[%d]", &fildes)) { return fildes; } return -1; } /* * is_valid = _ioCheckPathName(pathname, io_mode); * * Check that 'pathname' makes sense given the 'io_mode'. For * example, check that we aren't trying to read from stdout, or * write to stdin, or append to any standard stream. * * Return LIBRW_OK if 'pathname' passes all the checks; otherwise * return an error code explaining the problem. */ static int _ioCheckPathName( const char *pathname, rwio_mode_t read_write_append) { int rv = LIBRW_OK; /* check name */ if (pathname == NULL || *pathname == '\0') { rv = LIBRW_ERR_NULL_ARGUMENT; goto END; } /* If pathname is "stdin" or "stdout", make certain stream is not * a terminal */ if (0 == strcmp(pathname, "stdin")) { switch (read_write_append) { case SK_RWIO_CLOSED: rv = LIBRW_ERR_STREAM_CLOSED; break; case SK_RWIO_READ: if (FILEIsATty(stdin)) { rv = LIBRW_ERR_STREAM_TTY; } break; case SK_RWIO_WRITE: case SK_RWIO_APPEND: /* cannot write or append to stdin */ rv = LIBRW_ERR_UNSUPPORT_STREAM; break; } goto END; } if (0 == strcmp(pathname, "stdout")) { switch (read_write_append) { case SK_RWIO_CLOSED: rv = LIBRW_ERR_STREAM_CLOSED; break; case SK_RWIO_READ: case SK_RWIO_APPEND: /* cannot read from or append to stdout */ rv = LIBRW_ERR_UNSUPPORT_STREAM; break; case SK_RWIO_WRITE: if (FILEIsATty(stdout)) { /* Ugh! Hack alert!! Ignore result of this test * under MPI, since it is always TRUE. */ rv = LIBRW_ERR_STREAM_TTY; } break; } goto END; } if (read_write_append == SK_RWIO_APPEND) { if (_ioPathnameIsCompressed(pathname, read_write_append)) { /* Cannot append to a compressed stream */ rv = LIBRW_ERR_UNSUPPORT_COMPRESS; goto END; } if (isFIFO(pathname)) { /* Cannot append to a FIFO */ rv = LIBRW_ERR_UNSUPPORT_STREAM; goto END; } } END: return rv; } /* * status = _ioCreateIOBuffer(rwIOS); * * Create the skIOBuf that the 'rwIOS' will read-from/write-to, and * bind it to the file descriptor or gzfile. Return LIBRW_OK on * success, or an error code on failure. */ static int _ioCreateIOBuffer( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; assert(rwIOS); assert(rwIOS->isOpenFlag); /* create the iobuf */ switch (rwIOS->io_mode) { case SK_RWIO_CLOSED: rv = LIBRW_ERR_STREAM_CLOSED; goto END; case SK_RWIO_READ: /* create the buffered reader */ rwIOS->iobuf = skIOBufCreateReader(); break; case SK_RWIO_WRITE: case SK_RWIO_APPEND: rwIOS->iobuf = skIOBufCreateWriter(); break; } if (rwIOS->iobuf == NULL) { rv = LIBRW_ERR_ALLOC; goto END; } /* set the record size */ if (skIOBufSetRecordSize(rwIOS->iobuf, rwIOS->recLen) == -1) { rwIOS->errobj.str = skIOBufStrError(rwIOS->iobuf); rv = LIBRW_ERR_IOBUF; goto END; } /* bind it to the file descriptor or gzfile */ #ifdef HAVE_ZLIB_H if (rwIOS->gz) { if (skIOBufBindGzip(rwIOS->iobuf, rwIOS->gz,rwGetFileCompMethod(rwIOS)) == -1) { rwIOS->errobj.str = skIOBufStrError(rwIOS->iobuf); rv = LIBRW_ERR_IOBUF; } goto END; } #endif if (skIOBufBind(rwIOS->iobuf, rwIOS->_fd, rwGetFileCompMethod(rwIOS)) == -1) { rwIOS->errobj.str = skIOBufStrError(rwIOS->iobuf); rv = LIBRW_ERR_IOBUF; } END: return rv; } /* * status = _ioOpenRead(rwIOS); * * Opens the file named in 'rwIOS' for reading. Returns LIBRW_OK * for success, or an error code for failure. */ static int _ioOpenRead( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; assert(rwIOS); assert(rwGetFileName(rwIOS)); if (0 == strcmp(rwGetFileName(rwIOS), "stdin")) { rwIOS->_fd = STDIN_FILENO; } else { /* regular file or named pipe */ rwIOS->_fd = open(rwGetFileName(rwIOS), O_RDONLY); if (rwIOS->_fd == -1) { rwIOS->errnum = errno; rv = LIBRW_ERR_OPEN; goto END; } /* handle compression */ if (_ioPathnameIsCompressed(rwGetFileName(rwIOS), rwIOS->io_mode)) { #ifdef HAVE_ZLIB_H rwIOS->gz = gzdopen(rwIOS->_fd, "rb"); if (rwIOS->gz == NULL) { rv = LIBRW_ERR_ALLOC; goto END; } #else /* compression not supported */ rv = LIBRW_ERR_UNSUPPORT_COMPRESS; goto END; #endif /* HAVE_ZLIB_H */ } } END: if (rv == LIBRW_OK) { rwIOS->isOpenFlag = 1; } return rv; } /* * status = _ioOpenAppend(rwIOS); * * Opens the file named in 'rwIOS' for appending. Returns LIBRW_OK * for success, or an error code for failure. */ static int _ioOpenAppend( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; int flags = O_RDWR | O_APPEND; assert(rwIOS); assert(rwGetFileName(rwIOS)); /* Open file for read and write; position at start. */ rwIOS->_fd = open(rwGetFileName(rwIOS), flags, 0); if (rwIOS->_fd == -1) { rwIOS->errnum = errno; rv = LIBRW_ERR_OPEN; goto END; } if (-1 == lseek(rwIOS->_fd, 0, SEEK_SET)) { rwIOS->errnum = errno; rv = LIBRW_ERR_FSEEK; goto END; } END: if (rv == LIBRW_OK) { rwIOS->isOpenFlag = 1; } return rv; } /* * status = _ioOpenWrite(rwIOS); * * Opens the file named in 'rwIOS' for writing. Returns LIBRW_OK * for success, or an error code for failure. */ static int _ioOpenWrite( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; int fildes; assert(rwIOS); assert(rwGetFileName(rwIOS)); if (0 == strcmp(rwGetFileName(rwIOS), "stdout")) { rwIOS->_fd = STDOUT_FILENO; } else if ((fildes = _ioPathnameIsFiledesc(rwGetFileName(rwIOS))) != -1) { /* Handle "[%d]": Store the descriptor */ rwIOS->_fd = fildes; } else { /* open a new regular file, /dev/null, or a FIFO */ int mode, flags; /* standard mod of 0666 */ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* first, assume we're opening a file that does not exist */ flags = O_WRONLY | O_CREAT | O_EXCL; rwIOS->_fd = open(rwGetFileName(rwIOS), flags, mode); if (rwIOS->_fd == -1) { rwIOS->errnum = errno; if (rwIOS->errnum == EEXIST) { /* file exists. If it is "/dev/null" or a FIFO, try * again with more simple flags */ if ((0 == strcmp(rwGetFileName(rwIOS), "/dev/null")) || isFIFO(rwGetFileName(rwIOS))) { flags = O_WRONLY; rwIOS->_fd = open(rwGetFileName(rwIOS), flags, mode); rwIOS->errnum = errno; } } /* if we (still) have an error, return */ if (rwIOS->_fd == -1) { /* we set errnum above */ rv = LIBRW_ERR_WRITE_FILE_EXISTS; goto END; } } /* handle compressed files */ if (_ioPathnameIsCompressed(rwGetFileName(rwIOS), rwIOS->io_mode)) { #ifdef HAVE_ZLIB_H rwIOS->gz = gzdopen(rwIOS->_fd, "wb"); if (rwIOS->gz == NULL) { rv = LIBRW_ERR_ALLOC; goto END; } #else /* compression not supported */ rv = LIBRW_ERR_UNSUPPORT_COMPRESS; goto END; #endif /* HAVE_ZLIB_H */ } } END: if (rv == LIBRW_OK) { rwIOS->isOpenFlag = 1; } return rv; } /* * status = _ioPrepareRead(rwIOS); * * Read the rwIO stream's header. This function reads the generic * header, then calls the appropriate function to read the * format-specific information from the file. Returns LIBRW_OK on * sucess, or an error code otherwise. * * The format-specific function called by this function will set * the following function pointers: 'rwUnpackFn', 'rwPackFn', * 'rwSwapFn', 'writeHdrFn'. * * When this function returns, the rwIOS should be positioned at * the first record to be read; this function will also be called * when appending to a file; in that case, the rwIOS will be * positioned at the end of the file, ready to write the first * record. */ static int _ioPrepareRead( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; genericHeader *gHdr; ssize_t bytes; assert(rwIOS); assert(rwGetHeader(rwIOS)); gHdr = (genericHeader*)rwGetHeader(rwIOS); { /* read header */ bytes = _ioRead(rwIOS, gHdr, sizeof(genericHeader)); if (bytes < (ssize_t)sizeof(genericHeader)) { if (bytes == -1) { /* read error */ rwIOS->errnum = errno; rv = LIBRW_ERR_READ; } else { /* short read */ rv = LIBRW_ERR_READ_EOF; } goto END; } } /* verify header is RW file */ if (CHECKMAGIC(gHdr)) { rv = LIBRW_ERR_BAD_MAGIC; goto END; } /* swap bytes? */ rv = _ioSetSwapFlag(rwIOS); /* handle specific type */ switch(gHdr->type) { case FT_RWAUGMENTED: rv = _augmentedioPrepareRead(rwIOS); break; case FT_RWAUGROUTING: rv = _augroutingioPrepareRead(rwIOS); break; case FT_RWAUGWEB: rv = _augwebioPrepareRead(rwIOS); break; case FT_RWAUGSNMPOUT: rv = _augsnmpoutioPrepareRead(rwIOS); break; case FT_RWFILTER: rv = _filterioPrepareRead(rwIOS); break; case FT_RWGENERIC: rv = _genericioPrepareRead(rwIOS); break; case FT_RWNOTROUTED: rv = _notroutedioPrepareRead(rwIOS); break; case FT_RWROUTED: rv = _routedioPrepareRead(rwIOS); break; case FT_RWSPLIT: rv = _splitioPrepareRead(rwIOS); break; case FT_RWWWW: rv = _wwwioPrepareRead(rwIOS); break; default: rv = LIBRW_ERR_UNSUPPORT_TYPE; break; } if (rv) { goto END; } if (rwIOS->io_mode == SK_RWIO_APPEND) { /* now that we've read the header, go to the end of the * file */ if (-1 == lseek(rwIOS->_fd, 0, SEEK_END)) { rwIOS->errnum = errno; rv = LIBRW_ERR_FSEEK; goto END; } } /* create the buffered reader (or writer if appending) */ rv = _ioCreateIOBuffer(rwIOS); if (rv) { goto END; } /* we've handled the header */ rwIOS->didHdrFlag = 1; END: return rv; } /* * status = _ioWriteHdr(rwIOS, &rwrec); * * Call the function on the 'rwIOS' that will write the file's * header to the rwIO stream. Return LIBRW_OK on success, or an * error code otherwise. * * The 'rwrec' is NULL or a pointer to the first record in the * file. Some file formats need this in order to finish * initializing the header. This function will not write the * record to disk; use rwWrite() to do that. * * When this function returns, the rwIOS will be positioned to * write the first record. */ static int _ioWriteHdr( rwIOStruct_t *rwIOS, const rwRec *rwrec) { int rv; rv = _ioAssertHeaderNotWritten(rwIOS); if (rv) { goto END; } rv = _ioAssertOpen(rwIOS); if (rv) { goto END; } rwIOS->didHdrFlag = 1; /* only print the header if this is not an MPI stream */ if ( !rwIOS->mpiFlag) { rv = rwIOS->writeHdrFn(rwIOS, rwrec); if (rv) { goto END; } } /* create the buffered writer */ rv = _ioCreateIOBuffer(rwIOS); if (rv) { goto END; } END: return rv; } /* * status = _ioPrepareWrite(rwIOS); * * Create---but do not write---the header that is specific to the * file format that 'rwIOS' represents. * * The format-specific function called by this function will set * the following function pointers: 'rwUnpackFn', 'rwPackFn', * 'rwSwapFn', 'writeHdrFn'. * * Return LIBRW_OK on success, or an error code otherwise. */ static int _ioPrepareWrite( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; /* Verify type and version match */ switch (rwGetFileType(rwIOS)) { case FT_RWAUGMENTED: rv = _augmentedioPrepareWrite(rwIOS); break; case FT_RWAUGROUTING: rv = _augroutingioPrepareWrite(rwIOS); break; case FT_RWAUGWEB: rv = _augwebioPrepareWrite(rwIOS); break; case FT_RWAUGSNMPOUT: rv = _augsnmpoutioPrepareWrite(rwIOS); break; case FT_RWFILTER: rv = _filterioPrepareWrite(rwIOS); break; case FT_RWGENERIC: rv = _genericioPrepareWrite(rwIOS); break; case FT_RWNOTROUTED: rv = _notroutedioPrepareWrite(rwIOS); break; case FT_RWROUTED: rv = _routedioPrepareWrite(rwIOS); break; case FT_RWSPLIT: rv = _splitioPrepareWrite(rwIOS); break; case FT_RWWWW: rv = _wwwioPrepareWrite(rwIOS); break; default: rv = LIBRW_ERR_UNSUPPORT_TYPE; break; } if (rv) { goto END; } END: return rv; } ssize_t _ioRead( rwIOStruct_t *rwIOS, void *buf, size_t count) { ssize_t s; assert(rwIOS); assert(rwIOS->_fd != -1); assert(rwIOS->io_mode == SK_RWIO_READ || rwIOS->io_mode == SK_RWIO_APPEND); assert(buf); #ifdef HAVE_ZLIB_H if (rwIOS->gz != NULL) { s = gzread(rwIOS->gz, buf, (unsigned)count); } else #endif { s = read(rwIOS->_fd, buf, count); } return s; } /* Read a record into 'buf'. Works on cluster or non-cluster. See * librw_priv.h for details. */ static int _ioReadRec(rwIOStruct *rwIOS, uint8_t *ar) { ssize_t count; if (rwIOS->eofFlag) { return LIBRW_ERR_READ_EOF; } count = skIOBufRead(rwIOS->iobuf, ar, rwIOS->recLen); if (count != (ssize_t)rwIOS->recLen) { /* EOF or error */ rwIOS->eofFlag = 1; if (count == 0) { /* 0 means clean record boundary; simple EOF */ return LIBRW_ERR_READ_EOF; } if (count == -1) { /* error */ rwIOS->errnum = errno; return LIBRW_ERR_READ; } /* short read */ skAppPrintErr("Short read (%lu/%lu bytes) on %s", (unsigned long)count, (unsigned long)rwIOS->recLen, rwIOS->fPath); return LIBRW_ERR_READ; } ++rwIOS->recCount; return LIBRW_OK; } int rwioReadRecord( rwIOStruct_t *rwIOS, rwGenericRec_V3 *rwrec) { uint8_t ar[SK_MAX_RECORD_SIZE]; int rv; rv = _ioReadRec(rwIOS, ar); if (rv) { goto END; } /* clear the record */ memset(rwrec, 0, sizeof(rwGenericRec_V3)); /* put array to native byte order and convert to an rwRec */ if (rwIOS->swapFlag) { (*rwIOS->rwSwapFn)(ar); } rwIOS->rwUnpackFn(rwIOS, rwrec, ar); /* Write to the all-dest stream */ if (rwIOS->copyInputFD) { rwWrite(rwIOS->copyInputFD, rwrec); } END: return rv; } int rwioSkipRecords( rwIOStruct_t *rwIOS, size_t skip_count) { #define SKIP_BLOCK_SIZE 1024 uint8_t ar[SK_MAX_RECORD_SIZE * SKIP_BLOCK_SIZE]; ssize_t bytes; size_t rec_count; if (rwIOS->eofFlag) { return LIBRW_ERR_READ_EOF; } while (skip_count > 0) { /* can only read the number of records our buffer allows */ if (skip_count > SKIP_BLOCK_SIZE) { rec_count = SKIP_BLOCK_SIZE; } else { rec_count = skip_count; } /* read the bytes and check for error or short reads */ bytes = skIOBufRead(rwIOS->iobuf, ar, (rwIOS->recLen * rec_count)); if (bytes != (ssize_t)(rwIOS->recLen * rec_count)) { /* Either error or an incomplete read--assume end of file */ rwIOS->eofFlag = 1; if (bytes == -1) { /* error */ rwIOS->errnum = errno; return LIBRW_ERR_READ; } } /* compute the number of records we actually read, update * counters, and check for any partially read records. */ rec_count = (bytes / rwIOS->recLen); rwIOS->recCount += rec_count; skip_count -= rec_count; bytes -= rec_count * rwIOS->recLen; if (bytes != 0) { /* short read */ skAppPrintErr("Short read (%lu/%lu bytes) on %s", (unsigned long)bytes, (unsigned long)rwIOS->recLen, rwIOS->fPath); return LIBRW_ERR_READ; } if (rwIOS->eofFlag) { return LIBRW_ERR_READ_EOF; } } return LIBRW_OK; } int rwioWriteRecord( rwIOStruct_t *rwIOS, const rwGenericRec_V3 *rwrec) { int rv = LIBRW_OK; /* return value */ uint8_t ar[SK_MAX_RECORD_SIZE]; if (!rwIOS->didHdrFlag) { /* write the header */ rv = _ioWriteHdr(rwIOS, rwrec); if (rv) { return rv; } } /* Convert the record into a byte array */ rv = rwIOS->rwPackFn(rwIOS, rwrec, ar); if (rv != LIBRW_OK) { rwIOS->errobj.rec = rwrec; return rv; } /* swap if required */ if (rwIOS->swapFlag) { (*rwIOS->rwSwapFn)(ar); } /* write the record */ if (skIOBufWrite(rwIOS->iobuf, ar, rwIOS->recLen) == (ssize_t)rwIOS->recLen) { ++rwIOS->recCount; return LIBRW_OK; } rwIOS->errobj.str = skIOBufStrError(rwIOS->iobuf); return LIBRW_ERR_WRITE; } ssize_t _ioWrite( rwIOStruct_t *rwIOS, const void *buf, size_t count) { ssize_t s; assert(rwIOS); assert(rwIOS->_fd != -1); assert(rwIOS->io_mode == SK_RWIO_WRITE || rwIOS->io_mode ==SK_RWIO_APPEND); assert(buf); #ifdef HAVE_ZLIB_H if (rwIOS->gz != NULL) { s = gzwrite(rwIOS->gz, buf, (unsigned)count); } else #endif { s = write(rwIOS->_fd, buf, count); } return s; } #if 0 ssize_t _ioWriteBuf( rwIOStruct_t *rwIOS, const void *buf, size_t count) { ssize_t s; assert(rwIOS); assert(rwIOS->_fd != -1); assert(rwIOS->io_mode == SK_RWIO_WRITE || rwIOS->io_mode ==SK_RWIO_APPEND); assert(buf); if ( !rwIOS->iobuf) { return _ioWrite(rwIOS, buf, count); } return skIOBufWrite(rwIOS->iobuf, buf, count); } #endif /* read or write the header's padding */ int _ioHandleHeaderPadding( rwIOStruct_t *rwIOS) { static uint8_t padding[SK_MAX_RECORD_SIZE]; uint32_t pad_len; assert(rwIOS); assert(rwIOS->recLen > 0); assert(rwIOS->recLen < SK_MAX_RECORD_SIZE); /* If required, read/write the header-padding that makes the * header length an even multiple of the record length. This * applies for file versions of 2 or greater. */ if (rwGetFileVersion(rwIOS) >= 2) { pad_len = rwIOS->recLen - (rwIOS->hdrLen % rwIOS->recLen); /* if pad_len == recLen, the header is already an even * multiple of the record size, and there is no padding. */ if (pad_len < rwIOS->recLen) { switch (rwIOS->io_mode) { case SK_RWIO_CLOSED: assert(rwIOS->io_mode != SK_RWIO_CLOSED); abort(); case SK_RWIO_READ: case SK_RWIO_APPEND: if (RWIO_READ(rwIOS, padding, pad_len)) { rwIOS->errnum = errno; return LIBRW_ERR_READ; } break; case SK_RWIO_WRITE: if (RWIO_WRITE(rwIOS, padding, pad_len)) { rwIOS->errnum = errno; return LIBRW_ERR_WRITE; } break; } } } return LIBRW_OK; } int rwioCreate( rwIOStruct_t **rwIOS, const char *pathname, rwio_mode_t read_write_append) { int rv = LIBRW_OK; genericHeader *gHdr; flowtypeID_t ft; if (rwIOS == NULL) { rv = LIBRW_ERR_NULL_ARGUMENT; goto END; } *rwIOS = NULL; if (read_write_append == SK_RWIO_CLOSED) { rv = LIBRW_ERR_NULL_ARGUMENT; goto END; } /* Allocate and initialize the rwIOStruct */ *rwIOS = calloc(1, sizeof(rwIOStruct)); if (NULL == *rwIOS) { rv = LIBRW_ERR_ALLOC; goto END; } (*rwIOS)->_fd = -1; /* store the parameters on the structure */ (*rwIOS)->io_mode = read_write_append; /* file name */ (*rwIOS)->fPath = strdup(pathname); if (NULL == (*rwIOS)->fPath) { rv = LIBRW_ERR_ALLOC; goto END; } /* Allocate a genericHeader; the header may be re-allocated * later once we know the file type. */ (*rwIOS)->hdrLen = sizeof(genericHeader); gHdr = calloc(1, (*rwIOS)->hdrLen); if (NULL == gHdr) { rv = LIBRW_ERR_ALLOC; goto END; } (*rwIOS)->hdr = gHdr; /* Set to a generic file, default version, native byte order */ PREPHEADER(gHdr); #if IS_LITTLE_ENDIAN gHdr->isBigEndian = 0; #else gHdr->isBigEndian = 1; #endif gHdr->type = FT_RWGENERIC; gHdr->version = SK_FILE_VERSION_ANY; gHdr->compMethod = sksiteCompmethodGetDefault(); /* Native format by default, so don't swap */ (*rwIOS)->swapFlag = 0; /* set sensor ID and flow type from the file name, but don't * complain on error and set the values to invalid. Maybe someday * these will be stored in the header of the file so we don't * depend on the filename. */ ft = sksiteParseFilename(&((*rwIOS)->flow_type), &((*rwIOS)->sID), NULL, NULL, pathname); if (ft == SK_INVALID_FLOWTYPE) { (*rwIOS)->flow_type = SK_INVALID_FLOWTYPE; (*rwIOS)->sID = SK_INVALID_SENSOR; } rv = _ioCheckPathName(pathname, read_write_append); END: return rv; } int rwioSetHeaderFromFile( rwIOStruct_t *rwIOS, const rwIOStruct_t *source_ios) { int rv; assert(rwIOS); if (source_ios == NULL) { rv = LIBRW_ERR_NULL_ARGUMENT; goto END; } /* Set the type, version, compression, and byte order from the * specified file */ if ((rv = rwioSetFileType(rwIOS, rwGetFileType(source_ios))) || (rv = rwioSetFileVersion(rwIOS, rwGetFileVersion(source_ios))) || (rv = rwioSetCompression(rwIOS, rwGetFileCompMethod(source_ios))) || (rv = rwioSetFileByteorder(rwIOS, rwGetFileByteorder(source_ios)))) { goto END; } /* Copy the command line history if present, or the start time */ if (rwGetFileType(source_ios) == FT_RWFILTER) { rv = rwioAppendToHistoryFromFile(rwIOS, source_ios); if (rv) { goto END; } } else if (rwGetFileType(source_ios) != FT_RWGENERIC) { /* Copy the start-time if present */ rv = rwioSetFileSTime(rwIOS, rwGetFileSTime(source_ios), 0); if (rv) { goto END; } } END: return rv; } int rwioSetFileType( rwIOStruct_t *rwIOS, uint8_t file_format) { int rv; /* verify librw understands the file_format */ switch (file_format) { case FT_RWAUGMENTED: case FT_RWAUGROUTING: case FT_RWAUGWEB: case FT_RWAUGSNMPOUT: case FT_RWFILTER: case FT_RWGENERIC: case FT_RWNOTROUTED: case FT_RWROUTED: case FT_RWSPLIT: case FT_RWWWW: break; default: rv = LIBRW_ERR_UNSUPPORT_TYPE; goto END; } /* can we actually modify the file type? */ rv = _ioAssertModifiable(rwIOS); if (rv) { goto END; } /* Do not support changing the type once we've grown the header, * since it may mean re-allocating.... */ if (rwIOS->hdrLen != sizeof(genericHeader)) { rv = LIBRW_ERR_ATTRIBUTE_FIXED; goto END; } rv = _ioSetFileFormat(rwIOS, file_format); END: return rv; } int rwioSetFileVersion( rwIOStruct_t *rwIOS, fileVersion_t file_version) { int rv; /* No check of the version until we try to open the file */ rv = _ioAssertModifiable(rwIOS); if (rv) { goto END; } rv = _ioSetFileVersion(rwIOS, file_version); if (rv) { goto END; } END: return rv; } int rwioSetCompression( rwIOStruct_t *rwIOS, sk_compmethod_t comp_method) { int rv; /* verify that compression method is available */ if ( !sksiteCompmethodIsAvailable(comp_method)) { rv = LIBRW_ERR_UNAVAILABLE_COMPRESS; rwIOS->errobj.num = comp_method; goto END; } rv = _ioAssertModifiable(rwIOS); if (rv) { goto END; } rv = _ioSetCompMethod(rwIOS, comp_method); if (rv) { goto END; } END: return rv; } int rwioSetFileByteorder( rwIOStruct_t *rwIOS, silk_endian_t byte_order) { int rv; rv = _ioAssertModifiable(rwIOS); if (rv) { goto END; } rv = _ioSetFileByteorder(rwIOS, byte_order); if (rv) { goto END; } END: return rv; } int rwioSetFileSTime( rwIOStruct_t *rwIOS, uint32_t start_time, int use_floor_hour) { int rv; rv = _ioAssertHeaderNotWritten(rwIOS); if (rv) { goto END; } switch (rwGetFileType(rwIOS)) { case FT_RWAUGMENTED: case FT_RWAUGROUTING: case FT_RWAUGWEB: case FT_RWAUGSNMPOUT: case FT_RWNOTROUTED: case FT_RWROUTED: case FT_RWSPLIT: case FT_RWWWW: rv = _packedfileheaderSetSTime(rwIOS, start_time, use_floor_hour); break; case FT_RWFILTER: case FT_RWGENERIC: default: rv = LIBRW_ERR_UNSUPPORT_TYPE; break; } END: return rv; } int rwioAppendToHistoryFromFile( rwIOStruct_t *rwIOS, const rwIOStruct_t *source_rwIOS) { int rv = LIBRW_OK; sk_cmd_history_t *src_hist; rv = _ioAssertHeaderNotWritten(rwIOS); if (rv) { goto END; } /* verify source and dest are RWFILTER files */ if (rwGetFileType(rwIOS) != FT_RWFILTER) { rv = LIBRW_ERR_UNSUPPORT_TYPE; goto END; } if (rwGetFileType(source_rwIOS) != FT_RWFILTER) { rv = LIBRW_ERR_UNSUPPORT_TYPE; goto END; } src_hist = &(((filterHeaderV1*)(source_rwIOS->hdr))->cmdHist); rv = _headersAppendFromFile(rwIOS, src_hist); END: return rv; } int rwioAppendToHistoryArgv( rwIOStruct_t *rwIOS, int argc, char * const *argv) { int rv = LIBRW_OK; rv = _ioAssertHeaderNotWritten(rwIOS); if (rv) { goto END; } if (rwGetFileType(rwIOS) != FT_RWFILTER) { rv = LIBRW_ERR_UNSUPPORT_TYPE; goto END; } rv = _headersAppendArgv(rwIOS, argc, argv); END: return rv; } int rwioOpen( rwIOStruct_t *rwIOS) { int rv; rv = _ioAssertNotOpen(rwIOS); if (rv) { goto END; } switch (rwIOS->io_mode) { case SK_RWIO_CLOSED: rv = LIBRW_ERR_STREAM_CLOSED; break; case SK_RWIO_WRITE: rv = _ioPrepareWrite(rwIOS); if (rv) { goto END; } rv = _ioOpenWrite(rwIOS); if (rv) { goto END; } break; case SK_RWIO_READ: rv = _ioOpenRead(rwIOS); if (rv) { goto END; } rv = _ioPrepareRead(rwIOS); if (rv) { rwioClose(rwIOS); goto END; } break; case SK_RWIO_APPEND: rv = _ioOpenAppend(rwIOS); if (rv) { goto END; } rv = _ioPrepareRead(rwIOS); if (rv) { rwioClose(rwIOS); goto END; } break; } END: return rv; } int rwioFDOpen( rwIOStruct_t *rwIOS, int file_desc) { int rv; rv = _ioAssertNotOpen(rwIOS); if (rv) { goto END; } /* pre-open checks and set mode */ switch (rwIOS->io_mode) { case SK_RWIO_WRITE: rv = _ioPrepareWrite(rwIOS); break; case SK_RWIO_CLOSED: case SK_RWIO_READ: case SK_RWIO_APPEND: /* no checks */ break; } if (rv) { goto END; } /* Store the file descriptor: "open" the file */ rwIOS->_fd = file_desc; rwIOS->isOpenFlag = 1; /* post-open checks */ switch (rwIOS->io_mode) { case SK_RWIO_CLOSED: case SK_RWIO_WRITE: /* no checks */ break; case SK_RWIO_READ: case SK_RWIO_APPEND: rv = _ioPrepareRead(rwIOS); break; } END: return rv; } int rwioMakeTemp( rwIOStruct_t *rwIOS) { int rv; rv = _ioAssertNotOpen(rwIOS); if (rv) { goto END; } /* Temp files only make sense for writing */ if (rwIOS->io_mode != SK_RWIO_WRITE) { rv = LIBRW_ERR_UNSUPPORT_STREAM; goto END; } rv = _ioPrepareWrite(rwIOS); if (rv) { goto END; } /* open file */ rwIOS->_fd = mkstemp(rwGetFileName(rwIOS)); if (rwIOS->_fd == -1) { rwIOS->errnum = errno; rv = LIBRW_ERR_MKSTEMP; goto END; } END: if (rv == LIBRW_OK) { rwIOS->isOpenFlag = 1; } return rv; } int rwioLockFile( rwIOStruct_t *rwIOS) { int rv; off_t pos; rv = _ioAssertOpen(rwIOS); if (rv) { goto END; } /* Don't try to lock anything that is not a real file */ pos = lseek(rwIOS->_fd, 0, SEEK_CUR); if (pos == -1 && errno == ESPIPE) { goto END; } if (rwIOS->io_mode == SK_RWIO_READ) { rv = getRLockFD_Wait(rwIOS->_fd); if (rv != 0) { rwIOS->errnum = errno; rv = LIBRW_ERR_RLOCK; } } else { rv = getWLockFD_Wait(rwIOS->_fd); if (rv != 0) { rwIOS->errnum = errno; rv = LIBRW_ERR_WLOCK; } } END: return rv; } int rwioMakeDirectory( rwIOStruct_t *rwIOS) { int rv; char *cp; rv = _ioAssertNotOpen(rwIOS); if (rv) { goto END; } if (rwIOS->io_mode != SK_RWIO_WRITE) { rv = LIBRW_ERR_UNSUPPORT_STREAM; goto END; } /* Create the directory to the file if the directory does not * exist. Check for a '/' in the name, but make certain it * isn't the first '/' in the file path (e.g., "/foo") */ cp = strrchr(rwIOS->fPath, '/'); if ((cp != NULL) && (cp != rwIOS->fPath)) { *cp = '\0'; if ( !dirExists(rwIOS->fPath)) { rv = mkDirPath(rwIOS->fPath); *cp = '/'; if (rv) { rwIOS->errnum = errno; rv = LIBRW_ERR_MKDIRPATH; goto END; } } *cp = '/'; } END: return rv; } int rwioWriteHeader( rwIOStruct_t *rwIOS) { return _ioWriteHdr(rwIOS, NULL); } int rwioClose( rwIOStruct_t *rwIOS) { int rv = LIBRW_OK; if (rwIOS == NULL) { rv = LIBRW_ERR_NULL_ARGUMENT; goto END; } if (rwIOS->_fd != -1) { off_t bytes; /* Flush the skIOBuf when it's a writer */ if (rwIOS->iobuf && rwIOS->io_mode != SK_RWIO_READ) { bytes = skIOBufFlush(rwIOS->iobuf); if (bytes == -1) { rwIOS->errobj.str = skIOBufStrError(rwIOS->iobuf); rv = LIBRW_ERR_IOBUF; } } /* Now flush the gzFile */ #ifdef HAVE_ZLIB_H if (rwIOS->gz) { int zerr = gzclose(rwIOS->gz); if (zerr != Z_OK) { if (zerr == Z_ERRNO) { rwIOS->errnum = errno; rv = LIBRW_ERR_WRITE; } else { rv = LIBRW_ERR_WRITE; } } /* gzclose() closes the file */ rwIOS->_fd = -1; } #endif /* HAVE_ZLIB_H */ /* Close if we're still open */ if (rwIOS->_fd != STDIN_FILENO) { if (close(rwIOS->_fd) == -1) { rwIOS->errnum = errno; rv = LIBRW_ERR_WRITE; } } rwIOS->_fd = -1; } /* Mark the rwIOS as closed and unable to be opened. */ rwIOS->io_mode = SK_RWIO_CLOSED; rwIOS->isOpenFlag = 0; END: return rv; } int rwioFlush( rwIOStruct_t *rwIOS) { int rv; rv = _ioAssertOpen(rwIOS); if (rv) { goto END; } if (rwIOS->io_mode == SK_RWIO_READ) { /* nothing to do for a reader */ goto END; } /* flush the iobuf */ if (rwIOS->iobuf) { if (skIOBufFlush(rwIOS->iobuf) == -1) { rwIOS->errobj.str = skIOBufStrError(rwIOS->iobuf); rv = LIBRW_ERR_IOBUF; goto END; } } END: return rv; } int rwioDestroy( rwIOStruct_t **rwIOS) { int rv = LIBRW_OK; if (rwIOS == NULL || *rwIOS == NULL) { goto END; } if ((*rwIOS)->_fd != -1) { rv = rwioClose(*rwIOS); (*rwIOS)->_fd = -1; } if ((*rwIOS)->iobuf) { skIOBufDestroy((*rwIOS)->iobuf); (*rwIOS)->iobuf = NULL; } if ((*rwIOS)->hdr) { if (FT_RWFILTER == rwGetFileType(*rwIOS)) { _headersDestroyV1(*rwIOS); } else { free((*rwIOS)->hdr); } (*rwIOS)->hdr = NULL; } if ((*rwIOS)->fPath) { free((*rwIOS)->fPath); (*rwIOS)->fPath = NULL; } free(*rwIOS); *rwIOS = NULL; END: return rv; } uint32_t rwGetHeaderLength( const rwIOStruct_t *rwIOS) { uint32_t remainder; if (_ioAssertOpen(rwIOS)) { return 0; } assert(rwIOS->recLen > 0); /* handle cases without padding */ if (rwGetFileVersion(rwIOS) < 2) { return rwIOS->hdrLen; } /* if hdrLen is not evenly divible by recLen, add an extra recLen * to hdrLen and subtract the remainder */ remainder = rwIOS->hdrLen % rwIOS->recLen; if (remainder == 0) { return rwIOS->hdrLen; } return (rwIOS->hdrLen + rwIOS->recLen - remainder); } /* * Opens a file for reading. See rwpack.h for details. */ rwIOStruct *rwOpenFile(const char *fPath, rwIOStruct *copyInput) { rwIOStruct *rwIOS; int rv = LIBRW_OK; rv = rwioCreate(&rwIOS, fPath, SK_RWIO_READ); if (rv) { goto END; } rv = rwioOpen(rwIOS); if (rv) { goto END; } rwIOS->copyInputFD = copyInput; END: if (rv) { rwioPrintLastErr(rwIOS, rv, NULL); if (rwIOS) { rwioDestroy(&rwIOS); } } return rwIOS; } /* rwOpenFile */ void rwioPrintLastErr( rwIOStruct_t *rwIOS, int error_code, sk_msg_fn_t errfn) { const char *msg; char t_stamp1[SK_TIMESTAMP_STRLEN]; char t_stamp2[SK_TIMESTAMP_STRLEN]; char format_name[SK_MAX_STRLEN_FILE_FORMAT+1]; struct timeval tv; if (errfn == NULL) { errfn = &skAppPrintErr; } #ifdef TEST_PRINTF_FORMATS #define errfn printf #endif /* helpful macros for common error messages */ #define FILENAME_MSG \ if (!rwIOS) { errfn("%s", msg); } \ else { errfn("%s '%s'", msg, rwGetFileName(rwIOS)); } #define STRERROR_MSG \ if (!rwIOS) { errfn("%s", msg); } \ else if (rwIOS->errnum == 0) { \ errfn("%s '%s'", msg, rwGetFileName(rwIOS)); } \ else { \ errfn("%s '%s': %s", msg, \ rwGetFileName(rwIOS), strerror(rwIOS->errnum)); \ } switch ((librwErrorCodes_t)error_code) { case LIBRW_OK: errfn("Command completed successfully"); return; case LIBRW_ERR_STIME_UNDRFLO: msg = "Record's start time less than that allowed in file"; if (!rwIOS) { errfn("%s", msg); } else { tv.tv_usec = 0; tv.tv_sec = rwIOS->errobj.rec->sTime; sktimestamp_r(t_stamp1, &tv, 1); tv.tv_sec = rwGetFileSTime(rwIOS); sktimestamp_r(t_stamp2, &tv, 1); errfn("%s '%s': %s < %s", msg, rwGetFileName(rwIOS), t_stamp1, t_stamp2); } return; case LIBRW_ERR_STIME_OVRFLO: msg = "Record's start time greater than that allowed in file"; if (!rwIOS) { errfn("%s", msg); } else { tv.tv_usec = 0; tv.tv_sec = rwIOS->errobj.rec->sTime; sktimestamp_r(t_stamp1, &tv, 1); tv.tv_sec = (MAX_START_TIME + rwGetFileSTime(rwIOS)); sktimestamp_r(t_stamp2, &tv, 1); errfn("%s '%s': %s >= %s", msg, rwGetFileName(rwIOS), t_stamp1, t_stamp2); } return; case LIBRW_ERR_ELPSD_OVRFLO: msg = "Record's duration greater than that allowed in file"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %u >= %u", msg, rwGetFileName(rwIOS), rwIOS->errobj.rec->elapsed, MAX_ELAPSED_TIME); } return; case LIBRW_ERR_PKTS_OVRFLO: msg = "Record's packet count greater than that allowed in file"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %u >= %u", msg, rwGetFileName(rwIOS), rwIOS->errobj.rec->pkts, (MAX_PKTS * PKTS_DIVISOR)); } return; case LIBRW_ERR_PKTS_ZERO: msg = "Record's packet count is zero while writting to file"; FILENAME_MSG; return; case LIBRW_ERR_SNMP_OVRFLO: msg = "Record's SNMP index greater than that allowed in file"; if (!rwIOS) { errfn("%s", msg); } else if (rwIOS->errobj.rec->input > 255) { errfn("%s '%s': input %u > 255", msg, rwGetFileName(rwIOS), (unsigned int)rwIOS->errobj.rec->input); } else { errfn("%s '%s': output %u > 255", msg, rwGetFileName(rwIOS), (unsigned int)rwIOS->errobj.rec->output); } return; case LIBRW_ERR_SENSORID_OVRFLO: msg = "Record's Sensor ID greater than that allowed in file"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %u > 255", msg, rwGetFileName(rwIOS), (unsigned int)rwIOS->errobj.rec->sID); } return; case LIBRW_ERR_PROTO_MISMATCH: msg = "Record's IP-protocol is not supported in file"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %u", msg, rwGetFileName(rwIOS), (unsigned int)rwIOS->errobj.rec->proto); } return; case LIBRW_ERR_PKTS_GT_BYTES: msg = "Record's 'pkts' value is greater than its 'bytes' value"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s in file '%s': %u > %u", msg, rwGetFileName(rwIOS), (unsigned int)rwIOS->errobj.rec->pkts, (unsigned int)rwIOS->errobj.rec->bytes); } return; case LIBRW_ERR_WRITE: msg = "Cannot write to file"; STRERROR_MSG; return; case LIBRW_ERR_NULL_ARGUMENT: errfn("Unexpected NULL or empty value"); return; case LIBRW_ERR_ALLOC: errfn("Memory allocation failed"); return; case LIBRW_ERR_UNSUPPORT_TYPE: msg = "Unsupported operation on file's type"; if (!rwIOS) { errfn("%s", msg); } else { sksiteFileformatGetName(format_name, sizeof(format_name), rwGetFileType(rwIOS)); errfn("%s '%s' type %s (0x%02x)", msg, rwGetFileName(rwIOS), format_name, rwGetFileType(rwIOS)); } return; case LIBRW_ERR_UNSUPPORT_VERSION: msg = "This SiLK release does not support the type and version of"; if (!rwIOS) { errfn("%s file", msg); } else { sksiteFileformatGetName(format_name, sizeof(format_name), rwGetFileType(rwIOS)); errfn("%s\n\t file '%s': %s(0x%02x) v%u", msg, rwGetFileName(rwIOS), format_name, rwGetFileType(rwIOS), (unsigned int)rwGetFileVersion(rwIOS)); } return; case LIBRW_ERR_UNSUPPORT_STREAM: msg = "Operation is not permitted on the stream/file"; FILENAME_MSG; return; case LIBRW_ERR_STREAM_TTY: msg = "Cannot process binary data on a stream connected to a terminal"; FILENAME_MSG; return; case LIBRW_ERR_ATTRIBUTE_FIXED: msg = "Cannot change attributes of this stream/file"; FILENAME_MSG; return; case LIBRW_ERR_STREAM_OPEN: msg = "Operation not permitted on previously opened file"; FILENAME_MSG; return; case LIBRW_ERR_STREAM_NOT_OPEN: msg = "Operation not permitted on unopened file"; FILENAME_MSG; return; case LIBRW_ERR_STREAM_CLOSED: msg = "Operation not permitted on closed stream"; FILENAME_MSG; return; case LIBRW_ERR_OPEN: msg = "Cannot open file"; STRERROR_MSG; return; case LIBRW_ERR_FDOPEN: msg = "Cannot open file descriptor for file as a stream"; if (!rwIOS) { errfn("%s", msg); } else if (rwIOS->errnum == 0) { errfn("%s desc %d, file '%s'", msg, rwIOS->errobj.num, rwGetFileName(rwIOS)); } else { errfn("%s desc %d, file '%s': %s", msg, rwIOS->errobj.num, rwGetFileName(rwIOS), strerror(rwIOS->errnum)); } return; case LIBRW_ERR_MKSTEMP: msg = "Cannot create temporary file"; STRERROR_MSG; return; case LIBRW_ERR_READ: msg = "Cannot read from file"; STRERROR_MSG; return; case LIBRW_ERR_READ_EOF: msg = "Reached unexpected end-of-file"; FILENAME_MSG; return; case LIBRW_ERR_WRITE_FILE_EXISTS: msg = "Cannot create new file over existing file"; FILENAME_MSG; return; case LIBRW_ERR_MKDIRPATH: msg = "Cannot create directory to hold file"; STRERROR_MSG; return; case LIBRW_ERR_OPEN_NOEXIST: msg = "Cannot open non-existent file"; FILENAME_MSG; return; case LIBRW_ERR_FSEEK: msg = "Cannot seek in file"; STRERROR_MSG; return; case LIBRW_ERR_UNSUPPORT_COMPRESS: msg = "Operation not permitted on compressed file"; FILENAME_MSG; return; case LIBRW_ERR_UNAVAILABLE_COMPRESS: msg = "Specified compression method is not available"; if (!rwIOS) { errfn("%s", msg); } else if (sksiteCompmethodIsValid(rwIOS->errobj.num)) { sksiteCompmethodGetName(format_name, sizeof(format_name), rwIOS->errobj.num); errfn("%s for '%s': %s", msg, rwGetFileName(rwIOS), format_name); } else { errfn("%s for '%s': %d [unknown id]", msg, rwGetFileName(rwIOS), rwIOS->errobj.num); } return; case LIBRW_ERR_BAD_MAGIC: msg = "File does not appear to be a SiLK data file"; FILENAME_MSG; return; case LIBRW_ERR_MISMATCH_TYPE: msg = "Specified type does not match that of file"; if (!rwIOS) { errfn("%s", msg); } else { sksiteFileformatGetName(format_name, sizeof(format_name), rwGetFileType(rwIOS)); errfn("%s '%s': %s (0x%02x)", msg, rwGetFileName(rwIOS), format_name, rwGetFileType(rwIOS)); } return; case LIBRW_ERR_MISMATCH_VERSION: msg = "Specified version does not match that of file"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %u", msg, rwGetFileName(rwIOS), (unsigned int)rwGetFileVersion(rwIOS)); } return; case LIBRW_ERR_MISMATCH_ENDIAN: msg = "Specified byte order does not match that of file"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %s", msg, rwGetFileName(rwIOS), ((rwGetIsBigEndian(rwIOS) ? "Big" : "Little"))); } return; case LIBRW_ERR_MISMATCH_STARTIME: msg = "Specified start time does not match that of file"; if (!rwIOS) { errfn("%s", msg); } else { tv.tv_usec = 0; tv.tv_sec = rwGetFileSTime(rwIOS); sktimestamp_r(t_stamp1, &tv, 1); errfn("%s '%s': %s", msg, rwGetFileName(rwIOS), t_stamp1); } return; case LIBRW_ERR_WLOCK: msg = "Cannot get a write lock on file"; STRERROR_MSG; return; case LIBRW_ERR_RLOCK: msg = "Cannot get a read lock on file"; STRERROR_MSG; return; case LIBRW_ERR_IOBUF: msg = "Cannot read-from/write-to a buffer"; if (!rwIOS) { errfn("%s", msg); } else { errfn("%s '%s': %s", msg, rwGetFileName(rwIOS), rwIOS->errobj.str); } return; } /* switch */ errfn("Unrecognized error code %d", error_code); } /* ** Local Variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */