OpenSolaris_b135/cmd/mms/mm/common/mm_types.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <syslog.h>
#include <mms_list.h>
#include <mms_parser.h>
#include <mms_par_impl.h>
#include <libpq-fe.h>
#include <mms_trace.h>
#include <mms_strapp.h>
#include <libxml/parser.h>
#include "mm_db.h"
#include "mm.h"
#include "mm_util.h"
#include "mm_commands.h"
#include "mm_sql.h"
#include "mm_sql_impl.h"
#include "mm_task.h"
#include "mm_path.h"

static char *_SrcFile = __FILE__;

typedef struct mm_type_library mm_type_library_t;
struct mm_type_library {
	mms_list_node_t	mm_library_list_next;
	mms_list_t		mm_library_name_list;
	mms_list_t		mm_shape_name_list;
};

typedef struct mm_type_data mm_type_data_t;
struct mm_type_data {
	int		mm_error;
	int		mm_level;
	int		mm_once;
	mms_list_t		mm_drive_name_list;
	mms_list_t		mm_cart_name_list;
	mms_list_t		mm_library_list;

	mm_type_library_t *cur_lib;
};
static void mm_check_drive_string(char *drive_name);
static void mm_check_cartridge_string(char *cartridge_name);
static void mm_check_cartridgetype_string(char *cartridge_name);
static void mm_check_library_string(char *library_name);
static void mm_check_slottype_string(char *cartridgeshape_name,
    char *cur_library_name);
static int mm_verify_types(mm_type_data_t *type_data);
static int mm_parse_types(mm_type_data_t *type_data, char *fn);
static void mm_parse_type_start_elements(void *xml_type_data,
    const xmlChar *xml_name, const xmlChar **xml_atts);
static void mm_parse_type_end_elements(void *xml_type_data,
    const xmlChar *xml_name);

static mm_db_t *db;


static PGresult *drive_results;
static int num_drive;
static PGresult *cartridge_results;
static int num_cartridge;
static PGresult *library_results;
static int num_library;
static PGresult *slottype_results;
static int num_slottype;
static PGresult *carttype_results;
static int num_carttype;

static void
mm_library_list_destroy(mms_list_t *list) {
	mm_type_library_t *lib_list;
	mm_type_library_t *next_lib_list;

	for (lib_list = mms_list_head(list);
	    lib_list != NULL;
	    lib_list = next_lib_list) {

		mm_char_list_destroy(&lib_list->mm_library_name_list);
		mm_char_list_destroy(&lib_list->mm_shape_name_list);

		next_lib_list =
			mms_list_next(list,
				lib_list);
		mms_list_remove(list,
			    lib_list);
		free(lib_list);
	}

}

static
mm_type_library_t *
mm_alloc_lib_struct() {
	mm_type_library_t *lib;
	lib = (mm_type_library_t *)calloc(1, sizeof (mm_type_library_t));

	if (lib == NULL) {
		printf("could not allocate mem for lib struct");
		exit(1);
	}

	mms_list_create(&lib->mm_library_name_list, sizeof (mm_char_list_t),
	    offsetof(mm_char_list_t, mm_char_list_next));
	mms_list_create(&lib->mm_shape_name_list, sizeof (mm_char_list_t),
	    offsetof(mm_char_list_t, mm_char_list_next));

	return (lib);
}


