Ejemplo n.º 1
0
int xml_script_reader_parse(script_t *script) {
    assert(_p_xml_reader);

    /* init list of playlets */
    int idx = 0;
    text_t *cur_text = NULL;
    ptrlist_init(&(script->texts));

    int            ret;
    int            element_type = XML_READER_TYPE_NONE;
    unsigned char *element_name = '\0';


    ret = xmlTextReaderRead(_p_xml_reader);
    while (ret == 1) {
        element_type = xmlTextReaderNodeType(_p_xml_reader);

        if (XML_READER_TYPE_ELEMENT == element_type) {
            element_name = xmlTextReaderLocalName(_p_xml_reader);

            if(!strcmp(XML_POINTER_ELE, (const char *) element_name)) {

                /* starting new text */
                cur_text = text_init();

                /* setting pointer index value. */
                cur_text->pointer_idx = idx++;

                /* setting cpu address value. */
                readPointerAddressAttr(&(cur_text->cpu_address));
            }

            xmlFree(element_name);
        }
        else if (XML_READER_TYPE_END_ELEMENT == element_type) {
            element_name = xmlTextReaderLocalName(_p_xml_reader);

            if(!strcmp(XML_POINTER_ELE, (const char *) element_name)) {
                /* end of text*/
                if(NULL != cur_text)
                    ptrlist_add(&(script->texts), cur_text);
                cur_text = NULL;
            }

            xmlFree(element_name);
        }
        else if (XML_READER_TYPE_CDATA == element_type && NULL != cur_text) {

            readPointerCData(&(cur_text->u8srt));

        }

        ret = xmlTextReaderRead(_p_xml_reader);
    }

    return 0;

}
Ejemplo n.º 2
0
    // Return value: -1 if "state end found", otherwise depth of node
    int XMLReader::gobbleUntilStartElement(xmlTextReaderPtr &reader, const string &name)
    {
        bool state_begin_found = false;
        bool state_end_found   = false;
        int depth              = -1;

        int r = xmlTextReaderRead(reader);
        while ( (r==1) && (!state_begin_found) && (!state_end_found) ) {
            const int type = xmlTextReaderNodeType( reader );
            depth = xmlTextReaderDepth(reader);
            xmlChar *localName = xmlTextReaderLocalName(reader);
            if (type==1) {
                state_begin_found = (xmlStrEqual(localName, BAD_CAST name.c_str()) != 0);
                if (state_begin_found)
                    state_end_found = (xmlTextReaderIsEmptyElement(reader) != 0);
            } else
                if (type==15) {
                    state_end_found = (xmlStrEqual(localName, BAD_CAST name.c_str()) != 0);
                }
            xmlFree(localName);
            r=xmlTextReaderRead(reader);
        }

        if ( r==0)
            state_end_found = true; // It makes no sense to have gotten to the beginning with r==0 at the same time

        return state_begin_found && (!state_end_found) ? depth : -1;
    }
Ejemplo n.º 3
0
static int _oval_test_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context, void *user)
{
	struct oval_test *test = (struct oval_test *)user;
	char *tagname = (char *)xmlTextReaderLocalName(reader);
	int return_code = 0;
	if ((strcmp(tagname, "notes") == 0)) {
		return_code = oval_parser_parse_tag(reader, context, &_oval_test_parse_notes, test);
	} else if ((strcmp(tagname, "object") == 0)) {
		char *object_ref = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "object_ref");
		if (object_ref != NULL) {
			struct oval_definition_model *model = context->definition_model;
			struct oval_object *object = oval_definition_model_get_new_object(model, object_ref);
			oscap_free(object_ref);
			object_ref = NULL;
			oval_test_set_object(test, object);
		}
	} else if ((strcmp(tagname, "state") == 0)) {
		char *state_ref = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "state_ref");
		if (state_ref != NULL) {
			struct oval_definition_model *model = context->definition_model;
			struct oval_state *state = oval_definition_model_get_new_state(model, state_ref);
			oval_test_add_state(test, state);
			oscap_free(state_ref);
			state_ref = NULL;
		}
	} else {
		oscap_dlprintf(DBG_W, "Skipping tag <%s>.\n", tagname);
		return_code = oval_parser_skip_tag(reader, context);
	}

	oscap_free(tagname);
	return return_code;

}
Ejemplo n.º 4
0
static int _oval_affected_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context, void *user)
{
	struct oval_affected *affected = (struct oval_affected *)user;
	int return_code;
	xmlChar *tagname = xmlTextReaderLocalName(reader);
	//xmlChar *namespace = xmlTextReaderNamespaceUri(reader);

	if (strcmp((char *)tagname, "platform") == 0) {
		char *platform = NULL;
		return_code = oscap_parser_text_value(reader, &oscap_text_consumer, &platform);
		if (platform != NULL) {
			oval_affected_add_platform(affected, platform);
			oscap_free(platform);
		}
	} else if (strcmp((char *)tagname, "product") == 0) {
		char *product = NULL;
		return_code = oscap_parser_text_value(reader, &oscap_text_consumer, &product);
		if (product != NULL) {
			oval_affected_add_product(affected, product);
			oscap_free(product);
		}
	} else {
		dI("Skipping tag: %s", tagname);
		return_code = oval_parser_skip_tag(reader, context);
	}
	oscap_free(tagname);
	return return_code;
}
Ejemplo n.º 5
0
/* reader:local_name() */
static int xmlreader_local_name(lua_State *L) {
  xmlreader xr = check_xmlreader(L, 1);
  char *ln = (char*)xmlTextReaderLocalName(xr);
  if (ln) {
    lua_pushstring(L, ln);
    xmlFree(ln);
    return 1;
  } else {
    lua_pushnil(L);
    lua_pushstring(L, "not available");
    return 2;
  }
}
Ejemplo n.º 6
0
    // Return value: true if next node has a sub-tree
    bool XMLReader::nextTypeContainsChildren(xmlTextReaderPtr &reader, const string &section_name, string &name, string &value,
                                     bool &state_end_found, int &depth)
    {
        state_end_found = false;
        depth = -1;
        int r = 1;
        bool done=false, subtree_found=false;
        while ( (r==1) && (!state_end_found) && (!done) ) {
            xmlChar *localName=xmlTextReaderLocalName(reader), *localValue=NULL;
            depth = xmlTextReaderDepth(reader);
            switch ( xmlTextReaderNodeType( reader ) ) {
            case 15:
                state_end_found = (xmlStrEqual(localName, BAD_CAST section_name.c_str()) != 0);
                break;
            case 1:
                r = xmlTextReaderRead(reader);
                if (r==1) {
                    switch ( xmlTextReaderNodeType(reader) ) {
                    case 3:
                        if (!xmlTextReaderHasValue(reader))
                            throw std::runtime_error("Huh?! Expected a value now. This xml should maybe not be valid?!");
                        localValue = xmlTextReaderValue(reader);
                        name = string((char *)localName);
                        value = string((char *)localValue);
                        r = xmlTextReaderRead(reader);
                        done = true;
                        break;
                    case 14:
                        if (!xmlTextReaderHasValue(reader))
                            throw std::runtime_error("Huh?! Expected a value now. This xml should maybe not be valid?!");
                        localValue = xmlTextReaderValue(reader);
                        name = string((char *)localName);
                        value = string((char *)localValue);
                        r = xmlTextReaderRead(reader);
                        done = true;
                        subtree_found = true;
                    }
                }
            } // end of switch (type)
            xmlFree(localName);
            if (localValue!=NULL)
                xmlFree(localValue);
            if (!done)
                r=xmlTextReaderRead(reader);
        }

        if (r==0)
            state_end_found = true; // If r==0, it makes no sense to scan for more stuff...

        return subtree_found;
    }
