/* write ASCII characters converting to UTF16 if needed * returns bytes written */ int iorm_write_utf_ascii(io_desc *iod, char *string, int len) { int outlen, mblen, status; wint_t utf_code; unsigned char *outstart, *out, *top, *outptr, *nextoutptr, *outptrtop, *nextmb; d_rm_struct *rm_ptr; boolean_t ch_set; ESTABLISH_RET_GTMIO_CH(&iod->pair, -1, ch_set); rm_ptr = (d_rm_struct *)iod->dev_sp; assert(NULL != rm_ptr); if (CHSET_UTF8 != iod->ochset) { outstart = outptr = &rm_ptr->outbuf[rm_ptr->out_bytes]; outptrtop = rm_ptr->outbuf + rm_ptr->recordsize; /* buffer is larger than recordsize to allow for EOL */ assert(len <= (&rm_ptr->outbuf[rm_ptr->outbufsize] - outstart)); for (out = (unsigned char*)string, top = out + len, outlen = 0; out < top && outptr <= outptrtop; out = nextmb, outptr = nextoutptr) { nextmb = UTF8_MBTOWC(out, top, utf_code); assert(nextmb == (out + 1)); if (WEOF == utf_code) { iod->dollar.za = 9; UTF8_BADCHAR((int)(nextmb - out), out, top, 0, NULL); } if (CHSET_UTF16BE == iod->ochset) nextoutptr = UTF16BE_WCTOMB(utf_code, outptr); else nextoutptr = UTF16LE_WCTOMB(utf_code, outptr); if (nextoutptr == outptr) { /* invalid codepoint */ iod->dollar.za = 9; UTF8_BADCHAR((int)(nextmb - out), out, top, chset_names[iod->ochset].len, chset_names[iod->ochset].addr); } mblen = (int)(nextoutptr - outptr); outlen += mblen; } } else { outstart = (unsigned char *)string; outlen = len; } if (0 < outlen) { if (rm_ptr->output_encrypted) { REALLOC_CRYPTBUF_IF_NEEDED(outlen); WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, outstart, outlen, pvt_crypt_buf.addr); outptr = (unsigned char *)pvt_crypt_buf.addr; } else outptr = outstart; DOWRITERC_RM(rm_ptr, outptr, outlen, status); ISSUE_NOPRINCIO_IF_NEEDED_RM(status, ==, iod); rm_ptr->write_occurred = TRUE; rm_ptr->out_bytes += outlen; } REVERT_GTMIO_CH(&iod->pair, ch_set); return outlen; }
void jnl_write_aimg_rec(sgmnt_addrs *csa, cw_set_element *cse, uint4 com_csum) { struct_jrec_blk aimg_record; int tmp_jrec_size, jrec_size, zero_len; jnl_format_buffer blk_trailer; /* partial record after the aimg block */ char local_buff[JNL_REC_START_BNDRY + JREC_SUFFIX_SIZE]; jrec_suffix *suffix; blk_hdr_ptr_t buffer, save_buffer; jnl_private_control *jpc; sgmnt_data_ptr_t csd; uint4 cursum; # ifdef GTM_CRYPT char *in, *out; int in_len, gtmcrypt_errno; gd_segment *seg; # endif csd = csa->hdr; assert(csa->now_crit); jpc = csa->jnl; assert(0 != jpc->pini_addr); aimg_record.prefix.jrec_type = JRT_AIMG; aimg_record.prefix.pini_addr = (0 == jpc->pini_addr) ? JNL_HDR_LEN : jpc->pini_addr; aimg_record.prefix.tn = csa->ti->curr_tn; /* At this point jgbl.gbl_jrec_time should be set by the caller */ assert(jgbl.gbl_jrec_time); aimg_record.prefix.time = jgbl.gbl_jrec_time; aimg_record.prefix.checksum = INIT_CHECKSUM_SEED; aimg_record.blknum = cse->blk; /* in case we have a bad block-size, we dont want to write an AIMG larger than the GDS block size (maximum block size) */ buffer = (blk_hdr_ptr_t)cse->new_buff; assert(buffer->bsiz <= csd->blk_size); assert(buffer->bsiz >= SIZEOF(blk_hdr)); aimg_record.bsiz = MIN(csd->blk_size, buffer->bsiz); aimg_record.ondsk_blkver = cse->ondsk_blkver; tmp_jrec_size = (int)FIXED_AIMG_RECLEN + aimg_record.bsiz + JREC_SUFFIX_SIZE; jrec_size = ROUND_UP2(tmp_jrec_size, JNL_REC_START_BNDRY); zero_len = jrec_size - tmp_jrec_size; blk_trailer.buff = local_buff + (JNL_REC_START_BNDRY - zero_len); memset(blk_trailer.buff, 0, zero_len); blk_trailer.record_size = zero_len + JREC_SUFFIX_SIZE; suffix = (jrec_suffix *)&local_buff[JNL_REC_START_BNDRY]; aimg_record.prefix.forwptr = suffix->backptr = jrec_size; suffix->suffix_code = JNL_REC_SUFFIX_CODE; assert(SIZEOF(uint4) == SIZEOF(jrec_suffix)); save_buffer = buffer; # ifdef GTM_CRYPT in_len = aimg_record.bsiz - SIZEOF(*buffer); if (BLK_NEEDS_ENCRYPTION3(csd->is_encrypted, buffer->levl, in_len)) { ASSERT_ENCRYPTION_INITIALIZED; assert(aimg_record.bsiz <= csa->hdr->blk_size); REALLOC_CRYPTBUF_IF_NEEDED(csa->hdr->blk_size); memcpy(pvt_crypt_buf.addr, buffer, SIZEOF(blk_hdr)); /* copy the block header */ in = (char *)(buffer + 1); /* + 1 because `buffer' is of type blk_hdr_ptr_t */ out = pvt_crypt_buf.addr + SIZEOF(blk_hdr); GTMCRYPT_ENCRYPT(csa, csa->encr_key_handle, in, in_len, out, gtmcrypt_errno); if (0 != gtmcrypt_errno) { seg = csa->region->dyn.addr; GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, seg->fname_len, seg->fname); } buffer = (blk_hdr_ptr_t)pvt_crypt_buf.addr; } # endif cursum = jnl_get_checksum((uint4 *)buffer, NULL, aimg_record.bsiz); COMPUTE_AIMG_CHECKSUM(cursum, &aimg_record, com_csum, aimg_record.prefix.checksum); jnl_write(jpc, JRT_AIMG, (jnl_record *)&aimg_record, buffer, &blk_trailer); buffer = save_buffer; }
void iorm_write_utf(mstr *v) { int4 inchars, char_count; /* in characters */ int4 inlen, outbytes, mblen; /* in bytes */ int4 availwidth, usedwidth, mbwidth; /* in display columns */ int status, padsize,fstat_res,save_errno; wint_t utf_code; io_desc *iod; d_rm_struct *rm_ptr; unsigned char *inptr, *top, *nextmb, *outptr, *nextoutptr, *outstart, temppad, temppadarray[2]; char *out_ptr; boolean_t utf8_active = TRUE; /* needed by GTM_IO_WCWIDTH macro */ boolean_t stream, wrap; struct stat statbuf; boolean_t ch_set; iod = io_curr_device.out; ESTABLISH_GTMIO_CH(&io_curr_device, ch_set); rm_ptr = (d_rm_struct *)iod->dev_sp; assert(NULL != rm_ptr); inptr = (unsigned char *)v->addr; inlen = v->len; top = inptr + inlen; if (!rm_ptr->fixed && 0 == iod->dollar.x) rm_ptr->out_bytes = 0; /* user reset $X */ inchars = UTF8_LEN_STRICT(v->addr, v->len); /* validate and get good char count */ if (0 >= inchars) { REVERT_GTMIO_CH(&io_curr_device, ch_set); return; } usedwidth = 0; stream = rm_ptr->stream; wrap = iod->wrap; if (stream && !wrap) { /* For STREAM and NOWRAP, allow the entire record to be written without any record truncations/terminations */ availwidth = inlen; /* calculate worst case requirement of width (in chars) to write out input bytes */ rm_ptr->out_bytes = 0; } else availwidth = iod->width - iod->dollar.x; outbytes = 0; if (CHSET_UTF8 != iod->ochset) { outstart = nextoutptr = outptr = &rm_ptr->outbuf[rm_ptr->out_bytes]; if (!rm_ptr->done_1st_write) { /* get the file size */ FSTAT_FILE(rm_ptr->fildes, &statbuf, fstat_res); if (-1 == fstat_res) { save_errno = errno; rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"), CALLFROM, save_errno); } if (CHSET_UTF16 == iod->ochset) { /* Write BOM but do not count it towards the bytes in the current record */ /* write BOM if file is empty */ if (0 == statbuf.st_size) { memcpy(outptr, UTF16BE_BOM, UTF16BE_BOM_LEN); outbytes = UTF16BE_BOM_LEN; if (rm_ptr->output_encrypted) { REALLOC_CRYPTBUF_IF_NEEDED(outbytes); WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, outstart, outbytes, pvt_crypt_buf.addr); out_ptr = pvt_crypt_buf.addr; } else out_ptr = (char *)outstart; DOWRITERC_RM(rm_ptr, out_ptr, outbytes, status); ISSUE_NOPRINCIO_IF_NEEDED_RM(status, ==, iod); rm_ptr->write_occurred = TRUE; outptr = outstart; rm_ptr->out_bytes = outbytes = 0; /* save UTF16BE_BOM_LEN in bom_num_bytes until bom is checked, but don't indicate that bom has been checked - which still needs to be done for reading the exception is if the file was opened WRITEONLY */ rm_ptr->bom_num_bytes = UTF16BE_BOM_LEN; if (rm_ptr->write_only) rm_ptr->bom_checked = TRUE; } iod->ochset = CHSET_UTF16BE; get_chset_desc(&chset_names[iod->ochset]); }