Пример #1
0
/* Retrieve a named element content and attributes */
char *xml_get_named_with_attributes( const char *xml, const char *name, char *content, size_t sizeof_content, char *attributes, size_t sizeof_attributes )
{
	struct xml_info info;

	xml = xml_find_named( xml, name, &info );
	if ( xml == NULL ) return NULL;

	if ( attributes != NULL ) xml_strcpy( attributes, sizeof_attributes, info.attributes, info.end_of_attributes );
	return xml_strcpy( content, sizeof_content, info.content, info.end_of_content );
}
Пример #2
0
/* Retrieve the content of the given element */
char *xml_get_content( const char *element, char* content, size_t sizeof_content )
{
	struct xml_info info;
	if ( xml_get_element_info( element, &info, STOP_AFTER_CONTENT ) )
		return xml_strcpy( content, sizeof_content, info.content, info.end_of_content );

	return NULL;
}
Пример #3
0
/* Retrieve the name of the given element */
char *xml_get_name( const char *element, char *name, size_t sizeof_name )
{
	struct xml_info info;
	if ( xml_get_element_info( element, &info, STOP_AFTER_NAME ) )
		return xml_strcpy( name, sizeof_name, info.name, info.end_of_name );

	return NULL;
}
Пример #4
0
/* Retrieve the attributes of the given element */
char *_xml_get_attributes( const char *element, char *attributes, size_t sizeof_attributes )
{
	struct xml_info info;
	if ( xml_get_element_info( element, &info, STOP_AFTER_ATTRIBUTES ) )
		return xml_strcpy( attributes, sizeof_attributes, info.attributes, info.end_of_attributes );
	
	return NULL;
}
Пример #5
0
/* Retrieve a named attribute value */
char *xml_get_named_attribute( const char *element, const char *name, char *value, size_t sizeof_value )
{
	struct xml_info info;

	if ( xml_find_named_attribute( element, name, &info ) )
		return xml_strcpy( value, sizeof_value, info.content, info.end_of_content );

	return NULL;
}
Пример #6
0
/********************************************************************
 * FUNCTION output_pattern_diff
 * 
 *  Output the differences report for one pattern clause and
 *  any of its sub-clauses, within a leaf, leaf-list, or 
 *  typedef definition
 *
 * INPUTS:
 *    cp == parameter block to use
 *    oldpat == old internal pattern
 *    newpat == new internal pattern
 *    patnum == index number of pattern in the Q [1 .. N]
 *
 *********************************************************************/
static void
    output_pattern_diff (yangdiff_diffparms_t *cp,
                         const typ_pattern_t *oldpat,
                         const typ_pattern_t *newpat,
                         uint32 patnum)
{
    const ncx_errinfo_t *olderr, *newerr;
    const xmlChar       *oldstr, *newstr;
    xmlChar              buff[NCX_MAX_NUMLEN+16], *p;

    oldstr = (oldpat) ? oldpat->pat_str : NULL;
    newstr = (newpat) ? newpat->pat_str : NULL;

    olderr = (oldpat) ? &oldpat->pat_errinfo : NULL;
    newerr = (newpat) ? &newpat->pat_errinfo : NULL;

    p = buff;
    p += xml_strcpy(p, YANG_K_PATTERN);
    *p++ = ' ';
    *p++ = '[';
    p += (uint32)sprintf((char *)p, "%u", patnum);
    *p++ = ']';
    *p = 0;
    
    if (!oldstr && newstr) {
        /* pattern added in new revision */
        output_diff(cp, buff, oldstr, newstr, FALSE);
        indent_in(cp);
        output_errinfo_diff(cp, olderr, newerr);
        indent_out(cp);
    } else if (oldstr && !newstr) {
        /* pattern removed in new revision */
        output_diff(cp, buff, oldstr, newstr, FALSE);
        indent_in(cp);
        output_errinfo_diff(cp, olderr, newerr);
        indent_out(cp);
    } else if (oldstr && newstr) {
        /* check if pattern changed */
        if (xml_strcmp(oldstr, newstr)) {
            output_diff(cp, buff, oldstr, newstr, FALSE);
            indent_in(cp);
            output_errinfo_diff(cp, olderr, newerr);
            indent_out(cp);
        } else if (errinfo_changed(olderr, newerr)) {
            output_mstart_line(cp, buff, oldstr, FALSE);
            indent_in(cp);
            output_errinfo_diff(cp, olderr, newerr);
            indent_out(cp);
        }
    }

} /* output_pattern_diff */
Пример #7
0
static 
int match_nodes( const mxml_char_t * path, size_t *path_len, mxml_node *n, LIST_TYPE lst )
{
#define XPATH_MAX_LEN 128
	mxml_char_t buffer [XPATH_MAX_LEN];
	const mxml_char_t * slash_ptr = xml_strchr( path, (mxml_char_t)('/') );
	const size_t length = slash_ptr ? (size_t)(slash_ptr - path) : 0;
	match m;

	if ( length >= XPATH_MAX_LEN )
		return -1;

	memset( buffer, 0, XPATH_MAX_LEN * sizeof( mxml_char_t ) );

	//*
	if ( length )
		xml_strncpy( buffer, path, length );
	else 
		xml_strcpy( buffer, path );

	init_str( &m.value );
	init_str( &m.pred.cond_value );
	init_str( &m.pred.value );

	if ( 0 == identify_match( buffer, &m ) )
	{
		if ( 0 != xpath_match( lst, n, &m ) )
			return -1;
		else
		{
			*path_len = length;

			return 0;
		}
	}
	//*/

	return -1;

#undef XPATH_MAX_LEN
}
Пример #8
0
/********************************************************************
 * FUNCTION expand_alias
 * 
 * Check if the first token is an alias name
 * If so, construct a new command line with the alias contents
 *
 * INPUT:
 *   line == command line to check and possibly convert
 *   res == address of return status
 *
 * OUTPUTS:
 *   *res == return status (ERR_NCX_SKIPPED if nothing done)
 *
 * RETURNS:
 *   pointer to malloced command string if *res==NO_ERR
 *   NULL if *res==ERR_NCX_SKIPPED or some real error
 *********************************************************************/
