/* ** Copyright (C) 2001-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@ */ /* ** rwheaders.c ** ** Routines for reading/writing rwfilter header files ** (moved from util/filter/filterio.c) ** **/ #include "silk.h" RCSIDENT("$SiLK: rwheaders.c 7291 2007-05-25 14:20:10Z mthomas $"); #include "librw_priv.h" static int _headersReadCmdHistory( rwIOStruct *rwIOS, sk_cmd_history_t *hist); static int _headersWriteCmdHistory( rwIOStruct *rwIOS, const sk_cmd_history_t *hist); int _headersCreateV1( rwIOStruct *rwIOS) { int rv = LIBRW_OK; size_t old_len; filterHeaderV1 *new_hdr; assert(rwIOS); assert(rwGetHeader(rwIOS)); /* if the header length is not the size of a generic header, * assume we've already created the header. */ if (rwIOS->hdrLen != sizeof(genericHeader)) { goto END; } /* store old header length */ old_len = rwIOS->hdrLen; /* the smallest on-disk header will hold the genericHeader and a * command-line count of 0; set the header length to that size */ rwIOS->hdrLen += sizeof(uint32_t); /* the in-core header is a filterHeaderV1; create a new empty * header, then copy the current header into it. */ new_hdr = calloc(1, sizeof(filterHeaderV1)); if (NULL == new_hdr) { rwIOS->hdrLen = old_len; rv = LIBRW_ERR_ALLOC; goto END; } memcpy(&new_hdr->gHdr, rwIOS->hdr, sizeof(genericHeader)); /* free the old header */ free(rwIOS->hdr); rwIOS->hdr = new_hdr; END: return rv; } /* destory a filterHeaderV1 */ int _headersDestroyV1( rwIOStruct *rwIOS) { filterHeaderV1 *hdr; sk_cmd_history_t *hist; uint32_t i; assert(rwIOS); hdr = (filterHeaderV1*)rwGetHeader(rwIOS); assert(hdr); if (rwIOS->hdrLen > sizeof(genericHeader)) { /* since the header is longer than a generic header, it must * be a filterHeaderV1 */ hist = &(hdr->cmdHist); if (hist->cmd_capacity > 0) { /* destroy each command line */ for (i = 0; i < hist->cmd_count; i++) { free(hist->cmd_array[i].cmd_info); } /* destroy the cmd_array itself */ free(hist->cmd_array); } } free(hdr); rwIOS->hdr = NULL; return LIBRW_OK; } /* Add command line to the history for rwIOS; update header length */ int _headersAppendArgv( rwIOStruct *rwIOS, int argc, char * const *argv) { int rv = LIBRW_OK; int i; char *cp; uint32_t len; const char *app_name = skAppName(); sk_cmd_history_t *hist; assert(rwIOS); assert(rwGetHeader(rwIOS)); /* make certain there is something to do */ if (argc == 0 || argv == NULL) { goto END; } /* grow the header and point to the history */ rv = _headersCreateV1(rwIOS); if (rv) { goto END; } hist = &(((filterHeaderV1*)(rwIOS->hdr))->cmdHist); /* grow the header if there are no entries or if the number of * entries is at capacity */ if (hist->cmd_count == hist->cmd_capacity) { sk_cmd_invoc_t *new_array = NULL; uint32_t new_cap = 2 + hist->cmd_capacity; if (hist->cmd_capacity == 0) { /* create new array */ new_array = malloc(new_cap * sizeof(sk_cmd_invoc_t)); } else { /* grow existing array */ new_array = realloc(hist->cmd_array, new_cap * sizeof(sk_cmd_invoc_t)); } if (new_array == NULL) { rv = LIBRW_ERR_ALLOC; goto END; } hist->cmd_array = new_array; hist->cmd_capacity = new_cap; } /* compute the total length of the application name and the * command line arguments */ len = strlen(app_name) + 1; /* allow for final \0 */ for(i = 1; i < argc; i++) { len += strlen(argv[i]) + 1; /* allow for the \0 */ /* truncate the command line if too long */ if (len >= UINT16_MAX) { len -= strlen(argv[i]) + 1; argc = i; break; } } /* store length */ hist->cmd_array[hist->cmd_count].cmd_length = (uint16_t)len; /* malloc the required space for the command line */ cp = malloc(len * sizeof(char)); if (NULL == cp) { rv = LIBRW_ERR_ALLOC; goto END; } hist->cmd_array[hist->cmd_count].cmd_info = cp; /* store the application name */ len = strlen(app_name) + 1; memcpy(cp, app_name, len); cp += len; /* store the command line */ for(i = 1; i < argc; i++) { /* copy all including trailing NUL */ len = strlen(argv[i]) + 1; memcpy(cp, argv[i], len); cp += len; } /* update header length and increment cmd-line count */ rwIOS->hdrLen += (sizeof(hist->cmd_array[hist->cmd_count].cmd_length) + hist->cmd_array[hist->cmd_count].cmd_length); ++hist->cmd_count; END: return rv; } /* Append the command line history 'src_hist' from a source file to * the command history for the stream in 'rwIOS', and update the * length of the header. */ int _headersAppendFromFile( rwIOStruct *rwIOS, const sk_cmd_history_t *src_hist) { int rv = LIBRW_OK; uint32_t src, tgt; sk_cmd_history_t *hist; assert(rwIOS); assert(rwGetHeader(rwIOS)); assert(src_hist); /* make certain there is something to do */ if (src_hist->cmd_count == 0) { goto END; } /* grow the header and point to the history */ rv = _headersCreateV1(rwIOS); if (rv) { goto END; } hist = &(((filterHeaderV1*)(rwIOS->hdr))->cmdHist); /* grow the header if there are no entries or if the number of * entries is at capacity */ if ((hist->cmd_count + src_hist->cmd_count) >= hist->cmd_capacity) { sk_cmd_invoc_t *new_array = NULL; uint32_t new_cap = (2 + hist->cmd_capacity + src_hist->cmd_count); if (hist->cmd_capacity == 0) { new_array = malloc(new_cap * sizeof(sk_cmd_invoc_t)); } else { new_array = realloc(hist->cmd_array, new_cap*sizeof(sk_cmd_invoc_t)); } if (new_array == NULL) { rv = LIBRW_ERR_ALLOC; goto END; } hist->cmd_array = new_array; hist->cmd_capacity = new_cap; } /* loop over all command-line entries in the source history, and * copy them into the target history. */ for (src=0, tgt=hist->cmd_count; src < src_hist->cmd_count; ++src,++tgt) { /* store length */ hist->cmd_array[tgt].cmd_length = src_hist->cmd_array[src].cmd_length; /* malloc the required space for the command line */ hist->cmd_array[tgt].cmd_info =malloc(hist->cmd_array[tgt].cmd_length); if (NULL == hist->cmd_array[tgt].cmd_info) { rv = LIBRW_ERR_ALLOC; goto END; } /* copy command line */ memcpy(hist->cmd_array[tgt].cmd_info, src_hist->cmd_array[src].cmd_info, hist->cmd_array[tgt].cmd_length); /* update header length and increment filter-count */ rwIOS->hdrLen += (sizeof(hist->cmd_array[tgt].cmd_length) + hist->cmd_array[tgt].cmd_length); ++hist->cmd_count; } END: return rv; } /* Read the section of the FT_RWFILTER header following the genericHeader */ int _headersReadV1( rwIOStruct *rwIOS) { int rv = LIBRW_OK; filterHeaderV1 *hdr; assert(rwIOS); /* create room for the command lines */ rv = _headersCreateV1(rwIOS); if (rv) { goto END; } hdr = (filterHeaderV1*)rwGetHeader(rwIOS); assert(hdr); /* read command line history */ rv = _headersReadCmdHistory(rwIOS, &(hdr->cmdHist)); if (rv) { goto END; } /* do header padding */ rv = _ioHandleHeaderPadding(rwIOS); if (rv) { goto END; } END: return rv; } /* Write the FT_RWFILTER header */ int _headersWriteV1( rwIOStruct *rwIOS, const rwRec UNUSED(*rwrec)) { int rv = LIBRW_OK; filterHeaderV1 *hdr; /* check input and record size */ assert(rwIOS); hdr = (filterHeaderV1*)rwGetHeader(rwIOS); assert(hdr); /* write the generic header */ if (RWIO_WRITE(rwIOS, hdr, sizeof(genericHeader))) { rwIOS->errnum = errno; rv = LIBRW_ERR_WRITE; goto END; } /* write the command lines */ rv = _headersWriteCmdHistory(rwIOS, &(hdr->cmdHist)); if (rv) { goto END; } /* do header padding */ rv = _ioHandleHeaderPadding(rwIOS); if (rv) { goto END; } END: return rv; } /* * status = _headersReadCmdHistory(rwIOS, hist); * * Read the command line history stored from the stream specified * by 'rwIOS' into the 'hist' object. This function assumes the * file's read pointer is sitting at the beginning of the * history---specifically on the number of command lines. */ static int _headersReadCmdHistory( rwIOStruct *rwIOS, sk_cmd_history_t *hist) { int rv = LIBRW_OK; uint16_t cmd_line_len; uint32_t i; /* check input */ assert(rwIOS); assert(hist); /* make certain we are using the correct swapping below */ assert(sizeof(uint32_t) == sizeof(hist->cmd_count)); assert(sizeof(cmd_line_len) == sizeof(hist->cmd_array[i].cmd_length) && 2 == sizeof(cmd_line_len)); /* read the number of command lines; the hdrLen already accounts * for this */ if (RWIO_READ(rwIOS, &hist->cmd_count, sizeof(hist->cmd_count))) { rwIOS->errnum = errno; rv = LIBRW_ERR_READ; goto END; } if (rwIOS->swapFlag) { hist->cmd_count = BSWAP32(hist->cmd_count); } /* allocate the required space */ if (hist->cmd_count > 0) { hist->cmd_capacity = 2 + hist->cmd_count; hist->cmd_array = malloc(hist->cmd_capacity * sizeof(sk_cmd_invoc_t)); if (hist->cmd_array == NULL) { rv = LIBRW_ERR_ALLOC; goto END; } } /* and load each one into newly malloc'd space */ for (i = 0; i < hist->cmd_count; i++) { /* the info length */ if (RWIO_READ(rwIOS, &cmd_line_len, sizeof(cmd_line_len))) { rwIOS->errnum = errno; rv = LIBRW_ERR_READ; goto END; } if (rwIOS->swapFlag) { cmd_line_len = BSWAP16(cmd_line_len); } if (cmd_line_len) { /* get space for the struct in the array */ hist->cmd_array[i].cmd_info = malloc(cmd_line_len * sizeof(char)); if (NULL == hist->cmd_array[i].cmd_info) { hist->cmd_count = i; rv = LIBRW_ERR_ALLOC; goto END; } /* read in the real information */ if (RWIO_READ(rwIOS, hist->cmd_array[i].cmd_info, cmd_line_len)) { free(hist->cmd_array[i].cmd_info); rv = LIBRW_ERR_ALLOC; goto END; } } /* update the in-core entry and the hdrLen */ hist->cmd_array[i].cmd_length = cmd_line_len; rwIOS->hdrLen += cmd_line_len + sizeof(cmd_line_len); } END: return rv; } /* * status = _headersWriteCmdHistory(rwIOS, hist); * * Write the command line history stored in 'hist' to the stream * specified by 'rwIOS'. This function assumes the genericHeader * has already been written. */ static int _headersWriteCmdHistory( rwIOStruct *rwIOS, const sk_cmd_history_t *hist) { int rv = LIBRW_OK; uint32_t cmd_count; uint16_t cmd_line_len; uint32_t i; /* make certain we are using the correct swapping below */ assert(sizeof(cmd_count) == sizeof(hist->cmd_count) && 4 == sizeof(cmd_count)); assert(sizeof(cmd_line_len) == sizeof(hist->cmd_array[i].cmd_length) && 2 == sizeof(cmd_line_len)); /* check input and record size */ assert(rwIOS); assert(hist); /* number of command lines */ cmd_count = ((rwIOS->swapFlag) ? BSWAP32(hist->cmd_count) : hist->cmd_count); if (RWIO_WRITE(rwIOS, &cmd_count, sizeof(hist->cmd_count))) { rwIOS->errnum = errno; rv = LIBRW_ERR_WRITE; goto END; } /* handle each command line */ for (i = 0; i < hist->cmd_count; i++) { cmd_line_len = ((rwIOS->swapFlag) ? BSWAP16(hist->cmd_array[i].cmd_length) : hist->cmd_array[i].cmd_length); if (RWIO_WRITE(rwIOS, &cmd_line_len, sizeof(cmd_line_len)) || RWIO_WRITE(rwIOS, hist->cmd_array[i].cmd_info, hist->cmd_array[i].cmd_length)) { rwIOS->errnum = errno; rv = LIBRW_ERR_WRITE; goto END; } } END: return rv; } /* ** Local Variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */