static void gen_request( qli_req* request) { /************************************** * * g e n _ r e q u e s t * ************************************** * * Functional description * Prepare to generation and compile a request. * **************************************/ qli_par* param; qli_rlb* rlb = CHECK_RLB(request->req_blr); STUFF(blr_version4); STUFF(blr_begin); // Build declarations for all messages. for (qli_msg* message = request->req_messages; message; message = message->msg_next) { message->msg_length = 0; for (param = message->msg_parameters; param; param = param->par_next) { const dsc* desc = ¶m->par_desc; param->par_parameter = message->msg_parameter++; const USHORT alignment = type_alignments[desc->dsc_dtype]; if (alignment) message->msg_length = FB_ALIGN(message->msg_length, alignment); param->par_offset = message->msg_length; message->msg_length += desc->dsc_length; qli_par* missing_param = param->par_missing; if (missing_param) { missing_param->par_parameter = message->msg_parameter++; message->msg_length = FB_ALIGN(message->msg_length, sizeof(USHORT)); desc = &missing_param->par_desc; missing_param->par_offset = message->msg_length; message->msg_length += desc->dsc_length; } } STUFF(blr_message); STUFF(message->msg_number); STUFF_WORD(message->msg_parameter); qli_str* string = (qli_str*) ALLOCDV(type_str, message->msg_length + FB_DOUBLE_ALIGN - 1); message->msg_buffer = (UCHAR*) FB_ALIGN((FB_UINT64)(U_IPTR) string->str_data, FB_DOUBLE_ALIGN); for (param = message->msg_parameters; param; param = param->par_next) { gen_descriptor(¶m->par_desc, request); qli_par* missing_param = param->par_missing; if (missing_param) gen_descriptor(&missing_param->par_desc, request); } } }
UCHAR* MSC_alloc(int size) { size = FB_ALIGN(size, FB_ALIGNMENT); if (!space || size > space->spc_remaining) { const int n = MAX(size, 4096); gpre_space* next = (gpre_space*) gds__alloc((SLONG) (n + sizeof(gpre_space))); if (!next) CPR_error("virtual memory exhausted"); #ifdef DEBUG_GDS_ALLOC // For V4.0 we don't care about gpre specific memory leaks gds_alloc_flag_unfreed(next); #endif next->spc_next = space; next->spc_remaining = n; space = next; } space->spc_remaining -= size; UCHAR* blk = ((UCHAR*) space + sizeof(gpre_space) + space->spc_remaining); memset(blk, 0, size); return blk; }
void BlrFromMessage::buildBlr(IMessageMetadata* metadata) { if (!metadata) return; LocalStatus st; expectedMessageLength = metadata->getMessageLength(&st); checkStatus(&st); getBlrData().clear(); const unsigned count = metadata->getCount(&st); fb_assert(count < MAX_USHORT / 2); if (count == 0) return; // If there isn't an SQLDA, don't bother with anything else. appendVersion(); appendUChar(blr_begin); appendUChar(blr_message); appendUChar(0); appendUShort(count * 2); unsigned msgLen = 0; for (unsigned i = 0; i < count; ++i) { unsigned dtype = metadata->getType(&st, i) & ~1; checkStatus(&st); unsigned len = metadata->getLength(&st, i); checkStatus(&st); unsigned scale = metadata->getScale(&st, i); checkStatus(&st); unsigned charSet = metadata->getCharSet(&st, i); checkStatus(&st); switch (dtype) { case SQL_VARYING: appendUChar(blr_varying2); appendUShort(charSet); appendUShort(len); dtype = dtype_varying; len += sizeof(USHORT); break; case SQL_TEXT: appendUChar(blr_text2); appendUShort(charSet); appendUShort(len); dtype = dtype_text; break; case SQL_DOUBLE: appendUChar(blr_double); dtype = dtype_double; break; case SQL_FLOAT: appendUChar(blr_float); dtype = dtype_real; break; case SQL_D_FLOAT: appendUChar(blr_d_float); dtype = dtype_d_float; break; case SQL_TYPE_DATE: appendUChar(blr_sql_date); dtype = dtype_sql_date; break; case SQL_TYPE_TIME: appendUChar(blr_sql_time); dtype = dtype_sql_time; break; case SQL_TIMESTAMP: appendUChar(blr_timestamp); dtype = dtype_timestamp; break; case SQL_BLOB: appendUChar(blr_blob2); appendUShort(metadata->getSubType(&st, i)); appendUShort(charSet); dtype = dtype_blob; break; case SQL_ARRAY: appendUChar(blr_quad); appendUChar(0); dtype = dtype_array; break; case SQL_LONG: appendUChar(blr_long); appendUChar(scale); dtype = dtype_long; break; case SQL_SHORT: appendUChar(blr_short); appendUChar(scale); dtype = dtype_short; break; case SQL_INT64: appendUChar(blr_int64); appendUChar(scale); dtype = dtype_int64; break; case SQL_QUAD: appendUChar(blr_quad); appendUChar(scale); dtype = dtype_quad; break; case SQL_BOOLEAN: appendUChar(blr_bool); dtype = dtype_boolean; break; case SQL_NULL: appendUChar(blr_text); appendUShort(len); dtype = dtype_text; break; default: Arg::Gds(isc_dsql_sqlda_value_err).raise(); break; } appendUChar(blr_short); appendUChar(0); unsigned align = type_alignments[dtype]; if (align) msgLen = FB_ALIGN(msgLen, align); msgLen += len; align = type_alignments[dtype_short]; if (align) msgLen = FB_ALIGN(msgLen, align); msgLen += sizeof(SSHORT); } appendUChar(blr_end); appendUChar(blr_eoc); if (expectedMessageLength && msgLen && (expectedMessageLength != msgLen)) { Arg::Gds(isc_wrong_message_length).raise(); } }
void create() { static char place[sizeof(Firebird::Mutex) + FB_ALIGNMENT]; mutex = new((void*) FB_ALIGN(place, FB_ALIGNMENT)) Firebird::Mutex; }
ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t direction) { /************************************** * * C A N _ e n c o d e _ d e c o d e * ************************************** * * Functional description * encode and decode canonical backup. * **************************************/ const burp_fld* field; SSHORT n; XDR xdr; XDR* xdrs = &xdr; xdr_init(xdrs, buffer, direction ? XDR_ENCODE : XDR_DECODE); RCRD_OFFSET offset = 0; for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; UCHAR* p = data + field->fld_offset; const bool array_fld = ((field->fld_flags & FLD_array) != 0); const FLD_LENGTH length = array_fld ? 8 : field->fld_length; if (field->fld_offset >= offset) offset = field->fld_offset + length; if (field->fld_type == blr_varying && !array_fld) offset += sizeof(SSHORT); SSHORT dtype; if (field->fld_type == blr_blob || array_fld) dtype = dtype_blob; else dtype = (SSHORT) gds_cvt_blr_dtype[field->fld_type]; switch (dtype) { case dtype_text: if (!xdr_opaque(xdrs, reinterpret_cast<char*>(p), length)) { return FALSE; } break; case dtype_varying: { vary* pVary = reinterpret_cast<vary*>(p); if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&pVary->vary_length))) { return FALSE; } if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(pVary->vary_string), MIN(pVary->vary_length, length))) { return FALSE; } } break; case dtype_cstring: if (xdrs->x_op == XDR_ENCODE) n = static_cast<SSHORT>(MIN(strlen(reinterpret_cast<const char*>(p)), length)); if (!xdr_short(xdrs, &n)) return FALSE; if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(p), n)) return FALSE; if (xdrs->x_op == XDR_DECODE) p[n] = 0; break; case dtype_short: if (!xdr_short(xdrs, (SSHORT *) p)) return FALSE; break; case dtype_long: case dtype_sql_time: case dtype_sql_date: if (!xdr_long(xdrs, (SLONG *) p)) return FALSE; break; case dtype_real: if (!xdr_float(xdrs, (float *) p)) return FALSE; break; case dtype_double: if (!xdr_double(xdrs, (double *) p)) return FALSE; break; case dtype_timestamp: if (!xdr_long(xdrs, &((SLONG*) p)[0])) return FALSE; if (!xdr_long(xdrs, &((SLONG*) p)[1])) return FALSE; break; case dtype_quad: case dtype_blob: if (!xdr_quad(xdrs, (SQUAD*) p)) return FALSE; break; case dtype_int64: if (!xdr_hyper(xdrs, (SINT64*) p)) return FALSE; break; case dtype_boolean: if (!xdr_opaque(xdrs, (SCHAR*) p, length)) return FALSE; break; default: fb_assert(FALSE); return FALSE; } } // Next, get null flags for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; offset = FB_ALIGN(offset, sizeof(SSHORT)); UCHAR* p = data + offset; if (!xdr_short(xdrs, (SSHORT*) p)) return FALSE; offset += sizeof(SSHORT); } return (xdrs->x_private - xdrs->x_base); }
// Parse the messages of a blr request. For specified message, allocate a format (Format) block. void Routine::parseMessages(thread_db* tdbb, CompilerScratch* csb, BlrReader blrReader) { if (blrReader.getLength() < 2) status_exception::raise(Arg::Gds(isc_metadata_corrupt)); csb->csb_blr_reader = blrReader; const SSHORT version = csb->csb_blr_reader.getByte(); switch (version) { case blr_version4: case blr_version5: //case blr_version6: break; default: status_exception::raise( Arg::Gds(isc_metadata_corrupt) << Arg::Gds(isc_wroblrver2) << Arg::Num(blr_version4) << Arg::Num(blr_version5/*6*/) << Arg::Num(version)); } if (csb->csb_blr_reader.getByte() != blr_begin) status_exception::raise(Arg::Gds(isc_metadata_corrupt)); while (csb->csb_blr_reader.getByte() == blr_message) { const USHORT msgNumber = csb->csb_blr_reader.getByte(); USHORT count = csb->csb_blr_reader.getWord(); Format* format = Format::newFormat(*tdbb->getDefaultPool(), count); USHORT padField; const bool shouldPad = csb->csb_message_pad.get(msgNumber, padField); USHORT maxAlignment = 0; ULONG offset = 0; USHORT i = 0; for (Format::fmt_desc_iterator desc = format->fmt_desc.begin(); i < count; ++i, ++desc) { const USHORT align = PAR_desc(tdbb, csb, &*desc); if (align) offset = FB_ALIGN(offset, align); desc->dsc_address = (UCHAR*)(IPTR) offset; offset += desc->dsc_length; maxAlignment = MAX(maxAlignment, align); if (maxAlignment && shouldPad && i + 1 == padField) offset = FB_ALIGN(offset, maxAlignment); } format->fmt_length = offset; switch (msgNumber) { case 0: setInputFormat(format); break; case 1: setOutputFormat(format); break; default: delete format; } } }
RMessage* PARSE_messages(const UCHAR* blr, size_t blr_length) { /************************************** * * P A R S E _ m e s s a g e s * ************************************** * * Functional description * Parse the messages of a blr request. For each message, allocate * a message (msg) and a format (fmt) block. Return the number of * messages found. If an error occurs, return -1; * **************************************/ if (blr_length < 2) return (RMessage*) -1; blr_length -= 2; const SSHORT version = *blr++; if (version != blr_version4 && version != blr_version5) return (RMessage*) -1; if (*blr++ != blr_begin) return 0; RMessage* message = NULL; ULONG net_length = 0; while (*blr++ == blr_message) { if (blr_length < 4) return parse_error(0, message); blr_length -= 4; const USHORT msg_number = *blr++; USHORT count = *blr++; count += (*blr++) << 8; rem_fmt* const format = new rem_fmt(count); #ifdef DEBUG_REMOTE_MEMORY printf("PARSE_messages allocate format %x\n", format); #endif ULONG offset = 0; for (dsc* desc = format->fmt_desc.begin(); count; --count, ++desc) { if (blr_length-- == 0) return parse_error(format, message); USHORT align = 4; switch (*blr++) { case blr_text: if (blr_length < 2) return parse_error(format, message); blr_length -= 2; desc->dsc_dtype = dtype_text; desc->dsc_length = *blr++; desc->dsc_length += (*blr++) << 8; align = type_alignments[dtype_text]; break; case blr_varying: if (blr_length < 2) return parse_error(format, message); blr_length -= 2; desc->dsc_dtype = dtype_varying; desc->dsc_length = *blr++ + sizeof(SSHORT); desc->dsc_length += (*blr++) << 8; align = type_alignments[dtype_varying]; break; case blr_cstring: if (blr_length < 2) return parse_error(format, message); blr_length -= 2; desc->dsc_dtype = dtype_cstring; desc->dsc_length = *blr++; desc->dsc_length += (*blr++) << 8; align = type_alignments[dtype_cstring]; break; // Parse the tagged blr types correctly case blr_text2: if (blr_length < 4) return parse_error(format, message); blr_length -= 4; desc->dsc_dtype = dtype_text; desc->dsc_scale = *blr++; desc->dsc_scale += (*blr++) << 8; desc->dsc_length = *blr++; desc->dsc_length += (*blr++) << 8; align = type_alignments[dtype_text]; break; case blr_varying2: if (blr_length < 4) return parse_error(format, message); blr_length -= 4; desc->dsc_dtype = dtype_varying; desc->dsc_scale = *blr++; desc->dsc_scale += (*blr++) << 8; desc->dsc_length = *blr++ + sizeof(SSHORT); desc->dsc_length += (*blr++) << 8; align = type_alignments[dtype_varying]; break; case blr_cstring2: if (blr_length < 4) return parse_error(format, message); blr_length -= 4; desc->dsc_dtype = dtype_cstring; desc->dsc_scale = *blr++; desc->dsc_scale += (*blr++) << 8; desc->dsc_length = *blr++; desc->dsc_length += (*blr++) << 8; align = type_alignments[dtype_cstring]; break; case blr_short: if (blr_length-- == 0) return parse_error(format, message); desc->dsc_dtype = dtype_short; desc->dsc_length = sizeof(SSHORT); desc->dsc_scale = *blr++; align = type_alignments[dtype_short]; break; case blr_long: if (blr_length-- == 0) return parse_error(format, message); desc->dsc_dtype = dtype_long; desc->dsc_length = sizeof(SLONG); desc->dsc_scale = *blr++; align = type_alignments[dtype_long]; break; case blr_int64: if (blr_length-- == 0) return parse_error(format, message); desc->dsc_dtype = dtype_int64; desc->dsc_length = sizeof(SINT64); desc->dsc_scale = *blr++; align = type_alignments[dtype_int64]; break; case blr_quad: if (blr_length-- == 0) return parse_error(format, message); desc->dsc_dtype = dtype_quad; desc->dsc_length = sizeof(SLONG) * 2; desc->dsc_scale = *blr++; align = type_alignments[dtype_quad]; break; case blr_float: desc->dsc_dtype = dtype_real; desc->dsc_length = sizeof(float); align = type_alignments[dtype_real]; break; case blr_double: case blr_d_float: desc->dsc_dtype = dtype_double; desc->dsc_length = sizeof(double); align = type_alignments[dtype_double]; break; // this case cannot occur as switch paramater is char and blr_blob // is 261. blob_ids are actually passed around as blr_quad. //case blr_blob: // desc->dsc_dtype = dtype_blob; // desc->dsc_length = sizeof (SLONG) * 2; // align = type_alignments [dtype_blob]; // break; case blr_blob2: { if (blr_length < 4) return parse_error(format, message); blr_length -= 4; desc->dsc_dtype = dtype_blob; desc->dsc_length = sizeof(SLONG) * 2; desc->dsc_sub_type = *blr++; desc->dsc_sub_type += (*blr++) << 8; USHORT textType = *blr++; textType += (*blr++) << 8; desc->setTextType(textType); align = type_alignments[dtype_blob]; } break; case blr_timestamp: desc->dsc_dtype = dtype_timestamp; desc->dsc_length = sizeof(SLONG) * 2; align = type_alignments[dtype_timestamp]; break; case blr_sql_date: desc->dsc_dtype = dtype_sql_date; desc->dsc_length = sizeof(SLONG); align = type_alignments[dtype_sql_date]; break; case blr_sql_time: desc->dsc_dtype = dtype_sql_time; desc->dsc_length = sizeof(ULONG); align = type_alignments[dtype_sql_time]; break; case blr_bool: desc->dsc_dtype = dtype_boolean; desc->dsc_length = sizeof(UCHAR); align = type_alignments[dtype_boolean]; break; default: fb_assert(FALSE); return parse_error(format, message); } if (desc->dsc_dtype == dtype_varying) net_length += 4 + ((desc->dsc_length - 2 + 3) & ~3); else net_length += (desc->dsc_length + 3) & ~3; if (align > 1) offset = FB_ALIGN(offset, align); desc->dsc_address = (UCHAR*) (IPTR) offset; offset += desc->dsc_length; } format->fmt_length = offset; format->fmt_net_length = net_length; RMessage* next = new RMessage(format->fmt_length); #ifdef DEBUG_REMOTE_MEMORY printf("PARSE_messages allocate message %x\n", next); #endif next->msg_next = message; message = next; message->msg_address = reinterpret_cast<UCHAR*>(format); message->msg_number = msg_number; } return message; }