/******************************************************************** * FUNCTION new_event_cb * * Malloc and fill in a new event control block * * INPUTS: * modname == module name * event == eventname * cbfn == callback function to use * * RETURNS: * filled in struct or NULL if ERR_INTERNAL_MEM *********************************************************************/ static event_cb_t * new_event_cb (const xmlChar *modname, const xmlChar *event, yangcli_notif_cbfn_t cbfn) { event_cb_t *cb = m__getObj(event_cb_t); if (cb == NULL) { return NULL; } memset(cb, 0x0, sizeof(event_cb_t)); cb->modname = xml_strdup(modname); if (cb->modname == NULL) { free_event_cb(cb); return NULL; } cb->event = xml_strdup(event); if (cb->event == NULL) { free_event_cb(cb); return NULL; } cb->cbfn = cbfn; return cb; } /* new_event_cb */
/******************************************************************** * FUNCTION agt_ses_set_dummy_session_acm * * Set the session ID and username of the user that * will be responsible for the rollback if needed * * INPUTS: * dummy_session == session control block to change * use_sid == Session ID to use for the rollback * * RETURNS: * status *********************************************************************/ status_t agt_ses_set_dummy_session_acm (ses_cb_t *dummy_session, ses_id_t use_sid) { ses_cb_t *scb; assert( dummy_session && "dummy_session is NULL!" ); if (!agt_ses_init_done) { agt_ses_init(); } scb = agtses[use_sid]; if (scb == NULL) { return ERR_NCX_INVALID_VALUE; } dummy_session->rollback_sid = use_sid; /*TODO Quick fix for confirmed-commit/rollback bug. */ /* Needs further investigation. */ dummy_session->sid = use_sid; if (scb == dummy_session) { return NO_ERR; /* skip -- nothing to do */ } if (dummy_session->username && scb->username) { m__free(dummy_session->username); dummy_session->username = NULL; } if (scb->username) { dummy_session->username = xml_strdup(scb->username); if (dummy_session->username == NULL) { return ERR_INTERNAL_MEM; } } if (dummy_session->peeraddr && scb->peeraddr) { m__free(dummy_session->peeraddr); dummy_session->peeraddr = NULL; } if (scb->peeraddr) { dummy_session->peeraddr = xml_strdup(scb->peeraddr); if (dummy_session->peeraddr == NULL) { return ERR_INTERNAL_MEM; } } return NO_ERR; } /* agt_ses_set_dummy_session_acm */
/******************************************************************** * FUNCTION ncx_copy_str * * Copy the contents of str1 to str2 * Supports base types: * NCX_BT_STRING * NCX_BT_INSTANCE_ID * NCX_BT_LEAFREF * * INPUTS: * str1 == first string * str2 == second string * btyp == expected data type * * OUTPUTS: * str2 contains copy of str1 * * RETURNS: * status *********************************************************************/ status_t ncx_copy_str (const ncx_str_t *str1, ncx_str_t *str2, ncx_btype_t btyp) { #ifdef DEBUG if (!str1 || !str2) { return SET_ERROR(ERR_INTERNAL_PTR); } #endif if (!(typ_is_string(btyp) || btyp==NCX_BT_BITS)) { return ERR_NCX_INVALID_VALUE; } if (*str1) { *str2 = xml_strdup(*str1); if (!*str2) { return ERR_INTERNAL_MEM; } } else { *str2 = NULL; } return NO_ERR; } /* ncx_copy_str */
/******************************************************************** * FUNCTION mgr_rpc_new_request * * Malloc and initialize a new mgr_rpc_req_t struct * * INPUTS: * scb == session control block * * RETURNS: * pointer to struct or NULL or memory error *********************************************************************/ mgr_rpc_req_t * mgr_rpc_new_request (ses_cb_t *scb) { mgr_scb_t *mscb; mgr_rpc_req_t *req; char numbuff[NCX_MAX_NUMLEN]; req = m__getObj(mgr_rpc_req_t); if (!req) { return NULL; } memset(req, 0x0, sizeof(mgr_rpc_req_t)); mscb = mgr_ses_get_mscb(scb); sprintf(numbuff, "%u", mscb->next_id); if (mscb->next_id >= MGR_MAX_REQUEST_ID) { mscb->next_id = 0; } else { mscb->next_id++; } req->msg_id = xml_strdup((const xmlChar *)numbuff); if (req->msg_id) { xml_msg_init_hdr(&req->mhdr); xml_init_attrs(&req->attrs); } else { m__free(req); req = NULL; } return req; } /* mgr_rpc_new_request */
/******************************************************************** * FUNCTION agt_cfg_new_auditrec * * Malloc and initialize a new agt_cfg_audit_rec_t struct * * INPUTS: * target == i-i string of edit target * editop == edit operation enum * * RETURNS: * pointer to struct or NULL or memory error *********************************************************************/ agt_cfg_audit_rec_t * agt_cfg_new_auditrec (const xmlChar *target, op_editop_t editop) { agt_cfg_audit_rec_t *auditrec; #ifdef DEBUG if (target == NULL) { SET_ERROR(ERR_INTERNAL_PTR); return NULL; } #endif auditrec = m__getObj(agt_cfg_audit_rec_t); if (!auditrec) { return NULL; } memset(auditrec, 0x0, sizeof(agt_cfg_audit_rec_t)); auditrec->target = xml_strdup(target); if (auditrec->target == NULL) { m__free(auditrec); return NULL; } auditrec->editop = editop; return auditrec; } /* agt_cfg_new_auditrec */
void test_output() { xml_body_ptr body = NULL; xml_table_ptr table = NULL; xml_item_ptr item = NULL; xml_item_attr_ptr attr = NULL; xml_handel handel = NULL; char *buf; int len, i, t_cnt = 1; printf("\n*** test_output ***\n"); /* new body with [t_cnt] tables */ body = xml_body_new(t_cnt); for ( i = 0; i < t_cnt; i++ ) { /* init every table with 1 item, each item 1 attribute */ xml_table_init(body->t_list + i, 1, 1); } /* init xml_body here */ body->unit_code = xml_strdup(body, "场所编码"); table = xml_get_table(body, 0); /* init xml_table[0] here */ table->name = xml_strdup(body, "记录集名称"); item = xml_get_item(table, 0); attr = xml_get_attr(item, 0); /* init xml_item[0].attr[0] */ attr->name = xml_strdup(body, "item1"); attr->value = xml_strdup(body, "值1"); /* get xml buffer */ handel = xml_output(body, &buf, &len); printf("%s", buf); /* clean xml buffer */ xml_output_clean(handel); /* clean body */ xml_body_clean(body); }
static void s_xml_parse_item(xml_body_ptr body, xml_item_ptr item, xmlNodePtr n_item) { xmlAttrPtr n_attr = NULL; int i; for ( i = 0, n_attr = n_item->properties; NULL != n_attr; i++, n_attr = n_attr->next ) { item->attr_list[i].name = xml_strdup(body, (const char *)n_attr->name); item->attr_list[i].value = s_xml_get_attr(body, n_item, (const char *)n_attr->name); } }
/******************************************************************** * FUNCTION ncx_clone_iffeature * * Clone a new ncx_iffeature_t struct * * INPUTS: * srciff == ifffeature struct to clone * RETURNS: * pointer to a malloced ncx_iffeature_t struct, * or NULL if malloc error *********************************************************************/ ncx_iffeature_t * ncx_clone_iffeature (ncx_iffeature_t *srciff) { ncx_iffeature_t *iff; iff = m__getObj(ncx_iffeature_t); if (!iff) { return NULL; } memset(iff, 0x0, sizeof(ncx_iffeature_t)); if (srciff->prefix) { iff->prefix = xml_strdup(srciff->prefix); if (iff->prefix == NULL) { ncx_free_iffeature(iff); return NULL; } } if (srciff->name) { iff->name = xml_strdup(srciff->name); if (iff->name == NULL) { ncx_free_iffeature(iff); return NULL; } } iff->feature = srciff->feature; ncx_set_error(&iff->tkerr, srciff->tkerr.mod, srciff->tkerr.linenum, srciff->tkerr.linepos); //iff->seen not set return iff; } /* ncx_clone_iffeature */
/******************************************************************** * FUNCTION new_feature_entry * * Create a feature_entry_t * * INPUTS: * featstr == feature string parm to use *********************************************************************/ static feature_entry_t * new_feature_entry (const xmlChar *featstr) { uint32 len = 0; boolean splitdone = FALSE; status_t res = split_feature_string(featstr, &len); if (res == NO_ERR) { splitdone = TRUE; } feature_entry_t *feature_entry = m__getObj(feature_entry_t); if (feature_entry == NULL) { return NULL; } memset(feature_entry, 0x0, sizeof(feature_entry_t)); if (splitdone) { feature_entry->modname = xml_strndup(featstr, len); if (feature_entry->modname == NULL) { free_feature_entry(feature_entry); return NULL; } feature_entry->feature = xml_strdup(&featstr[len+1]); if (feature_entry->feature == NULL) { free_feature_entry(feature_entry); return NULL; } } else { feature_entry->feature = xml_strdup(featstr); if (feature_entry->feature == NULL) { free_feature_entry(feature_entry); return NULL; } } return feature_entry; } /* new_feature_entry */
/* 得到xml结点的属性值 */ static char * s_xml_get_attr(xml_body_ptr body, const xmlNodePtr node, const char *name) { xmlChar *value = NULL; char *value_o = NULL; value = xmlGetProp(node, CONST_CAST name); if ( NULL != value ) { value_o = xml_strdup(body, iconv_utf8_to_gbk((char *)value)); xmlFree((void *)value); } return value_o; }
/******************************************************************** * FUNCTION yangapi_new_keyval * * Create a new YANGAPI keyval holder * * INPUTS: * keyval == key valuse string * RETURNS: * pointer to initialized keyval, or NULL if malloc error *********************************************************************/ yangapi_keyval_t * yangapi_new_keyval (const xmlChar *keyval) { yangapi_keyval_t *val = m__getObj(yangapi_keyval_t); if (val) { memset(val, 0x0, sizeof(yangapi_keyval_t)); val->value = xml_strdup(keyval); if (!val->value) { yangapi_free_keyval(val); return NULL; } } return val; } /* yangapi_new_keyval */
/******************************************************************** * FUNCTION new_feature_entry2 * * Create a feature_entry_t * * INPUTS: * modname == module name to use * name == feature name to use *********************************************************************/ static feature_entry_t * new_feature_entry2 (const xmlChar *modname, const xmlChar *name) { feature_entry_t *feature_entry = m__getObj(feature_entry_t); if (feature_entry == NULL) { return NULL; } memset(feature_entry, 0x0, sizeof(feature_entry_t)); feature_entry->modname = xml_strdup(modname); if (feature_entry->modname == NULL) { free_feature_entry(feature_entry); return NULL; } feature_entry->feature = xml_strdup(name); if (feature_entry->feature == NULL) { free_feature_entry(feature_entry); return NULL; } return feature_entry; } /* new_feature_entry2 */
/******************************************************************** * FUNCTION set_alias * * Set an alias value field * * INPUTS: * alias == alias record to use * valstr == value string to use * * RETURNS: * status *********************************************************************/ static status_t set_alias (alias_cb_t *alias, const xmlChar *valstr) { status_t res = NO_ERR; if (alias->value) { m__free(alias->value); alias->value = NULL; } alias->quotes = 0; if (valstr) { if (*valstr == '"' || *valstr == '\'') { /* preseve quotes used */ alias->quotes = (*valstr == '"') ? 2 : 1; /* check trim quoted string */ uint32 len = xml_strlen(valstr); if (len > 2) { const xmlChar *endstr = &valstr[len-1]; if (*endstr == *valstr) { /* remove paired quotes */ alias->value = xml_strndup(valstr+1, len-2); if (alias->value == NULL) { res = ERR_INTERNAL_MEM; } } else { /* improper string; unmatched quotes */ res = ERR_NCX_INVALID_VALUE; } } else { /* else got just a quote char */ res = ERR_NCX_INVALID_VALUE; } } else { alias->value = xml_strdup(valstr); if (alias->value == NULL) { res = ERR_INTERNAL_MEM; } } } /* else cleared value if not already */ return res; } /* set_alias */
static agt_cb_queue_notification_set_t* new_callback_set( const xmlChar *modname ) { agt_cb_queue_notification_set_t* cbSet = m__getObj( agt_cb_queue_notification_set_t ); if ( !cbSet ) { return NULL; } memset( cbSet, 0, sizeof( agt_cb_queue_notification_set_t ) ); cbSet->modname = xml_strdup( modname ); if ( !cbSet->modname ) { m__free( cbSet ); return NULL; } return cbSet; }
/******************************************************************** * FUNCTION consume_node * * Internal consume XML node function * see agt_xml_consume_node for details. * * EXTRA INPUTS: * eoferr == TRUE if an End of File error should be generated * == FALSE if not * nserr == TRUE if bad namespace should be checked * == FALSE if not * clean == TRUE is a string should be cleaned before returned * == FALSE if a string node should be returned as-is * * RETURNS: * status of the operation * Try to fail on fatal errors only *********************************************************************/ static status_t consume_node (ses_cb_t *scb, boolean advance, xml_node_t *node, ncx_layer_t layer, xml_msg_hdr_t *msghdr, boolean eoferr, boolean nserr, boolean clean) { int ret, nodetyp; const xmlChar *badns; xmlChar *valstr, *namestr; uint32 len; status_t res, res2; boolean done; /* init local vars */ done = FALSE; res = NO_ERR; res2 = NO_ERR; badns = NULL; /* loop past any unused xmlTextReader node types */ while (!done) { /* check if a new node should be read */ if (advance) { /* advance the node pointer */ ret = xmlTextReaderRead(scb->reader); if (ret != 1) { /* do not treat this as an internal error */ res = ERR_XML_READER_EOF; if (msghdr && eoferr) { /* generate an operation-failed error */ agt_record_error(scb, msghdr, layer, res, NULL, NCX_NT_NONE, NULL, NCX_NT_NONE, NULL); } return res; } } /* get the node depth to match the end node correctly */ node->depth = xmlTextReaderDepth(scb->reader); if (node->depth == -1) { /* this never actaully happens */ SET_ERROR(ERR_XML_READER_INTERNAL); node->depth = 0; } /* get the internal nodetype, check it and convert it */ nodetyp = xmlTextReaderNodeType(scb->reader); switch (nodetyp) { case XML_ELEMENT_NODE: /* classify element as empty or start */ if (xmlTextReaderIsEmptyElement(scb->reader)) { node->nodetyp = XML_NT_EMPTY; } else { node->nodetyp = XML_NT_START; } done = TRUE; break; case XML_ELEMENT_DECL: node->nodetyp = XML_NT_END; done = TRUE; break; case XML_TEXT_NODE: /* case XML_DTD_NODE: */ node->nodetyp = XML_NT_STRING; done = TRUE; break; default: /* unused node type -- keep trying */ if (LOGDEBUG3) { log_debug3("\nxml_consume_node: skip unused node (%s)", xml_get_node_name(nodetyp)); } advance = TRUE; } } /* finish the node, depending on its type */ switch (node->nodetyp) { case XML_NT_START: case XML_NT_END: case XML_NT_EMPTY: /* get the element QName */ namestr = xml_strdup(xmlTextReaderConstName(scb->reader)); if (!namestr) { res = ERR_INTERNAL_MEM; } else { node->qname = namestr; /* check for namespace prefix in the name * only error returned is unknown-namespace */ len = 0; res = xml_check_ns(scb->reader, namestr, &node->nsid, &len, &badns); if (!nserr && res != NO_ERR) { node->nsid = xmlns_inv_id(); len = 0; res = NO_ERR; } /* set the element name to the char after the prefix, if any */ node->elname = (const xmlChar *)(namestr+len); /* get all the attributes, except for XML_NT_END */ if (res == NO_ERR && node->nodetyp != XML_NT_END) { res2 = get_all_attrs(scb, node, &node->attrs, layer, msghdr, nserr); } /* Set the node module */ if (res == NO_ERR) { if (node->nsid) { node->module = xmlns_get_module(node->nsid); } else { /* no entry, use the default module (ncx) */ node->module = NCX_DEF_MODULE; } } } break; case XML_NT_STRING: /* get the text value -- this is a malloced string */ node->simval = NULL; valstr = xmlTextReaderValue(scb->reader); if (valstr) { if (clean) { node->simfree = xml_copy_clean_string(valstr); } else { node->simfree = xml_strdup(valstr); } if (node->simfree) { node->simlen = xml_strlen(node->simfree); node->simval = (const xmlChar *)node->simfree; } /* see if this is a QName string; if so save the NSID */ xml_check_qname_content(scb->reader, node); xmlFree(valstr); } if (!node->simval) { /* prevent a NULL ptr reference */ node->simval = EMPTY_STRING; node->simlen = 0; node->simfree = NULL; } break; default: break; } if ((res != NO_ERR) && msghdr) { if (badns) { /* generate an operation-failed error */ agt_record_error(scb, msghdr, layer, res, node, NCX_NT_STRING, badns, NCX_NT_NONE, NULL); } else { agt_record_error(scb, msghdr, layer, res, node, NCX_NT_NONE, NULL, NCX_NT_NONE, NULL); } } if (LOGDEBUG4) { log_debug4("\nxml_consume_node: return (%d)", (res==NO_ERR) ? res2 : res); if (scb->state != SES_ST_INIT) { xml_dump_node(node); } } /* return general error first, then attribute error * It doesn't really matter since the caller will * assume all error reports have been queued upon return */ return (res==NO_ERR) ? res2 : res; } /* consume_node */
XMLNODE *XMLParseFile(XSLTGLOBALDATA *gctx, char *file) { info("XMLParseFile:: file %s", file); return xml_parse_file(gctx, xml_strdup(file), 0); }
/******************************************************************** * FUNCTION mgr_rpc_dispatch * * Dispatch an incoming <rpc-reply> response * handle the <rpc-reply> element * called by mgr_top.c: * This function is registered with top_register_node * for the module 'netconf', top-node 'rpc-reply' * * INPUTS: * scb == session control block * top == top element descriptor *********************************************************************/ void mgr_rpc_dispatch (ses_cb_t *scb, xml_node_t *top) { obj_template_t *rpyobj; mgr_rpc_rpy_t *rpy; mgr_rpc_req_t *req; xml_attr_t *attr; xmlChar *msg_id; ncx_module_t *mod; mgr_rpc_cbfn_t handler; ncx_num_t num; status_t res; #ifdef DEBUG if (!scb || !top) { SET_ERROR(ERR_INTERNAL_PTR); return; } #endif /* init local vars */ res = NO_ERR; msg_id = NULL; req = NULL; /* make sure any real session has been properly established */ if (scb->type != SES_TYP_DUMMY && scb->state != SES_ST_IDLE) { log_error("\nError: mgr_rpc: skipping incoming message '%s'", top->qname); mgr_xml_skip_subtree(scb->reader, top); return; } /* check if the reply template is already cached */ rpyobj = NULL; mod = ncx_find_module(NC_MODULE, NULL); if (mod != NULL) { rpyobj = ncx_find_object(mod, NC_RPC_REPLY_TYPE); } if (rpyobj == NULL) { SET_ERROR(ERR_NCX_DEF_NOT_FOUND); mgr_xml_skip_subtree(scb->reader, top); return; } /* get the NC RPC message-id attribute; should be present * because the send-rpc function put a message-id in <rpc> */ attr = xml_find_attr(top, 0, NCX_EL_MESSAGE_ID); if (attr && attr->attr_val) { msg_id = xml_strdup(attr->attr_val); } if (msg_id == NULL) { mgr_xml_skip_subtree(scb->reader, top); log_info("\nmgr_rpc: incoming message with no message-id"); return; } /* the current node is 'rpc-reply' in the netconf namespace * First get a new RPC reply struct */ rpy = new_reply(); if (rpy == NULL) { m__free(msg_id); log_error("\nError: mgr_rpc: skipping incoming message"); mgr_xml_skip_subtree(scb->reader, top); return; } else { rpy->msg_id = msg_id; } /* get the NCX RPC group-id attribute if present */ attr = xml_find_attr(top, xmlns_ncx_id(), NCX_EL_GROUP_ID); if (attr && attr->attr_val) { res = ncx_decode_num(attr->attr_val, NCX_BT_UINT32, &num); if (res == NO_ERR) { rpy->group_id = num.u; } } /* find the request that goes with this reply */ if (rpy->msg_id != NULL) { req = find_request(scb, rpy->msg_id); if (req == NULL) { #ifdef MGR_RPC_DEBUG log_debug("\nmgr_rpc: got request found for msg (%s) " "on session %d", rpy->msg_id, scb->sid); #endif mgr_xml_skip_subtree(scb->reader, top); mgr_rpc_free_reply(rpy); return; } else { dlq_remove(req); } } /* have a request/reply pair, so parse the reply * as a val_value_t tree, stored in rpy->reply */ rpy->res = mgr_val_parse_reply(scb, rpyobj, (req != NULL) ? req->rpc : ncx_get_gen_anyxml(), top, rpy->reply); if (rpy->res != NO_ERR && LOGINFO) { log_info("\nmgr_rpc: got invalid reply on session %d (%s)", scb->sid, get_error_string(rpy->res)); } /* check that there is nothing after the <rpc-reply> element */ if (rpy->res==NO_ERR && !xml_docdone(scb->reader) && LOGINFO) { log_info("\nmgr_rpc: got extra nodes in reply on session %d", scb->sid); } /* invoke the reply handler */ if (req != NULL) { handler = (mgr_rpc_cbfn_t)req->replycb; (*handler)(scb, req, rpy); } /* only reset the session state to idle if was not changed * to SES_ST_SHUTDOWN_REQ during this RPC call */ if (scb->state == SES_ST_IN_MSG) { scb->state = SES_ST_IDLE; } #ifdef MGR_RPC_DEBUG print_errors(); clear_errors(); #endif } /* mgr_rpc_dispatch */
/******************************************************************** * FUNCTION tstamp_convert_to_utctime * * Check if the specified string is a valid dateTime or * date-and-time string is valid and if so, convert it * to * * INPUTS: * buff == pointer to buffer to check * isNegative == address of return negative date flag * res == address of return status * * OUTPUTS: * *isNegative == TRUE if a negative dateTime string is given * FALSE if no starting '-' sign found * *res == return status * * RETURNS: * malloced pointer to converted date time string * or NULL if some error *********************************************************************/ xmlChar * tstamp_convert_to_utctime (const xmlChar *timestr, boolean *isNegative, status_t *res) { assert(timestr && "timestr is NULL!"); assert(isNegative && "isNegative is NULL!"); assert(res && "res is NULL!"); *res = NO_ERR; struct tm convertedtime; memset(&convertedtime, 0x0, sizeof(struct tm)); if (*timestr == '-') { *isNegative = TRUE; timestr++; } else { *isNegative = FALSE; } xmlChar *buffer = NULL; const char *retptr = NULL; uint32 len = xml_strlen(timestr); if (len == 20) { /* could be in canonical form */ retptr = strptime((const char *)timestr, "%FT%TZ", &convertedtime); if (retptr && *retptr == '\0') { buffer = xml_strdup(timestr); if (!buffer) { *res = ERR_INTERNAL_MEM; return NULL; } else { return buffer; } } else { *res = ERR_NCX_INVALID_VALUE; return NULL; } } else if (len > 20) { retptr = strptime((const char *)timestr, "%FT%T", &convertedtime); if (retptr == NULL || *retptr == '\0') { *res = ERR_NCX_INVALID_VALUE; return NULL; } /* check is frac-seconds entered, and skip it */ if (*retptr == '.') { retptr++; if (!isdigit((int)*retptr)) { *res = ERR_NCX_INVALID_VALUE; return NULL; } retptr++; /* got a start digit */ while (isdigit((int)*retptr)) { retptr++; } } /* check if a timezone offset is present */ retptr = strptime(retptr, "%z", &convertedtime); if (retptr == NULL) { *res = ERR_NCX_INVALID_VALUE; return NULL; } /* check where retptr ended up */ if (*retptr == '\0') { /* OK read all the bytes */ ; } else if (*retptr == ':') { if (strcmp(retptr, ":00")) { /* the linux strptime function does * not process the 'time-minute' field in the * time string; since this is so rare * just treat as a special error */ *res = ERR_NCX_OPERATION_NOT_SUPPORTED; return NULL; } /* else time-minute field == '00' and no error */ } else { *res = ERR_NCX_INVALID_VALUE; return NULL; } buffer = m__getMem(TSTAMP_MIN_SIZE); if (!buffer) { *res = ERR_INTERNAL_MEM; return NULL; } time_t utime = mktime(&convertedtime); if (utime == (utime)-1) { *res = ERR_NCX_INVALID_VALUE; m__free(buffer); return NULL; } struct tm *curtime = gmtime(&utime); time_to_string(curtime, buffer); return buffer; } else { /* improper length */ *res = ERR_NCX_INVALID_VALUE; return NULL; } } /* tstamp_convert_to_utctime */