xmlChar *
    expand_alias (xmlChar *line,
                  status_t *res)
{
    xmlChar  *start, *p = line, *newline;
    alias_cb_t *alias;
    uint32    namelen, newlen;
    boolean   done = FALSE;

    /* skip any leading whitespace; not expected from yangcli */
    while (*p && xml_isspace(*p)) {
        p++;
    }
    if (*p == 0) {
        *res = ERR_NCX_SKIPPED;
        return NULL;
    }

    /* look for end of name */
    start = p;
    if (!ncx_valid_fname_ch(*p++)) {
        *res = ERR_NCX_SKIPPED;
        return NULL;
    }
    while (*p && !done) {
        if (xml_isspace(*p)) {
            done = TRUE;
        } else if (!ncx_valid_name_ch(*p)) {
            *res = ERR_NCX_SKIPPED;
            return NULL;
        } else {
            p++;
        }
    }

    /* look for the alias */
    namelen = (uint32)(p - start);
    alias = find_alias(start, namelen);
    if (alias == NULL) {
        *res = ERR_NCX_SKIPPED;
        return NULL;
    }

    /* replace the alias name with its contents and make a new string */
    if (alias->value) {
        newlen = xml_strlen(p) + xml_strlen(alias->value);
    } else {
        newlen = xml_strlen(p);
    }
    newline = m__getMem(newlen + 1);
    if (newline == NULL) {
        *res = ERR_INTERNAL_MEM;
        return NULL;
    }
    start = newline;
    if (alias->value) {
        start += xml_strcpy(start, alias->value);
    }
    xml_strcpy(start, p);

    if (LOGDEBUG2) {
        log_debug2("\nExpanded alias '%s'; new line: '%s'",
                   alias->name, newline);
    }

    *res = NO_ERR;
    return newline;

}  /* expand_alias */
Пример #9
0
/********************************************************************
* FUNCTION set_initial_transaction_id
*
* Set the last_transaction_id for the running config
* Will check for sys:transaction-id leaf in config->root
*
* RETURNS:
*    status
*********************************************************************/
static status_t
    set_initial_transaction_id (void)
{
    cfg_template_t *cfg = cfg_get_config_id(NCX_CFGID_RUNNING);
    if (cfg == NULL) {
        return ERR_NCX_CFG_NOT_FOUND;
    }
    if (cfg->root == NULL) {
        return ERR_NCX_EMPTY_VAL;
    }

    agt_profile_t *profile = agt_get_profile();
    status_t res = NO_ERR;
    boolean  foundfile = FALSE;

    /* figure out which transaction ID file to use */
    if (profile->agt_startup_txid_file == NULL) {
        /* search for the default startup-cfg.xml filename */
        xmlChar *fname = ncxmod_find_data_file(NCX_DEF_STARTUP_TXID_FILE, 
                                               FALSE, &res);
        if (fname == NULL || res != NO_ERR || *fname == 0) {
            /* need to set the default startup transaction ID file name */
            log_debug("\nSetting initial transaction ID file to default");
            if (fname) {
                m__free(fname);
            }
            res = NO_ERR;
            fname = agt_get_startup_filespec(&res);
            if (fname == NULL || res != NO_ERR) {
                if (res == NO_ERR) {
                    res = ERR_NCX_OPERATION_FAILED;
                }
                log_error("\nFailed to set initial transaction ID file (%s)",
                          get_error_string(res));
                if (fname) {
                    m__free(fname);
                }
                return res;
            }
            /* get dir part and append the TXID file name to it */
            uint32 fnamelen = xml_strlen(fname);
            xmlChar *str = &fname[fnamelen - 1];
            while (str >= fname && *str && *str != NCX_PATHSEP_CH) {
                str--;
            }
            if (*str != NCX_PATHSEP_CH) {
                log_error("\nFailed to set initial transaction ID file");
                m__free(fname);
                return ERR_NCX_INVALID_VALUE;
            }

            /* copy base filespec + 1 for the path-sep-ch */
            uint32 baselen = (uint32)(str - fname) + 1;
            uint32 newlen =  baselen + xml_strlen(NCX_DEF_STARTUP_TXID_FILE);
            xmlChar *newstr = m__getMem(newlen + 1);
            if (newstr == NULL) {
                m__free(fname);
                return ERR_INTERNAL_MEM;
            }
            str = newstr;
            str += xml_strncpy(str, fname, baselen);
            xml_strcpy(str, NCX_DEF_STARTUP_TXID_FILE);
            m__free(fname);
            profile->agt_startup_txid_file = newstr; // pass off memory here
        } else {
            foundfile = TRUE;
            profile->agt_startup_txid_file = fname; // pass off memory here
        }
    }

    /* initialize the starting transaction ID in the config module */
    res = agt_cfg_init_transactions(profile->agt_startup_txid_file, foundfile);
    if (res != NO_ERR) {
        log_error("\nError: cfg-init transaction ID failed (%s)",
                  get_error_string(res));
    }
    return res;

} /* set_initial_transaction_id */
Пример #10
0
/********************************************************************
* FUNCTION agt_ses_process_first_ready
*
* Check the readyQ and process the first message, if any
*
* RETURNS:
*     TRUE if a message was processed
*     FALSE if the readyQ was empty
*********************************************************************/
boolean
    agt_ses_process_first_ready (void)
{
    ses_cb_t     *scb;
    ses_ready_t  *rdy;
    ses_msg_t    *msg;
    status_t      res;
    uint32        cnt;
    xmlChar       buff[32];

    rdy = ses_msg_get_first_inready();
    if (!rdy) {
        return FALSE;
    }

    /* get the session control block that rdy is embedded into */
    scb = agtses[rdy->sid];

    if (scb == NULL) {
        log_debug("\nagt_ses: session %d gone", rdy->sid);
        return FALSE;
    }

    log_debug2("\nagt_ses msg ready for session %d", scb->sid);

    /* check the session control block state */
    if (scb->state >= SES_ST_SHUTDOWN_REQ) {
        /* don't process the message or even it mark it
         * It will be cleaned up when the session is freed
         */
        log_debug("\nagt_ses drop input, session %d shutting down", 
                  scb->sid);
        return TRUE;
    }

    /* make sure a message is really there */
    msg = (ses_msg_t *)dlq_firstEntry(&scb->msgQ);
    if (!msg || !msg->ready) {
        SET_ERROR(ERR_INTERNAL_PTR);
        log_error("\nagt_ses ready Q message not correct");
        if (msg && scb->state != SES_ST_INIT) {
            /* do not echo the ncx-connect message */
            cnt = xml_strcpy(buff, 
                             (const xmlChar *)"Incoming msg for session ");
            snprintf((char *)(&buff[cnt]), sizeof(buff) - cnt, "%u", scb->sid);
            ses_msg_dump(msg, buff);
        }
            
        return FALSE;
    } else if (LOGDEBUG2 && scb->state != SES_ST_INIT) {
        cnt = xml_strcpy(buff, 
                         (const xmlChar *)"Incoming msg for session ");
        snprintf((char *)(&buff[cnt]), sizeof(buff) - cnt, "%u", scb->sid);
        ses_msg_dump(msg, buff);
    }

    /* setup the XML parser */
    if (scb->reader) {
            /* reset the xmlreader */
        res = xml_reset_reader_for_session(ses_read_cb,
                                           NULL, 
                                           scb, 
                                           scb->reader);
    } else {
        res = xml_get_reader_for_session(ses_read_cb,
                                         NULL, 
                                         scb, 
                                         &scb->reader);
    }

    /* process the message */
    if (res == NO_ERR) {
        /* process the message 
         * the scb pointer may get deleted !!!
         */
        agt_top_dispatch_msg(&scb);
    } else {
        if (LOGINFO) {
            log_info("\nReset xmlreader failed for session %d (%s)",
                     scb->sid, 
                     get_error_string(res));
        }
        agt_ses_kill_session(scb, 0, SES_TR_OTHER);
        scb = NULL;
    }

    if (scb) {
        /* free the message that was just processed */
        dlq_remove(msg);
        ses_msg_free_msg(scb, msg);


        /* check if any messages left for this session */
        msg = (ses_msg_t *)dlq_firstEntry(&scb->msgQ);
        if (msg && msg->ready) {
            ses_msg_make_inready(scb);
        }
    }

    return TRUE;
    
}  /* agt_ses_process_first_ready */
Пример #11
0
/********************************************************************
 * FUNCTION output_one_type_diff
 * 
 *  Output the differences report for one type section
 *  within a leaf, leaf-list, or typedef definition
 *
 * type_changed should be called first to determine
 * if the type actually changed.  Otherwise a 'M typedef foo'
 * output line will result and be a false positive
 *
 * INPUTS:
 *    cp == parameter block to use
 *    oldtypdef == old internal typedef
 *    newtypdef == new internal typedef
 *
 *********************************************************************/