int
mm_init_types(mm_data_t *mm_data, char *fn)
{
	mm_type_data_t	type_data;

	mms_trace(MMS_DEVP, "types init %s", fn);

	db = &mm_data->mm_db;




	/* Get existing drives/carts/library/slottypes */
	if (mm_db_exec(HERE, db,
	    "select \"DriveString\" "
	    "from \"DRIVELIST\";") != MM_DB_DATA) {
		mms_trace(MMS_ERR,
		    "db error getting drive strings");
		mm_clear_db(&db->mm_db_results);
		return (1);
	} else {
		drive_results = db->mm_db_results;
		num_drive = PQntuples(drive_results);
	}
	if (mm_db_exec(HERE, db,
	    "select \"CartridgeString\" "
	    "from \"CARTRIDGELIST\";") != MM_DB_DATA) {
		mms_trace(MMS_ERR,
		    "db error getting cartridge strings");
		mm_clear_db(&drive_results);
		mm_clear_db(&db->mm_db_results);
		return (1);
	} else {
		cartridge_results = db->mm_db_results;
		num_cartridge = PQntuples(cartridge_results);
	}
	if (mm_db_exec(HERE, db,
	    "select \"LibraryString\" "
	    "from \"LIBRARYLIST\";") != MM_DB_DATA) {
		mms_trace(MMS_ERR,
		    "db error getting library strings");
		mm_clear_db(&drive_results);
		mm_clear_db(&cartridge_results);
		mm_clear_db(&db->mm_db_results);
		return (1);
	} else {
		library_results = db->mm_db_results;
		num_library = PQntuples(library_results);
	}
	if (mm_db_exec(HERE, db,
	    "select \"SlotTypeName\", \"CartridgeShapeName\" "
	    "from \"SLOTTYPE\";") != MM_DB_DATA) {
		mms_trace(MMS_ERR,
		    "db error getting slottype strings");
		mm_clear_db(&drive_results);
		mm_clear_db(&cartridge_results);
		mm_clear_db(&library_results);
		mm_clear_db(&db->mm_db_results);
		return (1);
	} else {
		slottype_results = db->mm_db_results;
		num_slottype = PQntuples(slottype_results);
	}

	if (mm_db_exec(HERE, db,
	    "select \"CartridgeTypeName\", \"CartridgeShapeName\" "
	    "from \"CARTRIDGETYPE\";") != MM_DB_DATA) {
		mms_trace(MMS_ERR,
		    "db error getting CARTRIDGETYPE strings");
		mm_clear_db(&drive_results);
		mm_clear_db(&cartridge_results);
		mm_clear_db(&library_results);
		mm_clear_db(&slottype_results);
		mm_clear_db(&db->mm_db_results);
		return (1);
	} else {
		carttype_results = db->mm_db_results;
		num_carttype = PQntuples(carttype_results);
	}


	memset(&type_data, 0, sizeof (mm_type_data_t));

	/* Create drive cart and library lists */
	mms_list_create(&type_data.mm_drive_name_list, sizeof (mm_char_list_t),
	    offsetof(mm_char_list_t, mm_char_list_next));
	mms_list_create(&type_data.mm_cart_name_list, sizeof (mm_char_list_t),
	    offsetof(mm_char_list_t, mm_char_list_next));
	mms_list_create(&type_data.mm_library_list, sizeof (mm_type_library_t),
	    offsetof(mm_type_library_t, mm_library_list_next));


	type_data.mm_error = 0;

	if (mm_parse_types(&type_data, fn)) {
		mm_clear_db(&drive_results);
		mm_clear_db(&cartridge_results);
		mm_clear_db(&library_results);
		mm_clear_db(&slottype_results);
		mm_clear_db(&carttype_results);
		mm_char_list_destroy(&type_data.mm_drive_name_list);
		mm_char_list_destroy(&type_data.mm_cart_name_list);
		mm_library_list_destroy(&type_data.mm_library_list);

		return (1);
	}


	mms_trace(MMS_DEVP,
	    "parsing types done, verify now");

	if (mm_verify_types(&type_data)) {
		mms_trace(MMS_ERR,
		    "error verifying types");
		mm_clear_db(&drive_results);
		mm_clear_db(&cartridge_results);
		mm_clear_db(&library_results);
		mm_clear_db(&slottype_results);
		mm_clear_db(&carttype_results);

		mm_char_list_destroy(&type_data.mm_drive_name_list);
		mm_char_list_destroy(&type_data.mm_cart_name_list);
		mm_library_list_destroy(&type_data.mm_library_list);
		return (1);
	}

	mms_trace(MMS_DEVP,
	    "types verified successfully, "
	    "type init done");

	mm_clear_db(&drive_results);
	mm_clear_db(&cartridge_results);
	mm_clear_db(&library_results);
	mm_clear_db(&slottype_results);
	mm_clear_db(&carttype_results);

	mm_char_list_destroy(&type_data.mm_drive_name_list);
	mm_char_list_destroy(&type_data.mm_cart_name_list);
	mm_library_list_destroy(&type_data.mm_library_list);

	return (0);
}

