/* * get_record: Get the next record into a buffer * Every 8192 bytes 16 bytes are inserted in the file, * even in the middle of a record. * This reads the next record without the eventual 16 bytes. * returns the length of the record + the stuffing (if any) * * Returns number of bytes read on success, 0 on EOF, -1 on error; * if -1 is returned, *err is set to the error indication and, for * errors where that's appropriate, *err_info is set to an additional * error string. * * XXX: works at most with 8191 bytes per record */ static gint get_record(k12_t *file_data, FILE_T fh, gint64 file_offset, gboolean is_random, int *err, gchar **err_info) { guint8 *buffer = is_random ? file_data->rand_read_buff : file_data->seq_read_buff; guint buffer_len = is_random ? file_data->rand_read_buff_len : file_data->seq_read_buff_len; guint total_read = 0; guint left; guint8* writep; #ifdef DEBUG_K12 guint actual_len; #endif /* * Where the next unknown 16 bytes are stuffed to the file. * Following the file header, they appear every 8192 bytes, * starting right after the file header, so if the file offset * relative to the file header is a multiple of 8192, the * 16-byte blob is there. */ guint junky_offset = 8192 - (gint) ( (file_offset - K12_FILE_HDR_LEN) % 8192 ); K12_DBG(6,("get_record: ENTER: junky_offset=%" G_GINT64_MODIFIER "d, file_offset=%" G_GINT64_MODIFIER "d",junky_offset,file_offset)); /* no buffer is given, lets create it */ if (buffer == NULL) { buffer = (guint8*)g_malloc(8192); buffer_len = 8192; if (is_random) { file_data->rand_read_buff = buffer; file_data->rand_read_buff_len = buffer_len; } else { file_data->seq_read_buff = buffer; file_data->seq_read_buff_len = buffer_len; } } if ( junky_offset == 8192 ) { /* * We're at the beginning of one of the 16-byte blobs, * so we first need to skip the blob. * * XXX - what if the blob is in the middle of the record * length? If the record length is always a multiple of * 4 bytes, that won't happen. */ if ( ! wtap_read_bytes( fh, NULL, K12_FILE_BLOB_LEN, err, err_info ) ) return -1; total_read += K12_FILE_BLOB_LEN; } /* * Read the record length. */ if ( !wtap_read_bytes( fh, buffer, 4, err, err_info ) ) return -1; total_read += 4; left = pntoh32(buffer + K12_RECORD_LEN); #ifdef DEBUG_K12 actual_len = left; #endif junky_offset -= 4; K12_DBG(5,("get_record: GET length=%u",left)); /* * Record length must be at least large enough for the length * and type, hence 8 bytes. * * XXX - is WTAP_MAX_PACKET_SIZE_STANDARD the right check for a maximum * record size? Should we report this error differently? */ if (left < 8) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12: Record length %u is less than 8 bytes long",left); return -1; } if (left > WTAP_MAX_PACKET_SIZE_STANDARD) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12: Record length %u is greater than the maximum %u",left,WTAP_MAX_PACKET_SIZE_STANDARD); return -1; } /* * XXX - calculate the lowest power of 2 >= left, rather than just * looping. */ while (left > buffer_len) { buffer = (guint8*)g_realloc(buffer,buffer_len*=2); if (is_random) { file_data->rand_read_buff = buffer; file_data->rand_read_buff_len = buffer_len; } else { file_data->seq_read_buff = buffer; file_data->seq_read_buff_len = buffer_len; } } writep = buffer + 4; left -= 4; /* Read the rest of the record. */ do { K12_DBG(6,("get_record: looping left=%d junky_offset=%" G_GINT64_MODIFIER "d",left,junky_offset)); if (junky_offset > left) { /* * The next 16-byte blob is past the end of this record. * Just read the rest of the record. */ if ( !wtap_read_bytes( fh, writep, left, err, err_info ) ) return -1; total_read += left; break; } else { /* * The next 16-byte blob is part of this record. * Read up to the blob. */ if ( !wtap_read_bytes( fh, writep, junky_offset, err, err_info ) ) return -1; total_read += junky_offset; writep += junky_offset; /* * Skip the blob. */ if ( !wtap_read_bytes( fh, NULL, K12_FILE_BLOB_LEN, err, err_info ) ) return -1; total_read += K12_FILE_BLOB_LEN; left -= junky_offset; junky_offset = 8192; } } while(left); K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len); return total_read; }
/* * get_record: Get the next record into a buffer * Every about 0x2000 bytes 0x10 bytes are inserted in the file, * even in the middle of a record. * This reads the next record without the eventual 0x10 bytes. * returns the length of the record + the stuffing (if any) * * Returns number of bytes read on success, 0 on EOF, -1 on error; * if -1 is returned, *err is set to the error indication and, for * errors where that's appropriate, *err_info is set to an additional * error string. * * XXX: works at most with 0x1FFF bytes per record */ static gint get_record(k12_t *file_data, FILE_T fh, gint64 file_offset, gboolean is_random, int *err, gchar **err_info) { guint8 *buffer = is_random ? file_data->rand_read_buff : file_data->seq_read_buff; guint buffer_len = is_random ? file_data->rand_read_buff_len : file_data->seq_read_buff_len; guint bytes_read; guint last_read; guint left; guint8 junk[0x14]; guint8* writep; #ifdef DEBUG_K12 guint actual_len; #endif /* where the next unknown 0x10 bytes are stuffed to the file */ guint junky_offset = 0x2000 - (gint) ( (file_offset - 0x200) % 0x2000 ); K12_DBG(6,("get_record: ENTER: junky_offset=%" G_GINT64_MODIFIER "d, file_offset=%" G_GINT64_MODIFIER "d",junky_offset,file_offset)); /* no buffer is given, lets create it */ if (buffer == NULL) { buffer = (guint8*)g_malloc(0x2000); buffer_len = 0x2000; if (is_random) { file_data->rand_read_buff = buffer; file_data->rand_read_buff_len = buffer_len; } else { file_data->seq_read_buff = buffer; file_data->seq_read_buff_len = buffer_len; } } /* Get the record length. */ if ( junky_offset == 0x2000 ) { /* the length of the record is 0x10 bytes ahead from we are reading */ bytes_read = file_read(junk,0x14,fh); if (bytes_read == 2 && junk[0] == 0xff && junk[1] == 0xff) { K12_DBG(1,("get_record: EOF")); return 0; } else if ( bytes_read < 0x14 ) { K12_DBG(1,("get_record: SHORT READ OR ERROR")); *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } memcpy(buffer,&(junk[0x10]),4); } else { /* the length of the record is right where we are reading */ bytes_read = file_read(buffer, 0x4, fh); if (bytes_read == 2 && buffer[0] == 0xff && buffer[1] == 0xff) { K12_DBG(1,("get_record: EOF")); return 0; } else if (bytes_read == 4 && buffer[0] == 0xff && buffer[1] == 0xff && buffer[2] == 0x00 && buffer[3] == 0x00) { /* * In at least one k18 RF5 file, there appears to be a "record" * with a length value of 0xffff0000, followed by a bunch of * data that doesn't appear to be records, including a long * list of numbers. * * We treat a length value of 0xffff0000 as an end-of-file * indication. * * XXX - is this a length indication, or will it appear * at the beginning of an 8KB block, so that we should * check for it above? */ K12_DBG(1,("get_record: EOF")); return 0; } else if ( bytes_read != 0x4 ) { K12_DBG(1,("get_record: SHORT READ OR ERROR")); *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } } left = pntoh32(buffer + K12_RECORD_LEN); #ifdef DEBUG_K12 actual_len = left; #endif junky_offset -= 0x4; K12_DBG(5,("get_record: GET length=%u",left)); /* * Record length must be at least large enough for the length, * hence 4 bytes. * * XXX - Is WTAP_MAX_PACKET_SIZE the right check for a maximum * record size? Should we report this error differently? */ if (left < 4 || left > WTAP_MAX_PACKET_SIZE) { K12_DBG(1,("get_record: Invalid GET length=%u",left)); *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("get_record: Invalid GET length=%u",left); return -1; } /* * XXX - calculate the lowest power of 2 >= left, rather than just * looping. */ while (left > buffer_len) { buffer = (guint8*)g_realloc(buffer,buffer_len*=2); if (is_random) { file_data->rand_read_buff = buffer; file_data->rand_read_buff_len = buffer_len; } else { file_data->seq_read_buff = buffer; file_data->seq_read_buff_len = buffer_len; } } writep = buffer + 4; left -= 4; /* Read the rest of the record. */ do { K12_DBG(6,("get_record: looping left=%d junky_offset=%" G_GINT64_MODIFIER "d",left,junky_offset)); if (junky_offset > left) { bytes_read += last_read = file_read(writep, left, fh); if ( last_read != left ) { K12_DBG(1,("get_record: SHORT READ OR ERROR")); *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } else { K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len); return bytes_read; } } else { bytes_read += last_read = file_read(writep, junky_offset, fh); if ( last_read != junky_offset ) { K12_DBG(1,("get_record: SHORT READ OR ERROR, read=%d expected=%d",last_read, junky_offset)); *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } writep += last_read; bytes_read += last_read = file_read(junk, 0x10, fh); if ( last_read != 0x10 ) { K12_DBG(1,("get_record: SHORT READ OR ERROR")); *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } left -= junky_offset; junky_offset = 0x2000; } } while(left); K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len); return bytes_read; }