void
    output_one_type_diff (yangdiff_diffparms_t *cp,
                          typ_def_t *oldtypdef,
                          typ_def_t *newtypdef)
{
    xmlChar            *p, *oldp, *newp;
    const xmlChar      *oldname, *newname;
    const xmlChar      *oldpath, *newpath;
    yangdiff_cdb_t      typcdb[5];
    ncx_btype_t         oldbtyp, newbtyp;
    ncx_tclass_t        oldclass, newclass;
    boolean             isrev;

    isrev = (cp->edifftype==YANGDIFF_DT_REVISION) ? TRUE : FALSE;

    oldclass = oldtypdef->tclass;
    newclass = newtypdef->tclass;

    oldname = typ_get_name(oldtypdef);
    newname = typ_get_name(newtypdef);

    oldbtyp = typ_get_basetype(oldtypdef);
    newbtyp = typ_get_basetype(newtypdef);

    if (oldbtyp == NCX_BT_LEAFREF) {
        oldpath = typ_get_leafref_path(oldtypdef);
    } else {
        oldpath = NULL;
    }
    if (newbtyp==NCX_BT_LEAFREF) {
        newpath = typ_get_leafref_path(newtypdef);
    } else {
        newpath = NULL;
    }

    /* check if there is a module prefix involved
     * in the change.  This may be a false positive
     * if the prefix simply changed
     * create YANG QNames for the type change record
     * use the scratch buffer cp->buff for both strings
     */
    p = cp->buff;
    if (oldtypdef->prefix) {
        oldp = p;
        p += xml_strcpy(p, oldtypdef->prefix);
        *p++ = ':';
        p += xml_strcpy(p, oldname);
        if (oldtypdef->tclass==NCX_CL_NAMED) {
            *p++ = ' ';
            *p++ = '(';
            p += xml_strcpy(p, (const xmlChar *)
                            tk_get_btype_sym(oldbtyp));
            *p++ = ')';
            *p = 0;         
        }
        p++;   /* leave last NULL char in place */
        oldname = oldp;
    }
    if (newtypdef->prefix) {
        newp = p;
        p += xml_strcpy(p, newtypdef->prefix);
        *p++ = ':';
        p += xml_strcpy(p, newname);
        if (newtypdef->tclass==NCX_CL_NAMED) {
            *p++ = ' ';
            *p++ = '(';
            p += xml_strcpy(p, (const xmlChar *)
                            tk_get_btype_sym(newbtyp));
            *p++ = ')';
            *p = 0;
        }
        newname = newp;
    }

    /* Print the type name change set only if it really
     * changed; otherwise force an M line to be printed
     */
    if (str_field_changed(YANG_K_TYPE, oldname, newname, 
                          isrev, &typcdb[0])) {
        output_cdb_line(cp, &typcdb[0]);
    } else {
        output_mstart_line(cp, YANG_K_TYPE, NULL, FALSE);
    }

    /* check invalid change of builtin type */
    if (oldbtyp != newbtyp) {
        /* need to figure out what type changes are really allowed */
        if (!((typ_is_number(oldbtyp) && typ_is_number(newbtyp)) ||
              (typ_is_string(oldbtyp) && typ_is_string(newbtyp)))) {
            /* ses_putstr(cp->scb, (const xmlChar *)" (invalid)"); */
            return;
        }
    }

    /* check if that is all the data requested */
    if (cp->edifftype == YANGDIFF_DT_TERSE) {
        return;
    }

    /* check corner-case, no sub-fields to compare */
    if (oldclass==NCX_CL_BASE && newclass==NCX_CL_BASE) {
        /* type field is a plain builtin like 'int32;' */
        return;
    }

    /* in all modes except 'normal', indent 1 level and
     * show the specific sub-clauses that have changed
     */
    indent_in(cp);

    /* special case -- check leafref here */
    if (oldpath || newpath) {
        output_diff(cp, YANG_K_PATH, oldpath, newpath, FALSE);
    }

    if (typ_is_number(oldbtyp)) {
        output_range_diff(cp, YANG_K_RANGE, oldtypdef, newtypdef);
    } else if (typ_is_string(oldbtyp)) {
        output_range_diff(cp, YANG_K_LENGTH, oldtypdef, newtypdef);
        output_patternQ_diff(cp, oldtypdef, newtypdef);
    } else {
        switch (oldbtyp) {
        case NCX_BT_ENUM:
            output_eb_type_diff(cp, oldtypdef, newtypdef, FALSE);
            break;
        case NCX_BT_BITS:
            output_eb_type_diff(cp, oldtypdef, newtypdef, TRUE);
            break;
        case NCX_BT_UNION:
            output_union_diff(cp, oldtypdef, newtypdef);
            break;
        default:
            ;
        }
    }

    indent_out(cp);

} /* output_one_type_diff */
Пример #12
0
/********************************************************************
* FUNCTION xml_msg_gen_new_prefix
*
* Generate a new namespace prefix
*
* INPUTS:
*    msg  == message to search and generate a prefix for
*    nsid == namespace ID to generate prefix for
*    retbuff == address of return buffer
*    buffsize == buffer size
* OUTPUTS:
*   if *retbuff is NULL it will be created
*   else *retbuff is filled in with the new prefix if NO_ERR
*
* RETURNS:
*    status
*********************************************************************/
status_t
xml_msg_gen_new_prefix (xml_msg_hdr_t *msg,
                        xmlns_id_t  nsid,
                        xmlChar **retbuff,
                        uint32 buffsize)
{
    const xmlChar      *defpfix;
    xmlChar             startch;
    int32               nlen, i;
    xmlChar             numbuff[NCX_MAX_NUMLEN], *buff;
    xmlns_id_t          testid;

#ifdef DEBUG
    if (!msg || !retbuff) {
        return SET_ERROR(ERR_INTERNAL_PTR);
    }
#endif

    if (*retbuff) {
        buff = *retbuff;
    } else {
        buff = m__getMem(NCX_MAX_NUMLEN+1);
        if (!buff) {
            return ERR_INTERNAL_MEM;
        } else {
            buffsize = NCX_MAX_NUMLEN+1;
            *retbuff = buff;
        }
    }

    /* first see if a default prefix was registered with the namespace
     * and use it if not already in the prefix map
     */
    defpfix = xmlns_get_ns_prefix(nsid);
    if (defpfix && *defpfix) {
        testid = find_prefix_val(msg, defpfix);
        if (testid == 0 || testid==nsid) {
            if (xml_strlen(defpfix) < buffsize) {
                xml_strcpy(buff, defpfix);
                return NO_ERR;
            } else {
                return ERR_BUFF_OVFL;
            }
        }
    }

    /* default already in use for something else so generate a prefix */
    nlen = snprintf((char *)numbuff, NCX_MAX_NUMLEN, "%u", (uint32)nsid);
    if (nlen < 0) {
        return ERR_NCX_INVALID_NUM;
    }

    if ((uint32)(nlen+2) >= buffsize) {
        return ERR_BUFF_OVFL;
    }

    /* copy the number to the prefix buffer w/ trailing zero */
    for (i=0; i<=nlen; i++) {
        buff[i+1] = numbuff[i];
    }

    /* set the start letter in the prefix buffer */
    startch = 'n';

    /* try to generate a unique prefix */
    for (i=0; i<=MAX_PREFIX_TRIES; i++) {
        /* adjust the label value */
        buff[0] = startch++;
        if (startch > 'z') {
            startch = 'a';
        }

        /* check if the prefix is in use */
        if (!find_prefix_val(msg, buff)) {
            return NO_ERR;
        }
    }

    return ERR_NCX_OPERATION_FAILED;

}  /* xml_msg_gen_new_prefix */