static void
mm_types_delete_drive(mm_type_data_t *type_data) {
	mm_char_list_t *node;
	mm_char_list_t *next;

	char		*buf = NULL;

	int		found_one = 0;

	buf = mms_strapp(buf,
	    "delete from \"DRIVELIST\" where ");

	for (node = mms_list_head(&type_data->mm_drive_name_list);
	    node != NULL;
	    node = next) {
		next = mms_list_next(&type_data->mm_drive_name_list, node);
		if (found_one != 0) {
			buf = mms_strapp(buf, " and ");
		}
		found_one = 1;
		buf = mms_strapp(buf, "(\"DriveString\" != '%s') ",
		    node->text);
	}

	if (found_one) {
		buf = mms_strapp(buf, ";");
		if (mm_db_exec(HERE, db, buf) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "mm_types_delete_drive: "
			    "db error deleting from drivelist");
		}
	}
	free(buf);

}

static void
mm_types_delete_cart(mm_type_data_t *type_data) {
	mm_char_list_t *node;
	mm_char_list_t *next;

	char		*buf = NULL;

	int		found_one = 0;

	buf = mms_strapp(buf,
	    "delete from \"CARTRIDGELIST\" where ");

	for (node = mms_list_head(&type_data->mm_cart_name_list);
	    node != NULL;
	    node = next) {
		next = mms_list_next(&type_data->mm_cart_name_list, node);
		if (found_one != 0) {
			buf = mms_strapp(buf, " and ");
		}
		found_one = 1;
		buf = mms_strapp(buf, "(\"CartridgeString\" != '%s') ",
		    node->text);
	}

	if (found_one) {
		buf = mms_strapp(buf, ";");
		if (mm_db_exec(HERE, db, buf) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "mm_types_delete_cart: "
			    "db error deleting from cartlist");
		}

	}
	free(buf);

}

static void
mm_types_delete_library(mm_type_data_t *type_data) {

	mm_type_library_t *lib_list;
	mm_type_library_t *next_lib_list;

	mm_char_list_t *node;
	mm_char_list_t *next;

	mm_char_list_t *node2;
	mm_char_list_t *next2;

	char *lib_buf = NULL;
	char *slottype_buf = NULL;

	int		found_one_lib = 0;
	int		found_one_slottype = 0;

	lib_buf = mms_strapp(lib_buf,
	    "delete from \"LIBRARYLIST\" where ");

	slottype_buf = mms_strapp(slottype_buf,
	    "delete from \"SLOTTYPE\" where ");

	for (lib_list = mms_list_head(&type_data->mm_library_list);
	    lib_list != NULL;
	    lib_list = next_lib_list) {
		next_lib_list =
		    mms_list_next(&type_data->mm_library_list,
		    lib_list);


		for (node = mms_list_head(&lib_list->mm_library_name_list);
		    node != NULL;
		    node = next) {
			next = mms_list_next(&lib_list->
			    mm_library_name_list,
			    node);

			if (found_one_lib != 0) {
				lib_buf = mms_strapp(lib_buf, " and ");
			}
			found_one_lib = 1;
			lib_buf = mms_strapp(lib_buf,
			    "(\"LibraryString\" != '%s') ",
			    node->text);



			for (node2 = mms_list_head(&lib_list->
			    mm_shape_name_list);
			    node2 != NULL;
			    node2 = next2) {
				next2 = mms_list_next(&lib_list->
				    mm_shape_name_list, node2);

				if (found_one_slottype != 0) {
					slottype_buf =
					    mms_strapp(slottype_buf, " and ");
				}
				found_one_slottype = 1;
				slottype_buf = mms_strapp(slottype_buf,
				    "((\"SlotTypeName\" != '%s') and "
				    "(\"CartridgeShapeName\" != '%s')) ",
				    node->text,
				    node2->text);
			}
		}
	}

	if (found_one_lib) {
		lib_buf = mms_strapp(lib_buf, ";");
		if (mm_db_exec(HERE, db, lib_buf) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "mm_types_delete_library: "
			    "db error deleting from librarylist");
		}


	}
	if (found_one_slottype) {
		slottype_buf = mms_strapp(slottype_buf, ";");
		if (mm_db_exec(HERE, db, slottype_buf) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "mm_types_delete_library: "
			    "db error deleting from slottype");
		}
	}
	free(lib_buf);
	free(slottype_buf);

}