Ejemplo n.º 7
0
//typedef void (*oval_entity_consumer)(struct oval_entity_node*, void*);
int oval_entity_parse_tag(xmlTextReaderPtr reader,
			  struct oval_parser_context *context, oscap_consumer_func consumer, void *user)
{
	__attribute__nonnull__(context);

	struct oval_entity *entity = oval_entity_new(context->definition_model);
	int return_code = 0;
	oval_datatype_t datatype = oval_datatype_parse(reader, "datatype", OVAL_DATATYPE_STRING);
	oval_operation_t operation = oval_operation_parse(reader, "operation", OVAL_OPERATION_EQUALS);
	int mask = oval_parser_boolean_attribute(reader, "mask", 0);

	char *nil_attr = (char *) xmlTextReaderGetAttributeNs(reader, BAD_CAST "nil", OSCAP_XMLNS_XSI);
	int xsi_nil = oscap_streq(nil_attr, "true") != 0;
	xmlFree(nil_attr);

	oval_entity_type_t type = OVAL_ENTITY_TYPE_UNKNOWN;
	//The value of the type field vs. the complexity of extracting type is arguable
	char *varref = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "var_ref");
	struct oval_value *value = NULL;
	struct oval_variable *variable;
	char *name = (char *)xmlTextReaderLocalName(reader);
	oval_entity_varref_type_t varref_type;
	if (strcmp(name, "var_ref") == 0) {	//special case for <var_ref>
		if (varref == NULL) {
			struct oval_definition_model *model = context->definition_model;
			varref_type = OVAL_ENTITY_VARREF_ELEMENT;
			struct oval_consume_varref_context ctx = {.model = model, .variable = &variable, .value = &value};
			return_code = oscap_parser_text_value(reader, &oval_consume_varref, &ctx);
		} else {
			varref_type = OVAL_ENTITY_VARREF_ATTRIBUTE;
			struct oval_definition_model *model = context->definition_model;
			oval_schema_version_t version = oval_definition_model_get_core_schema_version(model);
			if (oval_schema_version_cmp(version, OVAL_SCHEMA_VERSION(5.6)) > 0) {
				oscap_seterr(OSCAP_EFAMILY_OVAL, "The var_ref attribute for the var_ref entity "
						"of a variable_object is prohibited since OVAL 5.6. Use plain "
						"var_ref instead.");
			}
			variable = oval_definition_model_get_variable(model, varref);
			if (variable == NULL) {
				oscap_seterr(OSCAP_EFAMILY_OVAL,
						"Could not found variable '%s' referenced by var_ref element.", varref);
				return_code = 1;
			} else {
				oscap_free(varref);
				varref = NULL;
				value = NULL;
			}
		}
	} else if (varref == NULL) {
Ejemplo n.º 8
0
static int oval_result_definition_parse(xmlTextReaderPtr reader, struct oval_parser_context *context, void *usr) {
	int return_code = 0;
	xmlChar *localName = xmlTextReaderLocalName(reader);
	struct oval_result_system  *sys = oval_result_definition_get_system((struct oval_result_definition *) usr);
	
	if (strcmp((const char *)localName, "criteria") == 0) {
		return_code = oval_result_criteria_node_parse
		    (reader, context, sys, (oscap_consumer_func) _oval_result_definition_consume_criteria, usr);
	} else if (strcmp((const char *)localName, "message") == 0) {
		return_code = oval_message_parse_tag
		    (reader, context, (oscap_consumer_func) _oval_result_definition_consume_message, usr);
	}
	oscap_free(localName);
	return return_code;
}
Ejemplo n.º 9
0
static int _oval_result_test_parse(xmlTextReaderPtr reader, struct oval_parser_context *context, void **args) {
	int return_code = 0;
	xmlChar *localName = xmlTextReaderLocalName(reader);

	if (strcmp((const char *)localName, "message") == 0) {
		return_code = oval_message_parse_tag(reader, context, (oscap_consumer_func) _oval_test_message_consumer, TEST);
	} else if (strcmp((const char *)localName, "tested_item") == 0) {
		return_code = oval_result_item_parse_tag(reader, context, SYSTEM, (oscap_consumer_func) _oval_test_item_consumer, args);
	} else if (strcmp((const char *)localName, "tested_variable") == 0) {
		return_code = _oval_result_test_binding_parse(reader, context, args);
	} else {
		dW( "Unhandled tag: <%s>.\n", localName);
		oval_parser_skip_tag(reader, context);
	}

	oscap_free(localName);

	return return_code;
}
Ejemplo n.º 10
0
int oval_sysent_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context,
			  oval_sysent_consumer consumer, void *user)
{
	int ret, mask;
	char *tagname;
	struct oval_sysent *sysent;
	oval_datatype_t datatype;
	oval_syschar_status_t status;

	__attribute__nonnull__(context);

	tagname = (char *) xmlTextReaderLocalName(reader);
	if (!strcmp("#text", tagname)) {
		xmlFree(tagname);
		return 0;
	}

	sysent = oval_sysent_new(context->syschar_model);
	oval_sysent_set_name(sysent, tagname);

	mask = oval_parser_boolean_attribute(reader, "mask", 0);
	oval_sysent_set_mask(sysent, mask);

	datatype = oval_datatype_parse(reader, "datatype", OVAL_DATATYPE_STRING);
	oval_sysent_set_datatype(sysent, datatype);

	status = oval_syschar_status_parse(reader, "status", SYSCHAR_STATUS_EXISTS);
        oval_sysent_set_status(sysent, status);

	if (datatype == OVAL_DATATYPE_RECORD)
		ret = oval_parser_parse_tag(reader, context, &_oval_sysent_parse_record_field, sysent);
	else
		ret = oval_parser_text_value(reader, context, &oval_sysent_value_consumer_, sysent);

	if (ret == 0)
		(*consumer) (sysent, user);

	return ret;
}
Ejemplo n.º 11
0
Archivo: marcdump.c Proyecto: nla/yaz
static void marcdump_read_xml(yaz_marc_t mt, const char *fname)
{
    WRBUF wrbuf = wrbuf_alloc();
#if USE_XMLREADER
    xmlTextReaderPtr reader = xmlReaderForFile(fname, 0 /* encoding */,
                                               0 /* options */);

    if (reader)
    {
        int ret;
        while ((ret = xmlTextReaderRead(reader)) == 1)
        {
            int type = xmlTextReaderNodeType(reader);
            if (type == XML_READER_TYPE_ELEMENT)
            {
                const char *name = (const char *)
                    xmlTextReaderLocalName(reader);
                if (!strcmp(name, "record") || !strcmp(name, "r"))
                {
                    xmlNodePtr ptr = xmlTextReaderExpand(reader);

                    int r = yaz_marc_read_xml(mt, ptr);
                    if (r)
                    {
                        no_errors++;
                        fprintf(stderr, "yaz_marc_read_xml failed\n");
                    }
                    else
                    {
                        int write_rc = yaz_marc_write_mode(mt, wrbuf);
                        if (write_rc)
                        {
                            yaz_log(YLOG_WARN, "yaz_marc_write_mode: "
                                    "write error: %d", write_rc);
                            no_errors++;
                        }
                        fputs(wrbuf_cstr(wrbuf), stdout);
                        wrbuf_rewind(wrbuf);
                    }
                }
            }
        }
    }
#else
    xmlDocPtr doc = xmlParseFile(fname);
    if (doc)
    {
        xmlNodePtr ptr = xmlDocGetRootElement(doc);
        for (; ptr; ptr = ptr->next)
        {
            if (ptr->type == XML_ELEMENT_NODE)
            {
                if (!strcmp((const char *) ptr->name, "collection"))
                {
                    ptr = ptr->children;
                    continue;
                }
                if (!strcmp((const char *) ptr->name, "record") ||
                    !strcmp((const char *) ptr->name, "r"))
                {
                    int r = yaz_marc_read_xml(mt, ptr);
                    if (r)
                    {
                        no_errors++;
                        fprintf(stderr, "yaz_marc_read_xml failed\n");
                    }
                    else
                    {
                        yaz_marc_write_mode(mt, wrbuf);

                        fputs(wrbuf_cstr(wrbuf), stdout);
                        wrbuf_rewind(wrbuf);
                    }
                }
            }
        }
        xmlFreeDoc(doc);
    }
#endif
    fputs(wrbuf_cstr(wrbuf), stdout);
    wrbuf_destroy(wrbuf);
}
Ejemplo n.º 12
0
void readConfig( const char* filename ) {
    /* States:
     * 0 : reading new entities ( to: 1, 3, 4, 5 )
     * 1 : reading machine
     * 2 : reading role
     * 3 : reading core
     * 4 : reading file
     * 5 : reading test ( to: 2 )
     */
    int state = 0;

    struct machine m;
    struct role r;
    struct file f;
    struct core c;
    struct test t;

    xmlTextReaderPtr xmlRead = xmlReaderForFile( filename, NULL, XML_PARSE_NONET | XML_PARSE_NOENT | XML_PARSE_NOCDATA | XML_PARSE_NOXINCNODE | XML_PARSE_COMPACT );
    if( !xmlRead )
        quit( "Could not open %s for reading as XML config\n", filename );

    xmlTextReaderSetErrorHandler( xmlRead, xmlErrorHandler, 0 );

    int nodeType, ret;
    xmlChar* nodeName;
    while( 1 ) {
        if( ( ret = xmlTextReaderRead( xmlRead ) ) != 1 ) {
            if( ret < 0 )
                quit( "Error occurred\n" );
            if( state )
                quit( "No more nodes to read, but state is not 0. Incomplete elements.\n" );
            xmlTextReaderClose( xmlRead );
            return;
        }
        nodeType = xmlTextReaderNodeType( xmlRead );
        
        nodeName = NULL;
        switch( nodeType ) {
            case XmlNodeType.Element :
                nodeName = xmlTextReaderLocalName( xmlRead );
                switch( state ) {
                    case 0 :
                        if( !strcmp( nodeName, "machine" ) ) {
                            state = 1;
                            bzero( m, sizeof( struct machine ) );
                            readValidRequiredAttribute( m.name, "machine", "name" );
                            readValidRequiredAttribute( m.address, "machine", "address" );
                            if( !strcmp( m.address, "DAS4" ) ) {
                                readValidRequiredAttribute( m.count, "machine", "DAS4 node count" );
                                char* end = NULL;
                                m.icount = strtol( m.count, &end, 10 );
                                if( end == m.count || *end || m.icount < 1 )
                                    quit( "Invalid DAS4 node count for machine %s\n", m.name );
                            }
                            break;
                        }
                        if( !strcmp( nodeName, "core" ) ) {
                            state = 3;
                            bzero( c, sizeof( struct core ) );
                            readValidRequiredAttribute( c.name, "core", "name" );
                            break;
                        }
                        if( !strcmp( nodeName, "file" ) ) {
                            state = 4;
                            bzero( f, sizeof( struct file ) );
                            readValidRequiredAttribute( f.name, "file", "name" );
                            readValidRequiredAttribute( f.size, "file", "size" );
                            char* end = NULL;
                            f.isize = strtol( f.size, &end, 10 );
                            if( end == f.size || f.isize < 1 )
                                quit( "Invalid size specifier for file %s\n", f.name );
                            if( *end && *(end+1) )
                                quit( "Invalid size specifier for file %s\n", f.name );
                            if( *end ) {
                                switch( *end ) {
                                    case 'b' :
                                    case 'B' :
                                        break;
                                    case 'k' :
                                    case 'K' :
                                        f.isize *= 1024;
                                        break;
                                    case 'm' :
                                    case 'M' :
                                        f.isize *= 1024 * 1024;
                                        break;
                                    case 'g' :
                                    case 'G' :
                                        f.isize *= 1024 * 1024 * 1024;
                                        break;
                                    case 't' :
                                    case 'T' :
                                        f.isize *= 1024 * 1024 * 1024 * 1024;
                                        break;
                                    default :
                                        quit( "Invalid size specifier for file %s\n", f.name );
                                }
                            }
                            if( f.isize > 512 * 1024 * 1024 ) {
                                int p = 512*1024*1024;
                                while( p < f.isize )
                                    p <<= 1;
                                if( p != f.isize )
                                    quit( "Invalid size specifier for file %s: sizes above 512M should be powers of 2\n", f.name );
                            }
                            if( f.isize & 0x3 )
                                quit( "Invalid size specifier for file %s: sizes should be a multiple of 4\n", f.name );
                            break;
                        }
                        if( !strcmp( nodeName, "test" ) ) {
                            state = 5;
                            bzero( t, sizeof( struct test ) );
                            readValidRequiredAttribute( t.name, "test", "name" );
                            break;
                        }
                        break;
                    case 1 :
                        if( !strcmp( nodeName, "tmpDir" ) ) {
                            onlyOne( m.tmpdir, "machine", "tmpDir" );
                            readValidString( m.tmpdir, "temporary directory location" );
                            skipToEndElement( "tmpDir" );
                            break;
                        }
                        if( !strcmp( nodeName, "params" ) ) {
                            onlyOne( m.params, "machine", "params" );
                            readValidString( m.params, "params" );
                            skipToEndElement( "params" );
                            break;
                        }
                        printf( "Unexpected element %s in machine %s\n", nodeName, m.name );
                        break;
                    case 2 :
                        if( !strcmp( nodeName, "machine" ) ) {
                            if( r.machineCount > 255 )
                                quit( "Maximum of 256 machines per role passed on line %d\n", xmlTextReaderGetParserLineNumber( xmlRead ) );
                            readValid( r.machine[r.machineCount], "machine name" );
                            r.machineCount++;
                            skipToEndElement( "machine" );
                            break;
                        }
                        if( !strcmp( nodeName, "user" ) ) {
                            onlyOne( r.user, "role", "user" );
                            readValidString( r.user, "user" );
                            skipToEndElement( "user" );
                            break;
                        }
                        if( !strcmp( nodeName, "core" ) ) {
                            onlyOne( r.core, "role", "core" );
                            readValidString( r.core, "core name" );
                            skipToEndElement( "core" );
                            break;
                        }
                        if( !strcmp( nodeName, "file" ) ) {
                            onlyOne( r.file, "role", "file" );
                            readValidString( r.file, "file name" );
                            skipToEndElement( "file" );
                            break;
                        }
                        if( !strcmp( nodeName, "params" ) ) {
                            onlyOne( r.params, "role", "params" );
                            readValidString( r.params, "params" );
                            skipToEndElement( "params" );
                            break;
                        }
                        printf( "Unexpected element %s in role on line %d\n", nodeName, xmlTextReaderGetParserLineNumber( xmlRead ) );
                        break;
                    case 3 :
                        if( !strcmp( nodeName, "params" ) ) {
                            onlyOne( c.params, "core", "params" );
                            readValidString( c.params, "params" );
                            skipToEndElement( "params" );
                            break;
                        }
                        if( !strcmp( nodeName, "localDir" ) ) {
                            onlyOne( c.localdir, "core", "localDir" );
                            readValidString( c.localdir, "local core directory" );
                            skipToEndElement( "localDir" );
                            break;
                        }
                        if( !strcmp( nodeName, "compilationDir" ) ) {
                            onlyOne( c.compdir, "core", "compilationDir" );
                            readValidString( c.compdir, "relative compilation directory" );
                            skipToEndElement( "compilationDir" );
                            break;
                        }
                        if( !strcmp( nodeName, "program" ) ) {
                            onlyOne( c.program, "core", "program" );
                            readValidString( c.program, "program name" );
                            skipToEndElement( "program" );
                            break;
                        }
                        printf( "Unexpected element %s in core %s\n", nodeName, c.name );
                        skipToEndElement( nodeName );
                        break;
                    case 4 :
                        if( !strcmp( nodeName, "offset" ) ) {
                            onlyOne( c.offset, "file", "offset" );
                            readValidString( c.offset, "offset" );
                            char* end = NULL;
                            f.ioffset = strtol( f.offset, &end, 10 );
                            if( end == f.offset || *end || f.ioffset < 0 || f >= f.isize )
                                quit( "Invalid file offset for file %s\n", f.name );
                            skipToEndElement( "offset" );
                            break;
                        }
                        printf( "Unexpected element %s in file %s\n", nodeName, f.name );
                        skipToEndElement( nodeName );
                        break;
                    case 5 :
                        if( !strcmp( nodeName, "role" ) ) {
                            state = 2;
                            bzero( r, sizeof( struct role ) );
                            readValidRequiredAttribute( r.type, "role", "type" );
                            if( strcmp( r.type, "seed" ) && strcmp( r.type, "leech" ) )
                                quit( "Invalid value for attribute 'type' for role on line %d, expected 'seed' or 'leech'\n", xmlTextReaderGetParserLineNumber( xmlRead ) );
                            break;
                        }
                        quit( "Unexpected element %s in test on line %d\n", nodeName, xmlTextReaderGetParserLineNumber( xmlRead ) );
                    default :
                        quit( "State sanity\n", nodeName );
                }
                break;
            case XmlNodeType.EndElement :
                nodeName = xmlTextReaderLocalName( xmlRead );
                switch( state ) {
                    case 0 :
                        quit( "End element %s found while not in entity\n", nodeName );
                    case 1 :
                        if( !strcmp( nodeName, "machine" ) ) {
                            memcpy( machines + machineCount, &m, sizeof( struct machine ) );
                            machineCount++;
                            state = 0;
                        }
                        break;
                    case 2 :
                        if( !strcmp( nodeName, "role" ) ) {
                            mempcy( t.roles + r.roleCount, &r, sizeof( struct role ) );
                            t.roleCount++;
                            state = 5;
                        }
                        break;
                    case 3 :
                        if( !strcmp( nodeName, "core" ) ) {
                            memcpy( cores + coreCount, &c, sizeof( struct core ) );
                            coreCount++;
                            state = 0;
                        }
                        break;
                    case 4 :
                        if( !strcmp( nodeName, "file" ) ) {
                            memcpy( files + fileCount, &f, sizeof( struct file ) );
                            fileCount++;
                            state = 0;
                        }
                        break;
                    case 5 :
                        if( !strcmp( nodeName, "test" ) ) {
                            memcpy( tests + testCount, &t, sizeof( struct test ) );
                            testCount++;
                            state = 0;
                        }
                        break;
                    default :
                        quit( "State sanity\n" );
                }
            default :
        }
        if( nodeName )
            free( nodeName );
    }
}