static int
mm_verify_types(mm_type_data_t *type_data)
{
	mm_type_library_t *lib_list;
	mm_type_library_t *next_lib_list;

	mm_char_list_t *node;
	mm_char_list_t *next;

	mm_char_list_t *node2;
	mm_char_list_t *next2;


	int		print = 0;
	/* Print out what we have in the lists */
	if (print) {
		mms_trace(MMS_DEVP,
		    "Drive Strings:");
		mm_print_char_list(&type_data->
		    mm_drive_name_list);
	}
	for (node = mms_list_head(&type_data->mm_drive_name_list);
	    node != NULL;
	    node = next) {
		next = mms_list_next(&type_data->mm_drive_name_list, node);
		mm_check_drive_string(node->text);
	}


	if (print) {
		mms_trace(MMS_DEVP,
		    "Cartridge Strings:");
		mm_print_char_list(&type_data->
		    mm_cart_name_list);
	}
	for (node = mms_list_head(&type_data->mm_cart_name_list);
	    node != NULL;
	    node = next) {
		next = mms_list_next(&type_data->mm_cart_name_list, node);
		mm_check_cartridge_string(node->text);
	}


	for (lib_list = mms_list_head(&type_data->mm_library_list);
	    lib_list != NULL;
	    lib_list = next_lib_list) {
		next_lib_list =
		    mms_list_next(&type_data->mm_library_list,
		    lib_list);
		if (print) {
			mms_trace(MMS_DEVP,
			    "Library Strings:");
			mm_print_char_list(&lib_list->
			    mm_library_name_list);
			mms_trace(MMS_DEVP,
			    "Slottype Strings:");
			mm_print_char_list(&lib_list->
			    mm_shape_name_list);
		}

		for (node = mms_list_head(&lib_list->mm_library_name_list);
		    node != NULL;
		    node = next) {
			next = mms_list_next(&lib_list->
			    mm_library_name_list,
			    node);
			mm_check_library_string(node->text);

			for (node2 = mms_list_head(&lib_list->
			    mm_shape_name_list);
			    node2 != NULL;
			    node2 = next2) {
				next2 = mms_list_next(&lib_list->
				    mm_shape_name_list, node2);
				mm_check_slottype_string(node2->text,
				    node->text);

			}
		}

	}

	/* Create the Side1Name column for default types */
	if (mm_db_exec(HERE, db,
	    "ALTER TABLE \"CARTRIDGETYPE\" "
	    "ADD \"Side1Name\" text;") != MM_DB_OK) {
		/* If there is an error ignore it */
		mm_clear_db(&db->mm_db_results);
	}

	for (node = mms_list_head(&type_data->mm_cart_name_list);
	    node != NULL;
	    node = next) {
		next = mms_list_next(&type_data->mm_cart_name_list, node);
		mm_check_cartridgetype_string(node->text);
	}

	/* All strings in xml are now in db */
	/* now delete any strings that are not in the xml */
	mm_types_delete_drive(type_data);
	mm_types_delete_cart(type_data);
	mm_types_delete_library(type_data);


	return (0);
}