void validateConfigAndGenerateScripts( ) {
    int i, j, k, l;
    bool found;

    // == Validate test-role references to machines, cores and files
    // == Also register which machine uses which cores and which files
    for( i = 0; i < testCount; i++ ) {
        for( j = 0; j < tests[i].roleCount; j++ ) {
            // Check for validity of each role's core
            found = false;
            for( k = 0; k < coreCount; k++ ) {
                if( !strcmp( cores[k].name, tests[i].roles[j].core ) ) {
                    found = true;
                    break;
                }
            }
            if( !found )
                quit( "Test %s role %i refers to core %s which does not exist\n", tests[i].name, j, tests[i].roles[j].core );
            // Check for validity of each role's file
            found = false;
            for( k = 0; k < fileCount; k++ ) {
                if( !strcmp( files[k].name, tests[i].roles[j].file ) ) {
                    found = true;
                    break;
                }
            }
            if( !found )
                quit( "Test %s role %i refers to file %s which does not exist\n", tests[i].name, j, tests[i].roles[j].file );
            // Check for validity of each role's machines
            for( l = 0; l < tests[i].roles[j].machineCount; l++ ) {
                found = false;
                for( k = 0; k < machineCount; k++ ) {
                    if( !strcmp( machines[k].name, tests[i].roles[j].machines[l] ) ) {
                        // Machine found: register used core with the machine if needed
                        for( m = 0; m < machines[k].coreCount; m++ ) {
                            if( !strcmp( machines[k].cores[m], tests[i].roles[j].core ) ) {
                                found = true;
                                break;
                            }
                        }
                        if( !found )
                            machines[k].cores[machines[k].coreCount++] = tests[i].roles[j].core;
                        // Machine found: register used file with the machine if needed, only if seeding
                        if( !strcmp( tests[i].roles[j].type, "seed" ) ) {
                            found = false;
                            for( m = 0; m < machines[k].fileCount; m++ ) {
                                if( !strcmp( machines[k].files[m], tests[i].roles[j].file ) ) {
                                    found = true;
                                    break;
                                }
                            }
                            if( !found )
                                machines[k].files[machines[k].fileCount++] = tests[i].roles[j].file;
                        }
                        // Machine found
                        found = true;
                        break;
                    }
                }
                if( !found )
                    quit( "Test %s role %i refers to machine %s which does not exist\n", tests[i].name, j, tests[i].roles[j].machines[l] );
            }
        }
    }

    // Create temporary script
    FILE* script = tmpfile();
    if( !script )
        quit( "Can't create temporary script\n" );
    fprintf( script, "#!/bin/bash\n" );

    // == Check validity of machines and users: can each machine be accessed?
    for( i = 0; i < machineCount; i++ ) {
        // Creates a function in the script for sending command to the machine using ssh
        // Call using
        //    ssh_machine_%i "commands" || cleanup -1
        // where %i is the index of the machine in machines. Also be sure to return non-zero from your commands on error.
        fprintf( script, "function ssh_machine_%i {\n", i );
        if( strcmp( machines[i].address, "DAS4" ) )
            fprintf( script, "    ssh -T -n -o BatchMode=yes -h \"%s\"", machines[i].address );
        else
            fprintf( script, "    ssh -T -n -o BatchMode=yes -h fs3.das4.tudelft.nl" );
        if( machines[i].user )
            fprintf( script, " -l \"%s\"", machines[i].user );
        if( machines[i].params )
            fprintf( script, " %s", machines[i].params );
        fprintf( script, " $1 || return -1;\n" );
        fprintf( script, "}\n" );
        // Creates a function in the script for sending files to the machine using scp
        // Call using
        //    scp_to_machine_%i localfile remotefile
        fprintf( script, "function scp_to_machine_%i {\n", i );
        fprintf( script, "scp -o BatchMode=yes " );
        if( machines[i].params )
            fprintf( script, "%s ", machines[i].params );
        fprintf( script, "$1 ", l );
        if( machines[i].user )
            fprintf( script, "\"%s\"@", machines[i].user );
        if( strcmp( machines[i].address, "DAS4" ) )
            fprintf( script, "\"%s\"", machines[i].address );
        else
            fprintf( script, "fs3.das4.tudelft.nl" );
        fprintf( script, ":$2 || cleanup -1\n", i, l )
        fprintf( script, "}\n" );
        // Creates a function in the script for retrieving files from the machine using scp
        // Call using
        //    scp_from_machine_%i remotefile localfile
        fprintf( script, "function scp_from_machine_%i {\n", i );
        fprintf( script, "scp -o BatchMode=yes " );
        if( machines[i].params )
            fprintf( script, "%s ", machines[i].params );
        if( machines[i].user )
            fprintf( script, "\"%s\"@", machines[i].user );
        if( strcmp( machines[i].address, "DAS4" ) )
            fprintf( script, "\"%s\"", machines[i].address );
        else
            fprintf( script, "fs3.das4.tudelft.nl" );
        fprintf( script, ":$1 $2 || cleanup -1\n", i, l )
        fprintf( script, "}\n" );
        // Checks reachability of machine
        fprintf( script, "ssh_machine_%i || exit -1\n", i );
    }

    // == Check validity of each core: can each core be packaged? Can it be compiled locally and does the program then exist?
    // Create a cleanup file. This file should have code appended to cleanup things when errors occur or testing has finished. See existing code for examples of concatenating to it.
    // The cleanup function is available after this as well. Call it with an exit argument to end the script cleanly.
    fprintf( script, "CLEANUPFILE=`mktemp`\n" );
    fprintf( script, "chmod +x CLEANUPFILE\n" );
    fprintf( script, "[ -x CLEANUPFILE ] || exit -1\n" );
    fprintf( script, "function cleanup {\n" );
    fprintf( script, "    (\ncat <<EOL\nrm $CLEANUPFILE\nEOL\n) >> $CLEANUPFILE\n" );
    fprintf( script, "    . $CLEANUPFILE\n" );
    fprintf( script  "    exit $1\n" );
    fprintf( script, "}\n" );
    // Create a local temporary directory for storage
    fprintf( script, "TARDIR=`mktemp -d`\n[ \"X${TARDIR}X\" == \"XX\" ] && exit -1\n" );
    fprintf( script, "(\ncat <<EOL\n#!/bin/bash\nrm -rf $TARDIR\nEOL\n) >> $CLEANUPFILE\n" );
    fprintf( script, "CURDIR=`pwd`\n" );
    // Create a tarball for the testenvironment in the temporary local storage
    fprintf( script, "make clean || cleanup -1\n" );
    fprintf( script, "tar cf ${TARDIR}/testenvironment.tar . || cleanup -1\n" );
    fprintf( script, "bzip2 ${TARDIR}/testenvironment.tar || cleanup -1\n" );
    // Check whether the needed tools of the testenvironment compile locally
    fprintf( script, "make genfakedata || cleanup -1\n" );
    for( i = 0; i < coreCount; i++ ) {
        if( !cores[i].localdir )
            cores[i].localdir = strdup( "../" );
        // Create a tarball for the core in the temporary local storage
        fprintf( script, "cd %s || cleanup -1\n", cores[i].localdir );
        fprintf( script, "make clean\n" ); // Not checked: SHOULD be available, but...
        fprintf( script, "tar cf ${TARDIR}/core_%i.tar . || cleanup -1\n", i );
        fprintf( script, "bzip2 ${TARDIR}/core_%i.tar || cleanup -1\n", i );
        if( !cores[i].compdir )
            cores[i].compdir = strdup( "testenvironment/" );
        // Check whether the core compiles locally and the program exists after
        fprintf( script, "cd %s || cleanup -1\n", cores[i].compdir );
        fprintf( script, "make || cleanup -1\n" );
        if( !cores[i].program )
            cores[i].program = strdup( "swift" );
        fprintf( script, "[ -x %s ] || cleanup -1\n", cores[i].program );
        fprintf( script, "cd ${CURDIR}\n" );
    }

    // For each file, precalculate the hash
    for( i = 0; i < fileCount; i++ ) {
        // Create some temporary file to write fake data to. These fake data files will be regenerated at each machine since generating is faster than copying.
        size_t size = files[i].isize;
        FILE* data = tmpfile();
        if( !data )
            quit( "can't create temporary data file\n" );
        int datan = fileno( data );
        int filesize;
        if( size > 512*1024*1024 )
            filesize = 512*1024*1024;
        else
            filesize = size;
        if( generateFakeData( datan, filesize ) )
            quit( "could not write fake data\n" );
        
        MemoryHashStorage mhs;
        FileOffsetDataStorage fods( datan, files[i].ioffset );
        if( !fods.valid() )
            quit( "can't read back from temporary data file\n" );
        HashTree ht( fods, Sha1Hash::ZERO, mhs );
        Sha1Hash hash = ht.root_hash();
        if( size > filesize ) {
            MemoryHashStorage mhs2;
            int max = size/filesize;
            for( j = 0; j < max; j++ )
                mhs2.setHash( bin64(0,j), hash );
            int lvl = 0;
            do {
                max >>= 1;
                lvl++;
                for( j = 0; j < max; j++ )
                    mhs2.hashLeftRight( bin64_t(lvl, j) );
            } while( max > 1 );
            files[i].hash = mhs.getHash( bin64_t(lvl, 0) );
        }
        else
Ejemplo n.º 13
0
void processNode(xmlTextReaderPtr reader) 
{
	xmlChar *name;
	xmlChar *wcet;
	xmlChar *period;
	xmlChar *expFuChar;

	name = xmlTextReaderLocalName(reader);
	if (xmlStrcasecmp(name,  (const xmlChar*)"S") == 0) { 
		// Tag de inicio
		if (xmlTextReaderNodeType(reader) == 1) {
			rtsNr = rtsNr + 1;
			
			// Comprueba que el nodo contenga atributos
			if (xmlTextReaderHasAttributes(reader) != 1) {
				fprintf(stderr, "ERROR: `S` tag has no attributes.\n");
				exit(EXIT_FAILURE);
			}
			
			expFuChar = xmlTextReaderGetAttribute(reader,  (const xmlChar*)"U");
			expFu = atof((char*) expFuChar) / 100.0;
			xmlFree(expFuChar);
		}

		// Tag de cierre -- XmlNodeType.EndElement vale 15
		if (xmlTextReaderNodeType(reader) == 15) {
			int flag;
			double diff, diff2;
			flag = 0;
			diff = fabs(fu - expFu);
			diff2 = fabs(fu - gexpFu / 100.0);
			if (diff > delta) {
				if (verbose) {
					fprintf(stderr, "ERROR -- RTS %d, wrong FU: %.5f, expected %.5f (S)\n", 
							rtsNr, fu, expFu);
				}
				invalidFuCnt = invalidFuCnt + 1;
				flag = 1;
			}
			else if (diff2 > delta) {
				if (verbose) {
					fprintf(stderr, "ERROR -- RTS %d, wrong FU: %.5f, expected %.5f (Set)\n", 
							rtsNr, fu, gexpFu / 100.0); 
				}
				// No incrementa el contador si ya se detecto como erroneo
				if (flag == 0) {
					invalidFuCnt = invalidFuCnt + 1;
				}
			}
			else {
				// FU correcto
				validFuCnt = validFuCnt + 1;
			}
			fuArray[rtsNr - 1] = fu;
			fu = 0.0;
			flag = 0;
			
			cont = cont - 1;
		}
	}

	// Tarea
	if (xmlStrcasecmp(name,  (const xmlChar*)"i") == 0) { 
		wcet = xmlTextReaderGetAttribute(reader, (const xmlChar*)"C");
		period = xmlTextReaderGetAttribute(reader, (const xmlChar*)"T");
		fu = fu + atof((char*) wcet) / atof((char*) period);
		xmlFree(wcet);
		xmlFree(period);
	}

	xmlFree(name);
}
Ejemplo n.º 14
0
void getSetInfo(xmlTextReaderPtr reader) 
{
	if (reader == NULL) {
		fprintf(stderr, "Unable to access the file.\n");
		exit(EXIT_FAILURE);
	}

	int ret;
	ret = xmlTextReaderRead(reader);

	// Si no se recupera un siguiente nodo, se termina la ejecución
	if (ret != 1) {
		fprintf(stderr, "ERROR: Unable to parse XML file.\n");
		exit(EXIT_FAILURE);
	}

	xmlChar *name;
	name = xmlTextReaderLocalName(reader);

	// Si el nodo recuperado no corresponde al tag Set, se aborta
	if (xmlStrcasecmp(name,  (const xmlChar*)"Set") != 0) { 
		xmlFree(name);
		fprintf(stderr, "ERROR: No `Set` tag. Invalid XML file.\n");
		exit(EXIT_FAILURE);
	}
	xmlFree(name);
	
	// Comprueba que el nodo contenga atributos
	if (xmlTextReaderHasAttributes(reader) != 1) {
		fprintf(stderr, "ERROR: `Set` tag has no attributes.\n");
		exit(EXIT_FAILURE);
	}

	printf("=== File info ===\n");

	xmlChar *value;

	// Número de grupos de tareas en el archivo
	value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"size");
	expRtsNr = atoi((char*) value);
	printf("Expected number of RTS: %d\n", expRtsNr);
	xmlFree(value);

	// Número de STR a verificar si no se paso opción --limit
	if (cont == 0) {
		cont = expRtsNr;
	}
	limit = cont;

	// Reservamos memoria para almacenar los FU
	fuArray = (double *) malloc(cont * sizeof(double));

	// Cantidad de tareas por cada sistema
	value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"n");
	taskNr = atoi((char*) value);
	printf("Number of tasks per RTS: %d\n", taskNr);
	xmlFree(value);

	// FU para todos los RTS
	if (gexpFu == 0) {
		value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"u");
		if (value == NULL) {
			xmlFree(value);
			fprintf(stderr, "ERROR: `Set` tag has no FU value. Specify one with --fu option.\n");
			exit(EXIT_FAILURE);
		}
		gexpFu = atof((char*) value);
		xmlFree(value);
	}
	printf("Expected FU for all RTS: %.5f (%.3f)\n", gexpFu / 100.0, gexpFu);
	
	printf("RTS to analize: %d\n", cont);

	printf("Delta: %.3f\n", delta);
}
Ejemplo n.º 15
0
int cli_scandmg(cli_ctx *ctx)
{
    struct dmg_koly_block hdr;
    int ret, namelen, ofd;
    size_t maplen, nread;
    off_t pos = 0;
    char *dirname, *tmpfile;
    const char *outdata;
    unsigned int file = 0;
    struct dmg_mish_with_stripes *mish_list = NULL, *mish_list_tail = NULL;
    enum dmgReadState state = DMG_FIND_BASE_PLIST;
    int stateDepth[DMG_MAX_STATE];
#if HAVE_LIBXML2
    xmlTextReaderPtr reader;
#endif

    if (!ctx || !ctx->fmap) {
        cli_errmsg("cli_scandmg: Invalid context\n");
        return CL_ENULLARG;
    }

    maplen = (*ctx->fmap)->real_len;
    pos = maplen - 512;
    if (pos <= 0) {
        cli_dbgmsg("cli_scandmg: Sizing problem for DMG archive.\n");
        return CL_CLEAN;
    }

    /* Grab koly block */
    if (fmap_readn(*ctx->fmap, &hdr, pos, sizeof(hdr)) != sizeof(hdr)) {
        cli_dbgmsg("cli_scandmg: Invalid DMG trailer block\n");
        return CL_EFORMAT;
    }

    /* Check magic */
    hdr.magic = be32_to_host(hdr.magic);
    if (hdr.magic == 0x6b6f6c79) {
        cli_dbgmsg("cli_scandmg: Found koly block @ %ld\n", (long) pos);
    }
    else {
        cli_dbgmsg("cli_scandmg: No koly magic, %8x\n", hdr.magic);
        return CL_EFORMAT;
    }

    hdr.dataForkOffset = be64_to_host(hdr.dataForkOffset);
    hdr.dataForkLength = be64_to_host(hdr.dataForkLength);
    cli_dbgmsg("cli_scandmg: data offset %lu len %d\n", (unsigned long)hdr.dataForkOffset, (int)hdr.dataForkLength);

    hdr.xmlOffset = be64_to_host(hdr.xmlOffset);
    hdr.xmlLength = be64_to_host(hdr.xmlLength);
    if (hdr.xmlLength > (uint64_t)INT_MAX) {
        cli_dbgmsg("cli_scandmg: The embedded XML is way larger than necessary, and probably corrupt or tampered with.\n");
        return CL_EFORMAT;
    }
    if ((hdr.xmlOffset > (uint64_t)maplen) || (hdr.xmlLength > (uint64_t)maplen)
            || (hdr.xmlOffset + hdr.xmlLength) > (uint64_t)maplen) {
        cli_dbgmsg("cli_scandmg: XML out of range for this file\n");
        return CL_EFORMAT;
    }
    cli_dbgmsg("cli_scandmg: XML offset %lu len %d\n", (unsigned long)hdr.xmlOffset, (int)hdr.xmlLength);
    if (hdr.xmlLength == 0) {
        cli_dbgmsg("cli_scandmg: Embedded XML length is zero.\n");
        return CL_EFORMAT;
    }

    /* Create temp folder for contents */
    if (!(dirname = cli_gentemp(ctx->engine->tmpdir))) {
        return CL_ETMPDIR;
    }
    if (mkdir(dirname, 0700)) {
        cli_errmsg("cli_scandmg: Cannot create temporary directory %s\n", dirname);
        free(dirname);
        return CL_ETMPDIR;
    }
    cli_dbgmsg("cli_scandmg: Extracting into %s\n", dirname);

    /* Dump XML to tempfile, if needed */
    if (ctx->engine->keeptmp) {
        int xret;
        xret = dmg_extract_xml(ctx, dirname, &hdr);

        if (xret != CL_SUCCESS) {
            /* Printed err detail inside dmg_extract_xml */
            free(dirname);
            return xret;
        }
    }

    /* scan XML with cli_map_scandesc */
    ret = cli_map_scandesc(*ctx->fmap, (off_t)hdr.xmlOffset, (size_t)hdr.xmlLength, ctx);
    if (ret != CL_CLEAN) {
        cli_dbgmsg("cli_scandmg: retcode from scanning TOC xml: %s\n", cl_strerror(ret));
        if (!ctx->engine->keeptmp)
            cli_rmdirs(dirname);
        free(dirname);
        return ret;
    }

    /* page data from map */
    outdata = fmap_need_off_once_len(*ctx->fmap, hdr.xmlOffset, hdr.xmlLength, &nread);
    if (!outdata || (nread != hdr.xmlLength)) {
        cli_errmsg("cli_scandmg: Failed getting XML from map, len %d\n", (int)hdr.xmlLength);
        if (!ctx->engine->keeptmp)
            cli_rmdirs(dirname);
        free(dirname);
        return CL_EMAP;
    }

    /* time to walk the tree */
    /* plist -> dict -> (key:resource_fork) dict -> (key:blkx) array -> dict */
    /* each of those bottom level dict should have 4 parts */
    /* [ Attributes, Data, ID, Name ], where Data is Base64 mish block */

    /* This is the block where we require libxml2 */
#if HAVE_LIBXML2

    /* XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_COMPACT */
#define DMG_XML_PARSE_OPTS (1 << 1 | 1 << 11 | 1 << 16)

    reader = xmlReaderForMemory(outdata, (int)hdr.xmlLength, "toc.xml", NULL, DMG_XML_PARSE_OPTS);
    if (!reader) {
        cli_dbgmsg("cli_scandmg: Failed parsing XML!\n");
        if (!ctx->engine->keeptmp)
            cli_rmdirs(dirname);
        free(dirname);
        return CL_EFORMAT;
    }

    stateDepth[DMG_FIND_BASE_PLIST] = -1;

    // May need to check for (xmlTextReaderIsEmptyElement(reader) == 0)

    /* Break loop if have return code or reader can't read any more */
    while ((ret == CL_CLEAN) && (xmlTextReaderRead(reader) == 1)) {
        xmlReaderTypes nodeType;
        nodeType = xmlTextReaderNodeType(reader);

        if (nodeType == XML_READER_TYPE_ELEMENT) {
            // New element, do name check
            xmlChar *nodeName;
            int depth;

            depth = xmlTextReaderDepth(reader);
            if (depth < 0) {
                break;
            }
            if ((depth > 50) && SCAN_ALGO) {
                // Possible heuristic, should limit runaway
                cli_dbgmsg("cli_scandmg: Excessive nesting in DMG TOC.\n");
                break;
            }
            nodeName = xmlTextReaderLocalName(reader);
            if (!nodeName)
                continue;
            dmg_parsemsg("read: name %s depth %d\n", nodeName, depth);

            if ((state == DMG_FIND_DATA_MISH)
                    && (depth == stateDepth[state-1])) {
                xmlChar * textValue;
                struct dmg_mish_with_stripes *mish_set;
                /* Reset state early, for continue cases */
                stateDepth[DMG_FIND_KEY_DATA] = -1;
                state--;
                if (xmlStrcmp(nodeName, "data") != 0) {
                    cli_dbgmsg("cli_scandmg: Not blkx data element\n");
                    xmlFree(nodeName);
                    continue;
                }
                dmg_parsemsg("read: Found blkx data element\n");
                /* Pull out data content from text */
                if (xmlTextReaderIsEmptyElement(reader)) {
                    cli_dbgmsg("cli_scandmg: blkx data element is empty\n");
                    xmlFree(nodeName);
                    continue;
                }
                if (xmlTextReaderRead(reader) != 1) {
                    xmlFree(nodeName);
                    break;
                }
                if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) {
                    cli_dbgmsg("cli_scandmg: Next node not text\n");
                    xmlFree(nodeName);
                    continue;
                }
                textValue = xmlTextReaderValue(reader);
                if (textValue == NULL) {
                    xmlFree(nodeName);
                    continue;
                }
                /* Have encoded mish block */
                mish_set = cli_malloc(sizeof(struct dmg_mish_with_stripes));
                if (mish_set == NULL) {
                    ret = CL_EMEM;
                    xmlFree(textValue);
                    xmlFree(nodeName);
                    break;
                }
                ret = dmg_decode_mish(ctx, &file, textValue, mish_set);
                xmlFree(textValue);
                if (ret == CL_EFORMAT) {
                    /* Didn't decode, or not a mish block */
                    ret = CL_CLEAN;
                    xmlFree(nodeName);
                    continue;
                }
                else if (ret != CL_CLEAN) {
                    xmlFree(nodeName);
                    continue;
                }
                /* Add mish block to list */
                if (mish_list_tail != NULL) {
                    mish_list_tail->next = mish_set;
                    mish_list_tail = mish_set;
                }
                else {
                    mish_list = mish_set;
                    mish_list_tail = mish_set;
                }
                mish_list_tail->next = NULL;
            }
            if ((state == DMG_FIND_KEY_DATA)
                    && (depth > stateDepth[state-1])
                    && (xmlStrcmp(nodeName, "key") == 0)) {
                xmlChar * textValue;
                dmg_parsemsg("read: Found key - checking for Data\n");
                if (xmlTextReaderRead(reader) != 1) {
                    xmlFree(nodeName);
                    break;
                }
                if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) {
                    cli_dbgmsg("cli_scandmg: Key node no text\n");
                    xmlFree(nodeName);
                    continue;
                }
                textValue = xmlTextReaderValue(reader);
                if (textValue == NULL) {
                    cli_dbgmsg("cli_scandmg: no value from xmlTextReaderValue\n");
                    xmlFree(nodeName);
                    continue;
                }
                if (xmlStrcmp(textValue, "Data") == 0) {
                    dmg_parsemsg("read: Matched data\n");
                    stateDepth[DMG_FIND_KEY_DATA] = depth;
                    state++;
                }
                else {
                    dmg_parsemsg("read: text value is %s\n", textValue);
                }
                xmlFree(textValue);
            }
            if ((state == DMG_FIND_BLKX_CONTAINER)
                    && (depth == stateDepth[state-1])) {
                if (xmlStrcmp(nodeName, "array") == 0) {
                    dmg_parsemsg("read: Found array blkx\n");
                    stateDepth[DMG_FIND_BLKX_CONTAINER] = depth;
                    state++;
                }
                else if (xmlStrcmp(nodeName, "dict") == 0) {
                    dmg_parsemsg("read: Found dict blkx\n");
                    stateDepth[DMG_FIND_BLKX_CONTAINER] = depth;
                    state++;
                }
                else {
                    cli_dbgmsg("cli_scandmg: Bad blkx, not container\n");
                    stateDepth[DMG_FIND_KEY_BLKX] = -1;
                    state--;
                }
            }
            if ((state == DMG_FIND_KEY_BLKX)
                    && (depth == stateDepth[state-1] + 1)
                    && (xmlStrcmp(nodeName, "key") == 0)) {
                xmlChar * textValue;
                dmg_parsemsg("read: Found key - checking for blkx\n");
                if (xmlTextReaderRead(reader) != 1) {
                    xmlFree(nodeName);
                    break;
                }
                if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT) {
                    cli_dbgmsg("cli_scandmg: Key node no text\n");
                    xmlFree(nodeName);
                    continue;
                }
                textValue = xmlTextReaderValue(reader);
                if (textValue == NULL) {
                    cli_dbgmsg("cli_scandmg: no value from xmlTextReaderValue\n");
                    xmlFree(nodeName);
                    continue;
                }
                if (xmlStrcmp(textValue, "blkx") == 0) {
                    cli_dbgmsg("cli_scandmg: Matched blkx\n");
                    stateDepth[DMG_FIND_KEY_BLKX] = depth;
                    state++;
                }
                else {
                    cli_dbgmsg("cli_scandmg: wanted blkx, text value is %s\n", textValue);
                }
                xmlFree(textValue);
            }
            if ((state == DMG_FIND_DICT_RESOURCE_FORK)
                    && (depth == stateDepth[state-1])) {
                if (xmlStrcmp(nodeName, "dict") == 0) {
                    dmg_parsemsg("read: Found resource-fork dict\n");
                    stateDepth[DMG_FIND_DICT_RESOURCE_FORK] = depth;
                    state++;
                }
                else {
                    dmg_parsemsg("read: Not resource-fork dict\n");
                    stateDepth[DMG_FIND_KEY_RESOURCE_FORK] = -1;
                    state--;
                }
            }
            if ((state == DMG_FIND_KEY_RESOURCE_FORK)
                    && (depth == stateDepth[state-1] + 1)
                    && (xmlStrcmp(nodeName, "key") == 0)) {
                dmg_parsemsg("read: Found resource-fork key\n");
                stateDepth[DMG_FIND_KEY_RESOURCE_FORK] = depth;
                state++;
            }
            if ((state == DMG_FIND_BASE_DICT)
                    && (depth == stateDepth[state-1] + 1)
                    && (xmlStrcmp(nodeName, "dict") == 0)) {
                dmg_parsemsg("read: Found dict start\n");
                stateDepth[DMG_FIND_BASE_DICT] = depth;
                state++;
            }
            if ((state == DMG_FIND_BASE_PLIST) && (xmlStrcmp(nodeName, "plist") == 0)) {
                dmg_parsemsg("read: Found plist start\n");
                stateDepth[DMG_FIND_BASE_PLIST] = depth;
                state++;
            }
            xmlFree(nodeName);
        }
        else if ((nodeType == XML_READER_TYPE_END_ELEMENT) && (state > DMG_FIND_BASE_PLIST)) {
            int significantEnd = 0;
            int depth = xmlTextReaderDepth(reader);
            if (depth < 0) {
                break;
            }
            else if (depth < stateDepth[state-1]) {
                significantEnd = 1;
            }
            else if ((depth == stateDepth[state-1])
                     && (state-1 == DMG_FIND_BLKX_CONTAINER)) {
                /* Special case, ending blkx container */
                significantEnd = 1;
            }
            if (significantEnd) {
                dmg_parsemsg("read: significant end tag, state %d\n", state);
                stateDepth[state-1] = -1;
                state--;
                if ((state-1 == DMG_FIND_KEY_RESOURCE_FORK)
                        || (state-1 == DMG_FIND_KEY_BLKX)) {
                    /* Keys end their own tag (validly) and the next state depends on the following tag */
                    // cli_dbgmsg("read: significant end tag ending prior key state\n");
                    stateDepth[state-1] = -1;
                    state--;
                }
            }
            else {
                dmg_parsemsg("read: not significant end tag, state %d depth %d prior depth %d\n", state, depth, stateDepth[state-1]);
            }
        }
    }

    xmlFreeTextReader(reader);
    xmlCleanupParser();

#else

    cli_dbgmsg("cli_scandmg: libxml2 support is compiled out. It is required for full DMG support.\n");

#endif

    /* Loop over mish array */
    file = 0;
    while ((ret == CL_CLEAN) && (mish_list != NULL)) {
        /* Handle & scan mish block */
        ret = dmg_handle_mish(ctx, file++, dirname, hdr.xmlOffset, mish_list);
        free(mish_list->mish);
        mish_list_tail = mish_list;
        mish_list = mish_list->next;
        free(mish_list_tail);
    }

    /* Cleanup */
    /* If error occurred, need to free mish items and mish blocks */
    while (mish_list != NULL) {
        free(mish_list->mish);
        mish_list_tail = mish_list;
        mish_list = mish_list->next;
        free(mish_list_tail);
    }
    if (!ctx->engine->keeptmp)
        cli_rmdirs(dirname);
    free(dirname);
    return ret;
}