static int
mm_parse_types(mm_type_data_t *type_data, char *fn)
{
	xmlSAXHandler	handler;
	memset(&handler, 0, sizeof (xmlSAXHandler));
	handler.startElement = mm_parse_type_start_elements;
	handler.endElement = mm_parse_type_end_elements;
	xmlDefaultSAXHandlerInit();
	xmlSAXUserParseFile(&handler, type_data, fn);
	if (type_data->mm_once == 0) {
		type_data->mm_error = __LINE__;
	}
	if (type_data->mm_error) {
		mms_trace(MMS_ERR, "%s parse - error %d level %d",
		    fn,
		    type_data->mm_error,
		    type_data->mm_level);
	}
	return (type_data->mm_error);


}


static void
mm_check_drive_string(char *drive_name) {
	int i;
	char *cur_drive;
	int matched_drive = 0;

	for (i = 0; i < num_drive; i++) {
		cur_drive = PQgetvalue(drive_results,
		    i, 0);
		if (strcmp(drive_name, cur_drive) == 0) {
			/* already have this drive name */
			matched_drive = 1;
		}
	}

	if (matched_drive == 0) {
		/* Need to add this drive to drive list */
		if (mm_db_exec(HERE, db,
		    "insert into \"DRIVELIST\" "
		    "(\"DriveString\") values('%s');",
		    drive_name) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "error inserting %s "
			    "into DRIVELIST",
			    drive_name);
			mm_clear_db(&db->mm_db_results);
		}
	}
}
static void
mm_check_cartridge_string(char *cartridge_name) {
	int i;
	char *cur_cartridge;
	int matched_cartridge = 0;

	for (i = 0; i < num_cartridge; i++) {
		cur_cartridge = PQgetvalue(cartridge_results,
		    i, 0);
		if (strcmp(cartridge_name, cur_cartridge) == 0) {
			/* already have this cartridge name */
			matched_cartridge = 1;
		}
	}

	if (matched_cartridge == 0) {
		/* Need to add this cartridge to cartridge list */
		if (mm_db_exec(HERE, db,
		    "insert into \"CARTRIDGELIST\" "
		    "(\"CartridgeString\") values('%s');",
		    cartridge_name) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "error inserting %s "
			    "into CARTRIDGELIST",
			    cartridge_name);
			mm_clear_db(&db->mm_db_results);
		}
	}
}

static void
mm_check_cartridgetype_string(char *cartridgeshape_name) {
	int i;
	char *cur_carttype;
	char *cur_cartshape;
	int matched_cartridge = 0;

	for (i = 0; i < num_carttype; i++) {
		cur_carttype = PQgetvalue(carttype_results,
		    i, 0);
		cur_cartshape = PQgetvalue(carttype_results,
		    i, 1);
		if ((strcmp(cartridgeshape_name, cur_carttype) == 0) &&
		    (strcmp(cartridgeshape_name, cur_cartshape) == 0)) {
			/* already have this cartridge name */
			matched_cartridge = 1;
		}
	}

	if (matched_cartridge == 0) {
		/* Need to add this cartridge to cartridge list */
		if (mm_db_exec(HERE, db,
		    "insert into \"CARTRIDGETYPE\" "
		    "(\"CartridgeTypeName\", "
		    "\"CartridgeShapeName\", "
		    "\"Side1Name\", "
		    "\"CartridgeTypeMediaType\") values('%s',"
		    "'%s', 'side 1', 'data');",
		    cartridgeshape_name,
		    cartridgeshape_name) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "error inserting %s "
			    "into CARTRIDGETYPE",
			    cartridgeshape_name);
			mm_clear_db(&db->mm_db_results);
		}
	}
}

static void
mm_check_library_string(char *library_name) {
	int i;
	char *cur_library;
	int matched_library = 0;

	for (i = 0; i < num_library; i++) {
		cur_library = PQgetvalue(library_results,
		    i, 0);
		if (strcmp(library_name, cur_library) == 0) {
			/* already have this library name */
			matched_library = 1;
		}
	}

	if (matched_library == 0) {
		/* Need to add this library to library list */
		if (mm_db_exec(HERE, db,
		    "insert into \"LIBRARYLIST\" "
		    "(\"LibraryString\") values('%s');",
		    library_name) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "error inserting %s "
			    "into LIBRARYLIST",
			    library_name);
			mm_clear_db(&db->mm_db_results);
		}
	}

}

static void
mm_check_slottype_string(char *cartridgeshape_name,
    char *cur_library_name) {
	int i;
	char *cur_slottype;
	char *cur_cartridgeshape;
	int matched_slottype = 0;

	for (i = 0; i < num_slottype; i++) {
		cur_slottype = PQgetvalue(slottype_results,
		    i, 0);
		cur_cartridgeshape = PQgetvalue(slottype_results,
		    i, 1);
		if ((strcmp(cur_library_name, cur_slottype) == 0) &&
		    (strcmp(cartridgeshape_name, cur_cartridgeshape) == 0)) {
			/* already have this slottype name */
			matched_slottype = 1;
		}
	}

	if (matched_slottype == 0) {
		/* Need to add this slottype to slottype list */
		if (mm_db_exec(HERE, db,
		    "insert into \"SLOTTYPE\" "
		    "(\"SlotTypeName\", \"CartridgeShapeName\") "
		    "values('%s', '%s');",
		    cur_library_name,
		    cartridgeshape_name) != MM_DB_OK) {
			mms_trace(MMS_ERR,
			    "error inserting %s, %s "
			    "into SLOTTYPE",
			    cur_library_name,
			    cartridgeshape_name);
		}
	}
}



static void
mm_parse_type_start_elements(void *xml_type_data, const xmlChar *xml_name,
    const xmlChar **xml_atts)
{
	mm_type_data_t	*type_data = (mm_type_data_t *)xml_type_data;
	char		*name = (char *)xml_name;
	char		**atts = (char **)xml_atts;

	mm_type_library_t *new_lib;

	if (type_data->mm_error) {
		return;
	}

	if (type_data->mm_once == 0) {
		type_data->mm_once = 1;
	}

	if (type_data->mm_level == 0 &&
	    strcmp(name, "mm_types") == 0) {
		type_data->mm_level = 1;
		return;
	}

	if (type_data->mm_level == 1 &&
	    strcmp(name, "mm_drive_list") == 0) {
		type_data->mm_level = 2;
		return;
	}
	if (type_data->mm_level == 1 &&
	    strcmp(name, "mm_cartridge_list") == 0) {
		type_data->mm_level = 2;
		return;
	}
	if (type_data->mm_level == 1 &&
	    strcmp(name, "mm_library_list") == 0) {
		type_data->mm_level = 2;
		return;
	}
	if (type_data->mm_level == 2 &&
	    strcmp(name, "mm_library") == 0) {
		type_data->mm_level = 3;
		new_lib = mm_alloc_lib_struct();
		mms_list_insert_tail(&type_data->mm_library_list,
		    new_lib);
		type_data->cur_lib = new_lib;
		return;
	}
	if (type_data->mm_level == 3 &&
	    strcmp(name, "mm_slottype_list") == 0) {
		type_data->mm_level = 4;
		return;
	}
	if (type_data->mm_level == 3 &&
	    strcmp(name, "mm_cartridgeshape_list") == 0) {
		type_data->mm_level = 4;
		return;
	}


	if (type_data->mm_level == 2 &&
	    strcmp(name, "mm_drive_string") == 0) {
		if (atts[0] == NULL || strcmp(atts[0], "value") != 0) {
			type_data->mm_error = __LINE__;
		} else if (atts[1] != NULL) {
			mms_trace(MMS_DEVP,
			    "    mm_drive_string=%s",
			    atts[1]);
			if (mm_add_char(atts[1],
			    &type_data->mm_drive_name_list)) {
				mms_trace(MMS_ERR,
				    "mm_parse_type_start_elements: "
				    "out of mem adding to drive list");
			}

		}
		return;
	}
	if (type_data->mm_level == 2 &&
	    strcmp(name, "mm_cartridge_string") == 0) {
		if (atts[0] == NULL || strcmp(atts[0], "value") != 0) {
			type_data->mm_error = __LINE__;
		} else if (atts[1] != NULL) {
			mms_trace(MMS_DEVP,
			    "    mm_cartridge_string=%s",
			    atts[1]);
			if (mm_add_char(atts[1],
			    &type_data->mm_cart_name_list)) {
				mms_trace(MMS_ERR,
				    "mm_parse_type_start_elements: "
				    "out of mem adding to cart list");
			}

		}
		return;
	}

	if (type_data->mm_level == 4 &&
	    strcmp(name, "mm_slottype") == 0) {
		if (atts[0] == NULL || strcmp(atts[0], "name") != 0) {
			type_data->mm_error = __LINE__;
		} else if (atts[1] != NULL) {
			mms_trace(MMS_DEVP,
			    "    mm_slottype name=%s",
			    atts[1]);
			if (mm_add_char(atts[1],
			    &type_data->cur_lib->mm_library_name_list)) {
				mms_trace(MMS_ERR,
				    "mm_parse_type_start_elements: "
				    "out of mem adding to library list");
			}

		}
		return;
	}
	if (type_data->mm_level == 4 &&
	    strcmp(name, "mm_cartridgeshape") == 0) {
		if (atts[0] == NULL || strcmp(atts[0], "name") != 0) {
			type_data->mm_error = __LINE__;
		} else if (atts[1] != NULL) {
			mms_trace(MMS_DEVP,
			    "    mm_cartridgeshape name=%s",
			    atts[1]);
			if (mm_add_char(atts[1],
			    &type_data->cur_lib->mm_shape_name_list)) {
				mms_trace(MMS_ERR,
				    "mm_parse_type_start_elements: "
				    "out of mem adding to shape list");
			}
		}
		return;
	}

	type_data->mm_error = __LINE__;
}

static void
mm_parse_type_end_elements(void *xml_type_data, const xmlChar *xml_name)
{
	mm_type_data_t	*type_data = (mm_type_data_t *)xml_type_data;
	char		*name = (char *)xml_name;



	if (type_data->mm_level == 2 &&
	    strcmp(name, "mm_drive_list") == 0) {
		type_data->mm_level = 1;
		return;
	}
	if (type_data->mm_level == 2 &&
	    strcmp(name, "mm_cartridge_list") == 0) {
		type_data->mm_level = 1;
		return;
	}
	if (type_data->mm_level == 2 &&
	    strcmp(name, "mm_library_list") == 0) {
		type_data->mm_level = 1;
		return;
	}
	if (type_data->mm_level == 3 &&
	    strcmp(name, "mm_library") == 0) {
		type_data->mm_level = 2;
		type_data->cur_lib = NULL;
		return;
	}
	if (type_data->mm_level == 4 &&
	    strcmp(name, "mm_slottype_list") == 0) {
		type_data->mm_level = 3;
		return;
	}
	if (type_data->mm_level == 4 &&
	    strcmp(name, "mm_cartridgeshape_list") == 0) {
		type_data->mm_level = 3;
		return;
	}

}