diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libtnf | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libtnf')
27 files changed, 4286 insertions, 0 deletions
diff --git a/usr/src/lib/libtnf/Makefile b/usr/src/lib/libtnf/Makefile new file mode 100644 index 0000000000..523845a683 --- /dev/null +++ b/usr/src/lib/libtnf/Makefile @@ -0,0 +1,149 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libtnf/Makefile +# + +LIBRARY= libtnf.a +VERS= .1 +OBJECTS= $(MACH)dep.o \ + ref.o \ + abi.o \ + util.o \ + info.o \ + datum.o \ + record.o \ + scalar.o \ + array.o \ + struct.o \ + type.o \ + error.o \ + access.o \ + reader.o + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +check := TARGET= check +install := TARGET= install +lint := TARGET= lint +install_h := TARGET= install_h +_msg := TARGET= _msg + + +include ../Makefile.lib + +TEXT_DOMAIN= SUNW_OST_OSLIB +XGETFLAGS= -a +POFILE= $(LIBRARY:%.a=%.po) +POFILES= _error.po + +SED= sed +GREP= grep +CP= cp + +LIBS= $(DYNLIB) + +MAPDIR= ./spec/$(MACH) +MAPFILE= $(MAPDIR)/mapfile +MAPOPTS= $(MAPFILE:%=-M%) +DYNFLAGS += $(MAPOPTS) +CLOBBERFILES += $(MAPFILE) + +LDLIBS += -lc + +HDRS= tnf.h +ROOTHDRDIR= $(ROOT)/usr/include/tnf +ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%) +CHECKHDRS= $(HDRS:%.h=%.check) +$(ROOTHDRS) := FILEMODE = 0644 +CHECKHDRS = $(HDRS:%.h=%.check) + +$(ROOTHDRS) := FILEMODE = 644 + +CPPFLAGS += -D_DATUM_MACROS -D_REENTRANT + +LINTFLAGS += -y + +$(DYNLIB): $(MAPFILE) + +$(MAPFILE): + @cd $(MAPDIR); $(MAKE) mapfile + + +.KEEP_STATE: + +all: spec .WAIT $(LIBS) + +install: all spec $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) + +install_h: $(ROOTHDRDIR) $(ROOTHDRS) + +clean clobber: spec $(BUILD64) + +lint: + $(LINT.c) $(SRCS) + +check: $(CHECKHDRS) + +$(ROOTLIBDIR) $(ROOTHDRDIR): + $(INS.dir) + +$(ROOTHDRDIR)/% : % + $(INS.file) + +ASFLAGS= $(AS_PICFLAGS) -P -D_SYS_SYS_S -D_LOCORE -D_ASM -DPIC -DLOCORE $(CPPFLAGS) +BUILD.s= $(AS) $(ASFLAGS) $< -o $@ + +pics/%.o: ./%.s + $(BUILD.s) + $(POST_PROCESS_O) + +objs/%.o: ./%.s + $(BUILD.s) + $(POST_PROCESS_O) + +_msg: $(MSGDOMAIN) $(POFILE) + $(RM) $(MSGDOMAIN)/$(POFILE) + $(CP) $(POFILE) $(MSGDOMAIN) + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext *.[ch]*` + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +include ../Makefile.targ + +spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/libtnf/abi.c b/usr/src/lib/libtnf/abi.c new file mode 100644 index 0000000000..a50068eba5 --- /dev/null +++ b/usr/src/lib/libtnf/abi.c @@ -0,0 +1,578 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * Operations based on ABI bootstrap assumptions + */ + +#define _GET_TAG(tnf, p) \ + _GET_REF32(tnf, p) + +#define _GET_TAG_ARG(tnf, p) \ + _GET_REF16(tnf, p) + +#define _GET_SELF_SIZE(tnf, p) \ + _GET_UINT32(tnf, &((struct tnf_array_hdr *)(p))->self_size) + +#define _GET_NAME(tnf, p) \ + _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->name) + +#define _GET_PROPERTIES(tnf, p) \ + _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->properties) + +#define _GET_SLOT_TYPES(tnf, p) \ + _GET_REF32(tnf, &((struct tnf_struct_type_hdr *)(p))->slot_types) + +#define _GET_TYPE_SIZE(tnf, p) \ + _GET_UINT32(tnf, &((struct tnf_struct_type_hdr *)(p))->type_size) + +#define _GET_HEADER_SIZE(tnf, p) \ + _GET_UINT32(tnf, &((struct tnf_array_type_hdr *)(p))->header_size) + +#define _GET_DERIVED_BASE(tnf, p) \ + _GET_REF32(tnf, &((struct tnf_derived_type_hdr *)(p))->derived_base) + +/* + * Static declarations + */ + +static caddr_t fetch_slot(TNF *, caddr_t, tnf_ref32_t *); + +/* + * retrieve tag slot from a record + */ + +tnf_ref32_t * +_tnf_get_tag(TNF *tnf, tnf_ref32_t *record) +{ + return (_GET_TAG(tnf, record)); +} + +/* + * Retrieve tag_arg from tag slot of a record + */ + +tnf_ref32_t * +_tnf_get_tag_arg(TNF *tnf, tnf_ref32_t *record) +{ + return (_GET_TAG_ARG(tnf, record)); +} + +/* + * Retrieve the self_size slot of an ABI array record + */ + +size_t +_tnf_get_self_size(TNF *tnf, tnf_ref32_t *array) +{ + return (_GET_SELF_SIZE(tnf, array)); +} + +/* + * Calculate the number of elements in ABI array record + */ + +unsigned +_tnf_get_element_count(TNF *tnf, tnf_ref32_t *array, unsigned eltsize) +{ + size_t size, hdrsize; +#ifdef INFINITE_RECURSION_ARRAY + tnf_ref32_t *base_tag; + + size = _tnf_get_self_size(tnf, array); + base_tag = _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array)); + hdrsize = _tnf_get_header_size(tnf, base_tag); + return (((size - hdrsize) / eltsize)); +#else + size = _tnf_get_self_size(tnf, array); + hdrsize = sizeof (struct tnf_array_hdr); + return (((size - hdrsize) / eltsize)); +#endif +} + +/* + * Retrieve the base pointer of an ABI array record + */ + +caddr_t +/* ARGSUSED */ +_tnf_get_elements(TNF *tnf, tnf_ref32_t *array) +{ +#ifdef INFINITE_RECURSION_ARRAY + size_t hdrsize; + tnf_ref32_t *base_tag; + + base_tag = _tnf_get_base_tag(tnf, _tnf_get_tag(tnf, array)); + hdrsize = _tnf_get_header_size(tnf, base_tag); + return ((caddr_t)((char *)array + hdrsize)); +#else + return ((caddr_t)((char *)array + sizeof (struct tnf_array_hdr))); +#endif +} + +/* + * Retrieve the chars in an ABI string record + */ + +char * +_tnf_get_chars(TNF *tnf, tnf_ref32_t *string) +{ + return ((char *)_tnf_get_elements(tnf, string)); +} + +/* + * Retrieve the string in the name slot of a type record + */ + +char * +_tnf_get_name(TNF *tnf, tnf_ref32_t *tag) +{ + return (_tnf_get_chars(tnf, _GET_NAME(tnf, tag))); +} + +/* + * Retrieve the properties array slot of a type record + */ + +tnf_ref32_t * +_tnf_get_properties(TNF *tnf, tnf_ref32_t *tag) +{ + return (_GET_PROPERTIES(tnf, tag)); +} + +/* + * Retrieve the slot_types slot of struct_type or array_type record + */ + +tnf_ref32_t * +_tnf_get_slot_types(TNF *tnf, tnf_ref32_t *tag) +{ + return (_GET_SLOT_TYPES(tnf, tag)); +} + +/* + * Retrieve the header_size slot of an array_type record + */ + +size_t +_tnf_get_header_size(TNF *tnf, tnf_ref32_t *tag) +{ + return (_GET_HEADER_SIZE(tnf, tag)); +} + +/* + * Retrieve the derived_base slot of a derived_type record + */ + +tnf_ref32_t * +_tnf_get_derived_base(TNF *tnf, tnf_ref32_t *tag) +{ + return (_GET_DERIVED_BASE(tnf, tag)); +} + + +/* + * Find the root (self-tagged) type record + */ + +tnf_ref32_t * +_tnf_get_root_tag(TNF *tnf, tnf_ref32_t *record) +{ + if (tnf->root_tag) + return (tnf->root_tag); + else { + tnf_ref32_t *p1, *p2; + p1 = record; + while ((p2 = _tnf_get_tag(tnf, p1)) != p1) + p1 = p2; + tnf->root_tag = p2; + return (p2); + } +} + +/* + * Search ABI type array for a type named name + */ + +tnf_ref32_t * +_tnf_get_element_named(TNF *tnf, tnf_ref32_t *array, char *name) +{ + unsigned count, i; + tnf_ref32_t *elts; + + count = _tnf_get_element_count(tnf, array, sizeof (tnf_ref32_t)); + /* LINTED pointer cast may result in improper alignment */ + elts = (tnf_ref32_t *)_tnf_get_elements(tnf, array); + + for (i = 0; i < count; i++) { + tnf_ref32_t *type_elt; + + if ((type_elt = _GET_REF32(tnf, &elts[i])) == TNF_NULL) { + /* Can't have missing type records */ + _tnf_error(tnf, TNF_ERR_BADTNF); + return (TNF_NULL); + } + + if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0) + /* Found a type record named name */ + return (type_elt); + } + return (TNF_NULL); +} + +/* + * Look in type record's properties for named type. + * Recursively look at derived_base properties as well. + */ + +tnf_ref32_t * +_tnf_get_property(TNF *tnf, tnf_ref32_t *tag, char *name) +{ + tnf_ref32_t *properties, *property; + + if (strcmp(name, _tnf_get_name(tnf, tag)) == 0) + /* name is type name */ + return (tag); + + if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL) + /* no properties */ + return (TNF_NULL); + + if ((property = _tnf_get_element_named(tnf, properties, name)) + != TNF_NULL) + /* found property named name */ + return (property); + + /* + * Recursively check base type of derived types + */ + if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED) + != TNF_NULL) { + /* tag is a derived type: check its derived_base */ + tnf_ref32_t *base_tag; + + base_tag = _tnf_get_derived_base(tnf, tag); + /* tnf_derived has derived_base == TNF_NULL */ + if (base_tag != TNF_NULL) + return (_tnf_get_property(tnf, base_tag, name)); + } + + return (TNF_NULL); +} + +/* + * Get the ultimate base type of a type record + */ + +tnf_ref32_t * +_tnf_get_base_tag(TNF *tnf, tnf_ref32_t *tag) +{ + tnf_ref32_t *properties; + + if ((properties = _tnf_get_properties(tnf, tag)) == TNF_NULL) + /* no properties */ + return (tag); + + if (_tnf_get_element_named(tnf, properties, TNF_N_DERIVED) + != TNF_NULL) { + tnf_ref32_t *base_tag; + + if ((base_tag = _tnf_get_derived_base(tnf, tag)) != TNF_NULL) + return (_tnf_get_base_tag(tnf, base_tag)); + } + + return (tag); +} + +/* + * Calculate the reference size of an object with type==tag + */ + +size_t +_tnf_get_ref_size(TNF *tnf, tnf_ref32_t *tag) +{ + if (HAS_PROPERTY(tnf, tag, TNF_N_TAGGED)) { + /* Tagged objects occupy 4 bytes for reference */ + return ((sizeof (tnf_ref32_t))); + } else if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE)) { + /* Inline slots cannot be self sized */ + return (_tnf_get_storage_size(tnf, tag)); + } else { + /* Illegal to have references to abstract objects */ + _tnf_error(tnf, TNF_ERR_BADTNF); + return ((0)); + } +} + +/* + * Calculate storage size of an object with type==tag + */ + +size_t +_tnf_get_storage_size(TNF *tnf, tnf_ref32_t *tag) +{ + if (_tnf_get_tag(tnf, tag) == _tnf_get_root_tag(tnf, tag)) + return (_GET_TYPE_SIZE(tnf, tag)); + else { + tnf_ref32_t *base_tag; /* implementation tag */ + caddr_t sizep; + tnf_ref32_t *slot_types; + +#ifndef INFINITE_RECURSION_SIZE + char *base_name; + static struct n2s { + char *name; + size_t size; + } n2s[] = { + { TNF_N_CHAR, sizeof (tnf_char_t) }, + { TNF_N_INT8, sizeof (tnf_int8_t) }, + { TNF_N_INT16, sizeof (tnf_int16_t) }, + { TNF_N_INT32, sizeof (tnf_int32_t) }, + { TNF_N_UINT8, sizeof (tnf_uint8_t) }, + { TNF_N_UINT16, sizeof (tnf_uint16_t) }, + { TNF_N_UINT32, sizeof (tnf_uint32_t) }, + { TNF_N_INT64, sizeof (tnf_int64_t) }, + { TNF_N_UINT64, sizeof (tnf_uint64_t) }, + { TNF_N_FLOAT32, sizeof (tnf_float32_t) }, + { TNF_N_FLOAT64, sizeof (tnf_float64_t) }, + { NULL, 0 } + }; + struct n2s *p; +#endif + + base_tag = _tnf_get_base_tag(tnf, tag); + +#ifndef INFINITE_RECURSION_SIZE + base_name = _tnf_get_name(tnf, base_tag); + + /* XXX Why are we in this mess? */ + p = n2s; + while (p->name) { + if (strcmp(p->name, base_name) == 0) + return (p->size); + p++; + } +#endif + + sizep = _tnf_get_slot_typed(tnf, base_tag, TNF_N_TYPE_SIZE); + if (sizep) + /* Type sized */ + /* LINTED pointer cast may result in improper alignment */ + return (_GET_UINT32(tnf, (tnf_uint32_t *)sizep)); + + slot_types = (tnf_ref32_t *) + /* LINTED pointer cast may result in improper alignment */ + _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_TYPES); + if (slot_types && + _tnf_get_element_named(tnf, slot_types, TNF_N_SELF_SIZE)) + /* Self sized */ + return ((size_t)-1); + else + /* Abstract */ + return (0); + } +} + +/* + * Return the alignment restriction for any tag + */ + +unsigned +_tnf_get_align(TNF *tnf, tnf_ref32_t *tag) +{ + if (HAS_PROPERTY(tnf, tag, TNF_N_SCALAR)) { + tnf_ref32_t *base_tag; + caddr_t alignp; + + base_tag = _tnf_get_base_tag(tnf, tag); + alignp = _tnf_get_slot_typed(tnf, base_tag, TNF_N_ALIGN); + if (alignp) + /* LINTED pointer cast may result in improper alignment */ + return (_GET_UINT32(tnf, (tnf_uint32_t *)alignp)); + } + /* default: word alignment */ + return ((4)); +} + +/* + * Only works for records + * Doesn't check for slot_names in tag + * Tag records, for example, never have named slots + */ + +caddr_t +_tnf_get_slot_typed(TNF *tnf, tnf_ref32_t *record, char *name) +{ + tnf_ref32_t *tag, *base_tag; + tnf_ref32_t *slot_types, *types; + unsigned count, i; + unsigned offset; + + tag = _tnf_get_tag(tnf, record); + base_tag = _tnf_get_base_tag(tnf, tag); + + /* + * The position of slot_types is ABI fixed + * XXX Assume it is present in tag + */ + slot_types = _tnf_get_slot_types(tnf, base_tag); + count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t)); + /* LINTED pointer cast may result in improper alignment */ + types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types); + + offset = 0; + + for (i = 0; i < count; i++) { + tnf_ref32_t *type_elt; + size_t ref_size, align; + + /* Find the type record for slot */ + if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) { + /* Can't have missing type records */ + _tnf_error(tnf, TNF_ERR_BADTNF); + return ((caddr_t)NULL); + } + + /* See similar hack in init_slots() */ + + /* Calculate reference size */ + ref_size = _tnf_get_ref_size(tnf, type_elt); + + /* + * Calculate alignment + * XXX Prevent infinite recursion by assuming that + * a reference size of 4 implies word alignment + */ + align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt); + + /* Adjust offset to account for alignment, if needed */ + offset = ALIGN(offset, align); + + /* Check whether name corresponds to type name */ + if (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0) + /* Found the slot */ + return (fetch_slot(tnf, (caddr_t)record + offset, + type_elt)); + + /* Bump offset by reference size */ + offset += ref_size; + } + + return ((caddr_t)NULL); +} + +/* + * Only works for records + */ + +caddr_t +_tnf_get_slot_named(TNF *tnf, tnf_ref32_t *record, char *name) +{ + tnf_ref32_t *tag, *base_tag; + tnf_ref32_t *slot_types, *slot_names, *types, *names; + unsigned count, i; + unsigned offset; + + tag = _tnf_get_tag(tnf, record); + base_tag = _tnf_get_base_tag(tnf, tag); + + /* + * slot_names are optional + */ + slot_names = (tnf_ref32_t *) + /* LINTED pointer cast may result in improper alignment */ + _tnf_get_slot_typed(tnf, base_tag, TNF_N_SLOT_NAMES); + + /* no slot_names; use _tnf_get_slot_typed() */ + if (slot_names == TNF_NULL) + return (_tnf_get_slot_typed(tnf, record, name)); + + /* + * The position of slot_types is ABI fixed + * XXX Assume it is present in tag + */ + slot_types = _tnf_get_slot_types(tnf, base_tag); + count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t)); + /* LINTED pointer cast may result in improper alignment */ + types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types); + /* LINTED pointer cast may result in improper alignment */ + names = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names); + + offset = 0; + + for (i = 0; i < count; i++) { + tnf_ref32_t *type_elt, *name_elt; + size_t ref_size, align; + + /* Find the type record for slot */ + if ((type_elt = _GET_REF32(tnf, &types[i])) == TNF_NULL) { + /* Can't have missing type records */ + _tnf_error(tnf, TNF_ERR_BADTNF); + return ((caddr_t)NULL); + } + + /* XXX Keep consistent with init_slots() */ + + /* Calculate reference size */ + ref_size = _tnf_get_ref_size(tnf, type_elt); + + /* + * Calculate alignment + * XXX Prevent infinite recursion by assuming that + * a reference size of 4 implies word alignment + */ + align = (ref_size == 4)? 4: _tnf_get_align(tnf, type_elt); + + /* Adjust offset to account for alignment, if needed */ + offset = ALIGN(offset, align); + + /* First check slot name, then type name */ + if ((((name_elt = _GET_REF32(tnf, &names[i])) != TNF_NULL) && + (strcmp(name, _tnf_get_chars(tnf, name_elt)) == 0)) || + (strcmp(name, _tnf_get_name(tnf, type_elt)) == 0)) + /* Found slot */ + return (fetch_slot(tnf, (caddr_t)record + offset, + type_elt)); + + /* Bump offset by reference size */ + offset += ref_size; + } + + return ((caddr_t)NULL); +} + +static caddr_t +fetch_slot(TNF *tnf, caddr_t p, tnf_ref32_t *tag) +{ + if (HAS_PROPERTY(tnf, tag, TNF_N_INLINE)) + return (p); + else /* XXX assume tagged */ + /* LINTED pointer cast may result in improper alignment */ + return ((caddr_t)_GET_REF32(tnf, (tnf_ref32_t *)p)); +} diff --git a/usr/src/lib/libtnf/access.c b/usr/src/lib/libtnf/access.c new file mode 100644 index 0000000000..817a62ffc7 --- /dev/null +++ b/usr/src/lib/libtnf/access.c @@ -0,0 +1,184 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * File header operations + */ + +tnf_datum_t +tnf_get_file_header(TNF *tnf) +{ + return (DATUM(tnf->file_header_info, (caddr_t)tnf->file_header)); +} + +/* + * Block access operations + */ + +unsigned +tnf_get_block_count(TNF *tnf) +{ + return (tnf->block_count); +} + +tnf_datum_t +tnf_get_block_absolute(TNF *tnf, unsigned index) +{ + if (index >= tnf->block_count) + /* + * access to non-existent block: + * no error as per spec + */ + return (TNF_DATUM_NULL); + else + /* + * XXX Require a single block header tag + */ + /* LINTED pointer cast may result in improper alignment */ + return (DATUM(tnf->block_header_info, + (caddr_t)_GET_INDEX_BLOCK(tnf, index))); +} + +tnf_datum_t +tnf_get_block_relative(tnf_datum_t datum, int adjust) +{ + TNF *tnf; + tnf_ref32_t *bhdr; + unsigned index; + + CHECK_DATUM(datum); + + tnf = DATUM_TNF(datum); + bhdr = _GET_BLOCK(tnf, DATUM_VAL(datum)); + index = _GET_BLOCK_INDEX(tnf, bhdr); + + return (tnf_get_block_absolute(tnf, index + adjust)); +} + +int +tnf_is_block_header(tnf_datum_t datum) +{ + struct taginfo *info; + caddr_t val; + tnf_ref32_t *bhdr; + + CHECK_DATUM(datum); + + info = DATUM_INFO(datum); + val = DATUM_VAL(datum); + bhdr = _GET_BLOCK(info->tnf, val); + + return (((caddr_t)bhdr == val) && + (info == info->tnf->block_header_info)); +} + +tnf_datum_t +tnf_get_block_header(tnf_datum_t datum) +{ + TNF *tnf; + caddr_t val; + + CHECK_DATUM(datum); + + tnf = DATUM_TNF(datum); + val = DATUM_VAL(datum); + /* + * XXX Require a single block header tag + */ + return (DATUM(tnf->block_header_info, (caddr_t)_GET_BLOCK(tnf, val))); +} + +/* + * Sequential record access + */ + +tnf_datum_t +tnf_get_next_record(tnf_datum_t datum) +{ + TNF *tnf; + tnf_ref32_t *bhdr, *cell, ref32; + caddr_t val, nval, bval, blim; + size_t size, bytes; + + CHECK_RECORD(datum); + + tnf = DATUM_TNF(datum); + val = DATUM_VAL(datum); + + size = tnf_get_size(datum); + nval = val + size; + + /* Check file bounds */ + if (nval < tnf->data_start) + return (tnf_get_block_absolute(tnf, 0)); + else if (nval >= tnf->file_end) + return (TNF_DATUM_NULL); + + /* + * OK, nval is in data area, start looking in block + */ + bhdr = _GET_BLOCK(tnf, nval); + /* LINTED pointer cast may result in improper alignment */ + bytes = _GET_BLOCK_BYTES_VALID(tnf, bhdr); + bval = (caddr_t)bhdr; + blim = bval + bytes; + + /* sequentially examine valid cells in block from nval onwards */ + while (nval < blim) { + /* LINTED pointer cast may result in improper alignment */ + cell = (tnf_ref32_t *)nval; + ref32 = _GET_INT32(tnf, cell); + + switch (TNF_REF32_TYPE(ref32)) { + case TNF_REF32_T_FWD: /* skip forwarding cells */ + nval += sizeof (tnf_ref32_t); + break; + case TNF_REF32_T_RSVD: /* catch bogus cells */ + _tnf_error(tnf, TNF_ERR_BADTNF); + return (TNF_DATUM_NULL); + default: /* PAIR or TAG: record header */ + return (RECORD_DATUM(tnf, cell)); + } + } + + /* + * Couldn't find it: return next non-zero block header + */ + while ((bval += tnf->block_size) < tnf->file_end) + /* Gotta check that there is a real bhdr here */ + /* LINTED pointer cast may result in improper alignment */ + if (*(tnf_ref32_t *)bval != TNF_NULL) + /* LINTED pointer cast may result in improper alignment */ + return (RECORD_DATUM(tnf, (tnf_ref32_t *)bval)); + + /* + * default: we're off the end of the file + */ + return (TNF_DATUM_NULL); +} diff --git a/usr/src/lib/libtnf/array.c b/usr/src/lib/libtnf/array.c new file mode 100644 index 0000000000..09fd89c9e7 --- /dev/null +++ b/usr/src/lib/libtnf/array.c @@ -0,0 +1,205 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * XXX This module assumes that all arrays are self-sized records. + */ + +/* + * + */ + +static struct taginfo * get_array_info( + tnf_datum_t, + struct taginfo **base, + struct taginfo **elt, + struct taginfo **elt_base); + +/* + * XXX Assumes arrays are (self-sized) records + */ + +void +_tnf_check_array(tnf_datum_t datum) +{ + struct taginfo *info; + + CHECK_RECORD(datum); /* XXX */ + + info = DATUM_INFO(datum); + + if (!INFO_ARRAY(info)) + _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH); + +} + +/* + * Helper + */ + +static struct taginfo * +get_array_info( + tnf_datum_t datum, + struct taginfo **basep, + struct taginfo **eltp, + struct taginfo **elt_basep) +{ + struct taginfo *info, *base, *elt, *elt_base; + + info = DATUM_INFO(datum); + base = INFO_DERIVED(info) ? info->base : info; + + if (INFO_DERIVED(base) || (!INFO_ARRAY(base))) + _tnf_error(DATUM_TNF(datum), TNF_ERR_INTERNAL); + + elt = base->base; /* XXX base slot is reused for elttype */ + elt_base = INFO_DERIVED(elt) ? elt->base : elt; + + *basep = base; + *eltp = elt; + *elt_basep = elt_base; + return (info); +} + +/* + * Return number of elements in array + */ + +unsigned +tnf_get_element_count(tnf_datum_t datum) +{ + size_t hdr_size, elt_size, self_size; + struct taginfo *base, *elt, *elt_base; + + CHECK_ARRAY(datum); + + (void) get_array_info(datum, &base, &elt, &elt_base); + hdr_size = base->hdrsize; + elt_size = INFO_ELEMENT_SIZE(elt_base); + self_size = _tnf_get_self_size(DATUM_TNF(datum), + /* LINTED pointer cast may result in improper alignment */ + DATUM_RECORD(datum)); + return (((self_size - hdr_size) / elt_size)); +} + +/* + * Fetch indexed element + */ + +tnf_datum_t +tnf_get_element(tnf_datum_t datum, unsigned index) +{ + size_t hdr_size, elt_size, self_size; + struct taginfo *base, *elt, *elt_base; + unsigned count, offset; + + CHECK_ARRAY(datum); + + (void) get_array_info(datum, &base, &elt, &elt_base); + hdr_size = base->hdrsize; + elt_size = INFO_ELEMENT_SIZE(elt_base); + self_size = _tnf_get_self_size(DATUM_TNF(datum), + /* LINTED pointer cast may result in improper alignment */ + DATUM_RECORD(datum)); + + count = (self_size - hdr_size) / elt_size; + + if (index >= count) + _tnf_error(DATUM_TNF(datum), TNF_ERR_BADINDEX); + + offset = hdr_size + (index * elt_size); + + /* + * If tagged, use the tag to construct datum + */ + if (INFO_TAGGED(elt)) { + TNF *tnf; + tnf_ref32_t *rec; + + tnf = DATUM_TNF(datum); + /* LINTED pointer cast may result in improper alignment */ + rec = _GET_REF32(tnf, (tnf_ref32_t *) + (DATUM_VAL(datum) + offset)); + /* NULL elements are allowed */ + return ((rec == TNF_NULL)? TNF_DATUM_NULL : + RECORD_DATUM(tnf, rec)); + } else + return (DATUM(elt, DATUM_VAL(datum) + offset)); +} + +/* + * Return element type of array + */ + +tnf_datum_t +tnf_get_element_type(tnf_datum_t datum) +{ + struct taginfo *base, *elt, *elt_base; + + CHECK_ARRAY(datum); + + (void) get_array_info(datum, &base, &elt, &elt_base); + + return (RECORD_DATUM(DATUM_TNF(datum), elt->tag)); +} + +/* + * Return a char pointer for string record + */ + +char * +tnf_get_chars(tnf_datum_t datum) +{ + struct taginfo *info, *base, *elt, *elt_base; + + CHECK_ARRAY(datum); + + info = get_array_info(datum, &base, &elt, &elt_base); + + if (!INFO_STRING(info)) + _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH); + + return (DATUM_VAL(datum) + base->hdrsize); +} + +/* + * Return the base pointer of array + */ + +caddr_t +tnf_get_elements(tnf_datum_t datum) +{ + struct taginfo *base, *elt, *elt_base; + + CHECK_ARRAY(datum); + + (void) get_array_info(datum, &base, &elt, &elt_base); + + return ((caddr_t)(DATUM_VAL(datum) + base->hdrsize)); +} diff --git a/usr/src/lib/libtnf/datum.c b/usr/src/lib/libtnf/datum.c new file mode 100644 index 0000000000..0193f23f90 --- /dev/null +++ b/usr/src/lib/libtnf/datum.c @@ -0,0 +1,214 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * Defines + */ + +#define DATUM_KIND(d) (DATUM_INFO(d)->kind) + +/* + * Declarations + */ + +static int has_prop(tnf_datum_t, tag_props_t); + +/* + * Datum operations: for more debuggability + */ + +#ifndef _DATUM_MACROS + +tnf_datum_t +_tnf_datum(struct taginfo *info, caddr_t val) +{ + return (_DATUM(info, val)); +} + +struct taginfo * +_tnf_datum_info(tnf_datum_t datum) +{ + return ((struct taginfo *)_DATUM_HI(datum)); +} + +caddr_t +_tnf_datum_val(tnf_datum_t datum) +{ + return ((caddr_t)_DATUM_LO(datum)); +} + +#endif + +/* + * Check for valid datum + */ + +void +_tnf_check_datum(tnf_datum_t datum) +{ + caddr_t val; + TNF *tnf; + + if (datum == TNF_DATUM_NULL) + _tnf_error(NULL, TNF_ERR_BADTNF); + + val = DATUM_VAL(datum); + tnf = DATUM_TNF(datum); + + if ((val <= tnf->file_start) || (val >= tnf->file_end)) + _tnf_error(tnf, TNF_ERR_BADDATUM); +} + +/* + * Retrieve datum kind from cached information + */ + +tnf_kind_t +tnf_get_kind(tnf_datum_t datum) +{ + CHECK_DATUM(datum); + /* The kind field is always completely initialized */ + return (DATUM_KIND(datum)); +} + +/* + * Classification predicates: check the cached tag props + */ + +static int +has_prop(tnf_datum_t datum, tag_props_t prop) +{ + CHECK_DATUM(datum); + + /* Note: No need to get base info because props inherited */ + return (INFO_PROP(DATUM_INFO(datum), prop)); +} + +int +tnf_is_inline(tnf_datum_t datum) +{ + return (has_prop(datum, TAG_PROP_INLINE)); +} + +int +tnf_is_scalar(tnf_datum_t datum) +{ + return (has_prop(datum, TAG_PROP_SCALAR)); +} + +int +tnf_is_record(tnf_datum_t datum) /* XXX was: tnf_is_tagged */ +{ + return (has_prop(datum, TAG_PROP_TAGGED)); +} + +int +tnf_is_array(tnf_datum_t datum) +{ + return (has_prop(datum, TAG_PROP_ARRAY)); +} + +int +tnf_is_string(tnf_datum_t datum) +{ + return (has_prop(datum, TAG_PROP_STRING)); +} + +int +tnf_is_struct(tnf_datum_t datum) +{ + return (has_prop(datum, TAG_PROP_STRUCT)); +} + +int +tnf_is_type(tnf_datum_t datum) +{ + return (has_prop(datum, TAG_PROP_TYPE)); +} + +/* + * Get the type datum for any datum + */ + +tnf_datum_t +tnf_get_type(tnf_datum_t datum) +{ + struct taginfo *info; + + CHECK_DATUM(datum); + + info = DATUM_INFO(datum); + return (DATUM(info->meta, (caddr_t)info->tag)); +} + +/* + * Get the type name for any datum + * XXX Beware: this is a pointer into the file + */ + +char * +tnf_get_type_name(tnf_datum_t datum) +{ + CHECK_DATUM(datum); + return (DATUM_INFO(datum)->name); /* cached */ +} + +/* + * Get the size of any datum + */ + +size_t +tnf_get_size(tnf_datum_t datum) +{ + struct taginfo *info; + size_t size; + + CHECK_DATUM(datum); + + info = DATUM_INFO(datum); + size = info->size; + + if (size == (size_t)-1) /* self sized */ + /* XXX tnf_get_slot_named(datum, TNF_N_SELF_SIZE) */ + /* LINTED pointer cast may result in improper alignment */ + return (_tnf_get_self_size(info->tnf, DATUM_RECORD(datum))); + else + return (size); +} + +/* + * Get raw pointer to any datum + */ + +caddr_t +tnf_get_raw(tnf_datum_t datum) +{ + CHECK_DATUM(datum); + return (DATUM_VAL(datum)); +} diff --git a/usr/src/lib/libtnf/error.c b/usr/src/lib/libtnf/error.c new file mode 100644 index 0000000000..bad39d7f86 --- /dev/null +++ b/usr/src/lib/libtnf/error.c @@ -0,0 +1,114 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" +#include <libintl.h> + +#if !defined(TEXT_DOMAIN) +#define TEXT_DOMAIN "SYS_TEST" +#endif + +/* + * + */ + +static tnf_error_handler_t *_err_handler = &tnf_default_error_handler; +static void *_err_arg = 0; + +/* + * + */ + +void +tnf_set_error_handler(tnf_error_handler_t *handler, void *arg) +{ + /* XXX Not MT-safe */ + _err_arg = arg; + _err_handler = handler; +} + +/* + * + */ + +void +_tnf_error(TNF *tnf, tnf_errcode_t err) +{ + (*_err_handler)(_err_arg, tnf, err); +} + +/* + * + */ + +char * +tnf_error_message(tnf_errcode_t err) +{ + if (err == TNF_ERR_NONE) + return (dgettext(TEXT_DOMAIN, "no error")); + else if (err <= TNF_ERRNO_MAX) + return (strerror(err)); + else { + switch (err) { + case TNF_ERR_NOTTNF: + return (dgettext(TEXT_DOMAIN, "not a TNF file")); + case TNF_ERR_BADDATUM: + return (dgettext(TEXT_DOMAIN, + "operation on bad or NULL data handle")); + case TNF_ERR_TYPEMISMATCH: + return (dgettext(TEXT_DOMAIN, "type mismatch")); + case TNF_ERR_BADINDEX: + return (dgettext(TEXT_DOMAIN, "index out of bounds")); + case TNF_ERR_BADSLOT: + return (dgettext(TEXT_DOMAIN, "no such slot")); + case TNF_ERR_BADREFTYPE: + return (dgettext(TEXT_DOMAIN, "bad reference type")); + case TNF_ERR_ALLOCFAIL: + return (dgettext(TEXT_DOMAIN, + "memory allocation failure")); + case TNF_ERR_BADTNF: + return (dgettext(TEXT_DOMAIN, "bad TNF file")); + case TNF_ERR_INTERNAL: + return (dgettext(TEXT_DOMAIN, "internal error")); + default: + return (dgettext(TEXT_DOMAIN, "unknown error code")); + } + } +} + +/* + * + */ + +void +/* ARGSUSED */ +tnf_default_error_handler(void *arg, TNF *tnf, tnf_errcode_t err) +{ + fprintf(stderr, dgettext(TEXT_DOMAIN, "error: libtnf: %d: %s\n"), + err, tnf_error_message(err)); + abort(); +} diff --git a/usr/src/lib/libtnf/i386dep.c b/usr/src/lib/libtnf/i386dep.c new file mode 100644 index 0000000000..7f198ccd43 --- /dev/null +++ b/usr/src/lib/libtnf/i386dep.c @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* This file intentionally (almost) blank */ + +static int _zero_ = 0; diff --git a/usr/src/lib/libtnf/info.c b/usr/src/lib/libtnf/info.c new file mode 100644 index 0000000000..8c9829aa79 --- /dev/null +++ b/usr/src/lib/libtnf/info.c @@ -0,0 +1,400 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +#define TAG_INDEX(x) (TNF_TAG16_ABS16(x) / sizeof (tnf_ref32_t)) + +/* + * + */ + +static struct taginfo * add_info(TNF *, tnf_ref32_t *); + +static struct taginfo * +init_abstract_info(TNF *, tnf_ref32_t *, struct taginfo *); + +static struct taginfo * +init_derived_info(TNF *, tnf_ref32_t *, struct taginfo *); + +static struct taginfo * +init_scalar_info(TNF *, tnf_ref32_t *, struct taginfo *); + +static struct taginfo * +init_struct_info(TNF *, tnf_ref32_t *, struct taginfo *); + +static struct taginfo * +init_array_info(TNF *, tnf_ref32_t *, struct taginfo *); + +static void init_slots(TNF *, tnf_ref32_t *, struct taginfo *); + +/* + * Allocate tag table and directory + */ + +tnf_errcode_t +_tnf_init_tags(TNF *tnf) +{ + if ((tnf->tag_table = calloc(TAGTABCNT, sizeof (struct taginfo *))) + == NULL) + return (TNF_ERR_ALLOCFAIL); + if ((tnf->tag_directory = calloc(TAGDIRCNT(tnf->directory_size), + sizeof (struct taginfo *))) + == NULL) + return (TNF_ERR_ALLOCFAIL); + return (TNF_ERR_NONE); +} + +/* + * Deallocate all taginfos and tables associated with TNF handle + */ + +tnf_errcode_t +_tnf_fini_tags(TNF *tnf) +{ + int i; + struct taginfo *info, *link; + + /* + * free taginfos + */ + for (i = 0; i < TAGTABCNT; i++) { + info = tnf->tag_table[i]; + while (info) { + /* remember link */ + link = info->link; + /* free slot information */ + if (info->slotinfo) + free(info->slotinfo); + /* free taginfo */ + free(info); + /* next in hash chain */ + info = link; + } + } + /* + * free the tables + */ + free(tnf->tag_table); + tnf->tag_table = NULL; + free(tnf->tag_directory); + tnf->tag_directory = NULL; + + return (TNF_ERR_NONE); +} + +/* + * Get info for supplied tag + */ + +struct taginfo * +_tnf_get_info(TNF *tnf, tnf_ref32_t *tag) +{ + struct taginfo *bucket, *info; + + bucket = tnf->tag_table[TAGHASH(tnf, tag)]; + for (info = bucket; info; info = info->link) + if (info->tag == tag) + return (info); /* found it */ + + /* default: not there, create */ + return (add_info(tnf, tag)); +} + +/* + * Get info for supplied record + * Use fast lookup, if possible + */ + +struct taginfo * +_tnf_record_info(TNF *tnf, tnf_ref32_t *record) +{ + tnf_ref32_t ref32; + tnf_ref16_t tag16; + tnf_abs16_t index; + struct taginfo *info; + + ref32 = _GET_INT32(tnf, record); + + index = 0; + if (TNF_REF32_IS_PAIR(ref32)) { + tag16 = TNF_REF32_TAG16(ref32); + if (TNF_TAG16_IS_ABS(tag16)) + index = TAG_INDEX(tag16); + } + + if (index) { + if ((info = tnf->tag_directory[index]) != NULL) + return (info); + else { /* not in directory yet */ + info = _tnf_get_info(tnf, _tnf_get_tag(tnf, record)); + /* enter into tag directory */ + return ((tnf->tag_directory[index] = info)); + } + } + + /* default: not referenced via index */ + return (_tnf_get_info(tnf, _tnf_get_tag(tnf, record))); +} + +/* + * Add a new taginfo for tag + */ + +static struct taginfo * +add_info(TNF *tnf, tnf_ref32_t *tag) +{ + struct taginfo *info, *bucket; + unsigned hash; + tnf_ref32_t *meta; + + info = (struct taginfo *)calloc(1, sizeof (struct taginfo)); + + /* Initialize members */ + info->tnf = tnf; + info->tag = tag; + info->name = _tnf_get_name(tnf, tag); + info->props = _tnf_get_props(tnf, tag); + info->kind = _tnf_get_kind(tnf, tag); + info->size = _tnf_get_storage_size(tnf, tag); + info->align = _tnf_get_align(tnf, tag); + + /* Add it to table */ + hash = TAGHASH(tnf, tag); + bucket = tnf->tag_table[hash]; + info->link = bucket; + tnf->tag_table[hash] = info; + + /* Ensure meta info is available */ + meta = _tnf_get_tag(tnf, tag); + info->meta = _tnf_get_info(tnf, meta); + + /* + * Initialize info + * Derived must be first clause due to property inheritance + */ + + if (INFO_DERIVED(info)) + return (init_derived_info(tnf, tag, info)); + else if (INFO_STRUCT(info)) + return (init_struct_info(tnf, tag, info)); + else if (INFO_ARRAY(info)) + return (init_array_info(tnf, tag, info)); + else if (INFO_SCALAR(info)) + return (init_scalar_info(tnf, tag, info)); + else /* XXX assume abstract type */ + return (init_abstract_info(tnf, tag, info)); +} + + +/* + * Initialize info for an abstract tag + */ + +static struct taginfo * +/* ARGSUSED */ +init_abstract_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info) +{ + if (INFO_SCALAR(info) || INFO_DERIVED(info) || + INFO_STRUCT(info) || INFO_ARRAY(info)) + _tnf_error(tnf, TNF_ERR_INTERNAL); + if (info->size == (size_t)-1) + _tnf_error(tnf, TNF_ERR_BADTNF); + return (info); +} + +/* + * Initialize info for a derived tag + */ + +static struct taginfo * +init_derived_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info) +{ + tnf_ref32_t *base_tag; + + if (!INFO_DERIVED(info)) + _tnf_error(tnf, TNF_ERR_INTERNAL); + + /* Ensure ultimate base information is available */ + base_tag = _tnf_get_base_tag(tnf, tag); + info->base = _tnf_get_info(tnf, base_tag); + + return (info); +} + +/* + * Initialize info for a scalar tag + */ + +static struct taginfo * +/* ARGSUSED */ +init_scalar_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info) +{ + if ((!INFO_SCALAR(info)) || + (INFO_DERIVED(info) || INFO_ARRAY(info) || INFO_STRUCT(info))) + _tnf_error(tnf, TNF_ERR_INTERNAL); + if (info->size == (size_t)-1) + _tnf_error(tnf, TNF_ERR_BADTNF); + + /* XXX alignment already done */ + + return (info); +} + +/* + * Initialize info for a struct tag + */ + +static struct taginfo * +init_struct_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info) +{ + if ((!INFO_STRUCT(info)) || + (INFO_DERIVED(info) || INFO_ARRAY(info) || INFO_SCALAR(info))) + _tnf_error(tnf, TNF_ERR_INTERNAL); + if (info->size == (size_t)-1) + _tnf_error(tnf, TNF_ERR_BADTNF); + + /* Get slot information */ + init_slots(tnf, tag, info); + + return (info); +} + +/* + * Initialize info for an array tag + */ + +static struct taginfo * +init_array_info(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info) +{ + tnf_ref32_t *elt_tag; + int defeat; + + if ((!INFO_ARRAY(info)) || + (INFO_DERIVED(info) || INFO_STRUCT(info) || INFO_SCALAR(info))) + _tnf_error(tnf, TNF_ERR_INTERNAL); + + /* XXX special-case abstract array tag */ + defeat = (strcmp(info->name, TNF_N_ARRAY) == 0); + + /* Require all arrays to be self-sized records */ + if (!(INFO_TAGGED(info) && (info->size == (size_t)-1))) + if (!defeat) + _tnf_error(tnf, TNF_ERR_BADTNF); + + /* Store array header size */ + info->hdrsize = _tnf_get_header_size(tnf, tag); + /* XXX Temporary sanity check */ + if (info->hdrsize != sizeof (struct tnf_array_hdr)) + if (!defeat) + _tnf_error(tnf, TNF_ERR_BADTNF); + + /* Get slot information */ + init_slots(tnf, tag, info); + + /* Get info for element type */ + elt_tag = (tnf_ref32_t *)_tnf_get_slot_typed(tnf, tag, + /* LINTED pointer cast may result in improper alignment */ + TNF_N_ELEMENT_TYPE); + /* XXX tnf_array has element_type == NULL */ + info->base = elt_tag ? _tnf_get_info(tnf, elt_tag): NULL; + + return (info); +} + +/* + * Initialize slot information for aggregate tag + */ + +static void +init_slots(TNF *tnf, tnf_ref32_t *tag, struct taginfo *info) +{ + tnf_ref32_t *slot_types, *slot_names; + tnf_ref32_t *types, *names; + unsigned count, i, offset; + struct slotinfo *slotinfo; + + slot_types = (tnf_ref32_t *) + /* LINTED pointer cast may result in improper alignment */ + _tnf_get_slot_typed(tnf, tag, TNF_N_SLOT_TYPES); + slot_names = (tnf_ref32_t *) + /* LINTED pointer cast may result in improper alignment */ + _tnf_get_slot_typed(tnf, tag, TNF_N_SLOT_NAMES); + + /* abstract tags have no slots */ + if (slot_types == TNF_NULL) + return; + + count = _tnf_get_element_count(tnf, slot_types, sizeof (tnf_ref32_t)); + /* LINTED pointer cast may result in improper alignment */ + types = (tnf_ref32_t *)_tnf_get_elements(tnf, slot_types); + names = ((slot_names == TNF_NULL) ? TNF_NULL : + /* LINTED pointer cast may result in improper alignment */ + (tnf_ref32_t *)_tnf_get_elements(tnf, slot_names)); + + slotinfo = (struct slotinfo *) + calloc(1, sizeof (unsigned) + (count * sizeof (struct slot))); + if (slotinfo == (struct slotinfo *)NULL) + _tnf_error(tnf, TNF_ERR_ALLOCFAIL); + + slotinfo->slot_count = count; + offset = 0; + + for (i = 0; i < count; i++) { + tnf_ref32_t *type_elt, *name_elt; + struct taginfo *elt_info; + size_t ref_size, align; + + /* XXX No checks here for missing tags */ + type_elt = _GET_REF32(tnf, &types[i]); + name_elt = names ? _GET_REF32(tnf, &names[i]) : TNF_NULL; + + /* Resolve slot tag into taginfo */ + elt_info = _tnf_get_info(tnf, type_elt); + slotinfo->slots[i].slot_type = elt_info; + slotinfo->slots[i].slot_name = + ((name_elt != TNF_NULL) ? + _tnf_get_chars(tnf, name_elt) : + _tnf_get_name(tnf, type_elt)); + + /* Get cached reference size */ + ref_size = INFO_REF_SIZE(elt_info); + + /* Get cached alignment */ + align = INFO_ALIGN(elt_info); /* XXX */ + + /* Adjust offset to account for alignment, if needed */ + offset = ALIGN(offset, align); + + slotinfo->slots[i].slot_offset = offset; + + /* Bump offset by reference size */ + offset += ref_size; + } + + info->slotinfo = slotinfo; +} diff --git a/usr/src/lib/libtnf/libtnf.h b/usr/src/lib/libtnf/libtnf.h new file mode 100644 index 0000000000..27c111cbed --- /dev/null +++ b/usr/src/lib/libtnf/libtnf.h @@ -0,0 +1,340 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#ifndef _LIBTNF_H +#define _LIBTNF_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#include "tnf/tnf.h" +#include "machlibtnf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Info flags + */ + +typedef unsigned long tag_props_t; + +#define TAG_PROP_INLINE (1<<0) +#define TAG_PROP_TAGGED (1<<1) +#define TAG_PROP_SCALAR (1<<2) +#define TAG_PROP_DERIVED (1<<3) +#define TAG_PROP_ARRAY (1<<4) +#define TAG_PROP_STRING (1<<5) +#define TAG_PROP_STRUCT (1<<6) +#define TAG_PROP_TYPE (1<<7) + +/* + * Type tag information + */ + +struct taginfo { + struct taginfo *link; /* hash link */ +#define INFO_MEMBER_0 link + TNF *tnf; /* TNF handle */ + tnf_ref32_t *tag; /* tag record in file */ + char *name; /* chars in file */ + tnf_kind_t kind; /* data classification */ + tag_props_t props; /* tag property flags */ + struct taginfo *meta; /* meta tag info */ + struct taginfo *base; /* last derived base or elttype */ + size_t size; /* storage size or -1 */ + size_t align; /* slot alignment */ + size_t hdrsize; /* array header size */ + struct slotinfo { /* aggregate slot information */ + unsigned slot_count; + /* Embedded array */ + struct slot { + struct taginfo *slot_type; + char *slot_name; + unsigned slot_offset; + } slots[1]; + } *slotinfo; +}; + +#define INFO_PROP(ip, p) ((ip)->props & (p)) + +#define INFO_INLINE(ip) INFO_PROP(ip, TAG_PROP_INLINE) +#define INFO_TAGGED(ip) INFO_PROP(ip, TAG_PROP_TAGGED) +#define INFO_SCALAR(ip) INFO_PROP(ip, TAG_PROP_SCALAR) +#define INFO_DERIVED(ip) INFO_PROP(ip, TAG_PROP_DERIVED) +#define INFO_ARRAY(ip) INFO_PROP(ip, TAG_PROP_ARRAY) +#define INFO_STRING(ip) INFO_PROP(ip, TAG_PROP_STRING) +#define INFO_STRUCT(ip) INFO_PROP(ip, TAG_PROP_STRUCT) +#define INFO_TYPE(ip) INFO_PROP(ip, TAG_PROP_TYPE) + +#define INFO_REF_SIZE(ip) (INFO_TAGGED(ip)? 4: (ip)->size) +#define INFO_ELEMENT_SIZE(ip) INFO_REF_SIZE(ip) + +/* Alignment is stored for all but records and derivations thereof */ +#define INFO_ALIGN(ip) (INFO_TAGGED(ip)? 4: (ip)->align) + +#define ALIGN(n, a) \ + (((a) == 0) ? (n) : (((n) + (a) - 1) & ~((a) - 1))) + +/* + * Tag lookup + */ + +/* Number of directory entries */ +#define TAGDIRCNT(x) ((x) / sizeof (tnf_ref32_t)) + +/* Number of hash table buckets */ +#define TAGTABCNT 1024 +#define TAGTABMASK (TAGTABCNT-1) + +/* A tag is at least 32 bytes; with strings & props, assume 128 bytes */ +#define TAGTABSHIFT 7 + +/* Hash tag by bits 17:7 of offset within data area */ +#define TAGOFF(tnf, p) ((unsigned)((caddr_t)(p) - (tnf)->data_start)) +#define TAGHASH(tnf, p) ((TAGOFF(tnf, p) >> TAGTABSHIFT) & TAGTABMASK) + +/* + * TNF handle + */ + +struct TNF { + /* + * Client-supplied bounds + */ + caddr_t file_start; + size_t file_size; + caddr_t file_end; /* file_start + file_size */ + + /* + * File information + */ + unsigned file_magic; /* magic number of file */ + int file_native; /* endian flag */ + + /* file header */ + tnf_ref32_t *file_header; /* first record in file */ + size_t block_size; /* size of a block */ + size_t directory_size; /* size of directory area */ + + unsigned block_count; /* number of data blocks */ + caddr_t data_start; /* file_start + 64KB */ + + unsigned generation_shift; + unsigned address_mask; + + /* block headers */ + unsigned block_shift; /* index -> bhdr */ + unsigned block_mask; /* ptr -> bhdr */ + unsigned block_generation_offset; + unsigned block_bytes_valid_offset; + + /* root tag */ + tnf_ref32_t *root_tag; + + /* important taginfo */ + struct taginfo *file_header_info; + struct taginfo *block_header_info; + + /* tag lookup tables */ + struct taginfo **tag_table; /* by address */ + struct taginfo **tag_directory; /* by index */ + +}; + +/* + * File operations for reading integers + */ + +#define _GET_UINT32(tnf, ptr) \ + ((tnf)->file_native ? \ + *(tnf_uint32_t *)(ptr) : \ + _tnf_swap32(*(tnf_uint32_t *)(ptr))) + +#define _GET_INT32(tnf, ptr) \ + ((tnf_int32_t)_GET_UINT32(tnf, ptr)) + +#define _GET_UINT16(tnf, ptr) \ + ((tnf)->file_native ? \ + *(tnf_uint16_t *)(ptr) : \ + _tnf_swap16(*(tnf_uint16_t *)(ptr))) + +#define _GET_INT16(tnf, ptr) \ + ((tnf_int16_t)_GET_UINT16(tnf, ptr)) + +/* + * TNF reference-chasing operations + */ + +tnf_ref32_t * _tnf_get_ref32(TNF *, tnf_ref32_t *); +tnf_ref32_t * _tnf_get_ref16(TNF *, tnf_ref32_t *); + +#define _GET_REF32(tnf, ptr) _tnf_get_ref32(tnf, ptr) +#define _GET_REF16(tnf, ptr) _tnf_get_ref16(tnf, ptr) + +/* + * Block header record operations + * Only applicable in data area + */ + +#define _GET_BLOCK(tnf, ptr) \ + ((tnf_ref32_t *)((unsigned)(ptr) & (tnf)->block_mask)) + +#define _GET_BLOCK_INDEX(tnf, bhdr) \ + (((caddr_t)(bhdr) - (tnf)->data_start) >> (tnf)->block_shift) + +#define _GET_INDEX_BLOCK(tnf, index) \ + ((tnf_ref32_t *)((tnf)->data_start + ((index) << (tnf)->block_shift))) + +#define _GET_BLOCK_GENERATION(tnf, bhdr) \ + _GET_UINT32(tnf, (caddr_t)bhdr + tnf->block_generation_offset) + +#define _GET_BLOCK_BYTES_VALID(tnf, bhdr) \ + (!(bhdr) ? 0 : _GET_UINT16(tnf, (caddr_t)bhdr + \ + tnf->block_bytes_valid_offset)) + +/* + * Datum operations + */ + +#ifndef _DATUM_MACROS + +tnf_datum_t _tnf_datum(struct taginfo *, caddr_t); +struct taginfo * _tnf_datum_info(tnf_datum_t); +caddr_t _tnf_datum_val(tnf_datum_t); + +#define DATUM(x, y) _tnf_datum(x, y) +#define DATUM_INFO(x) _tnf_datum_info(x) +#define DATUM_VAL(x) _tnf_datum_val(x) + +#else /* _DATUM_MACROS */ + +/* Some degree of type safety: */ +#define DATUM(x, y) _DATUM(&(x)->INFO_MEMBER_0, y) +#define DATUM_INFO(d) ((struct taginfo *)_DATUM_HI(d)) +#define DATUM_VAL(d) ((caddr_t)_DATUM_LO(d)) + +#endif /* _DATUM_MACROS */ + +#define _DATUM(hi, lo) (((unsigned long long)(hi) << 32) | (unsigned)(lo)) +#define _DATUM_HI(x) ((unsigned) ((x) >> 32)) +#define _DATUM_LO(x) ((unsigned) (x)) + +#define DATUM_RECORD(x) \ + ((tnf_ref32_t *)DATUM_VAL(x)) + +#define RECORD_DATUM(tnf, rec) \ + DATUM(_tnf_record_info(tnf, rec), (caddr_t)rec) + +#define DATUM_TNF(x) DATUM_INFO(x)->tnf +#define DATUM_TAG(x) DATUM_INFO(x)->tag + +/* + * Type checking operations + */ + +void _tnf_check_datum(tnf_datum_t); +#define CHECK_DATUM(x) _tnf_check_datum(x) + +void _tnf_check_record(tnf_datum_t); +#define CHECK_RECORD(x) _tnf_check_record(x) + +void _tnf_check_slots(tnf_datum_t); +#define CHECK_SLOTS(x) _tnf_check_slots(x) + +void _tnf_check_array(tnf_datum_t); +#define CHECK_ARRAY(x) _tnf_check_array(x) + +void _tnf_check_type(tnf_datum_t); +#define CHECK_TYPE(x) _tnf_check_type(x) + +/* + * Operations based on ABI layouts and bootstrap assumptions + */ + +tnf_ref32_t * _tnf_get_tag(TNF *, tnf_ref32_t *); +tnf_ref32_t * _tnf_get_tag_arg(TNF *, tnf_ref32_t *); +size_t _tnf_get_self_size(TNF *, tnf_ref32_t *); +unsigned _tnf_get_element_count(TNF *, tnf_ref32_t *, unsigned); +caddr_t _tnf_get_elements(TNF *, tnf_ref32_t *); +char * _tnf_get_chars(TNF *, tnf_ref32_t *); +char * _tnf_get_name(TNF *, tnf_ref32_t *); +tnf_ref32_t * _tnf_get_properties(TNF *, tnf_ref32_t *); +tnf_ref32_t * _tnf_get_slot_types(TNF *, tnf_ref32_t *); +size_t _tnf_get_header_size(TNF *, tnf_ref32_t *); +tnf_ref32_t * _tnf_get_derived_base(TNF *, tnf_ref32_t *); + +tnf_ref32_t * _tnf_get_root_tag(TNF *, tnf_ref32_t *); +tnf_ref32_t * _tnf_get_property(TNF *, tnf_ref32_t *, char *); +tnf_ref32_t * _tnf_get_element_named(TNF *, tnf_ref32_t *, char *); +tnf_ref32_t * _tnf_get_base_tag(TNF *, tnf_ref32_t *); + +size_t _tnf_get_storage_size(TNF *, tnf_ref32_t *); +size_t _tnf_get_ref_size(TNF *, tnf_ref32_t *); + +unsigned _tnf_get_align(TNF *, tnf_ref32_t *); + +caddr_t _tnf_get_slot_typed(TNF *, tnf_ref32_t *, char *); +caddr_t _tnf_get_slot_named(TNF *, tnf_ref32_t *, char *); + +#define HAS_PROPERTY(tnf, tag, name) \ + (_tnf_get_property(tnf, tag, name) != TNF_NULL) + +/* + * Call the installed error handler with installed arg + */ + +void _tnf_error(TNF *, tnf_errcode_t); + +/* + * Tag lookup operations + */ + +struct taginfo * _tnf_get_info(TNF *, tnf_ref32_t *); +struct taginfo * _tnf_record_info(TNF *, tnf_ref32_t *); + +tnf_errcode_t _tnf_init_tags(TNF *); +tnf_errcode_t _tnf_fini_tags(TNF *); + +/* + * Classify a tag into its props and data kind + */ + +tag_props_t _tnf_get_props(TNF *, tnf_ref32_t *); +tnf_kind_t _tnf_get_kind(TNF *, tnf_ref32_t *); + +caddr_t _tnf_get_member(TNF *, caddr_t, struct taginfo *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBTNF_H */ diff --git a/usr/src/lib/libtnf/machlibtnf.h b/usr/src/lib/libtnf/machlibtnf.h new file mode 100644 index 0000000000..a10fc2b219 --- /dev/null +++ b/usr/src/lib/libtnf/machlibtnf.h @@ -0,0 +1,60 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _MACHLIBTNF_H +#define _MACHLIBTNF_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/isa_defs.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_BIG_ENDIAN) || defined(__sparc) + +tnf_uint32_t _tnf_swap32(tnf_uint32_t); +tnf_uint16_t _tnf_swap16(tnf_uint16_t); + +#elif defined(_LITTLE_ENDIAN) || defined(__i386) || defined(__amd64) + +#include <sys/byteorder.h> + +#define _tnf_swap32(x) ntohl(x) +#define _tnf_swap16(x) ntohs(x) + +#else + +#error Unknown endian + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _MACHLIBTNF_H */ diff --git a/usr/src/lib/libtnf/reader.c b/usr/src/lib/libtnf/reader.c new file mode 100644 index 0000000000..c7d3d8fe74 --- /dev/null +++ b/usr/src/lib/libtnf/reader.c @@ -0,0 +1,191 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * Initiate a reader session + */ + +tnf_errcode_t +tnf_reader_begin(caddr_t base, size_t size, TNF **tnfret) +{ + tnf_uint32_t magic; + int native; + TNF *tnf; + tnf_ref32_t *fhdr, *bhdr; + size_t tmpsz; + caddr_t p, genp, bvp; + tnf_errcode_t err; + + /* + * Check magic number + */ + + /* LINTED pointer cast may result in improper alignment */ + if ((magic = *(tnf_uint32_t *)base) == TNF_MAGIC) + native = 1; /* same endian */ + else if (magic == TNF_MAGIC_1) + native = 0; /* other endian */ + else + return (TNF_ERR_NOTTNF); + + /* + * Allocate TNF struct, initialize members + */ + + if ((tnf = (TNF*)calloc(1, sizeof (*tnf))) == (TNF*)NULL) + return (TNF_ERR_ALLOCFAIL); + + tnf->file_magic = magic; + tnf->file_native = native; + tnf->file_start = base; + tnf->file_size = size; + tnf->file_end = base + size; + + /* + * Examine file header + */ + + /* LINTED pointer cast may result in improper alignment */ + fhdr = (tnf_ref32_t *)(base + sizeof (magic)); /* second word */ + tnf->file_header = fhdr; + + /* Block size */ + p = _tnf_get_slot_named(tnf, fhdr, TNF_N_BLOCK_SIZE); + /* LINTED pointer cast may result in improper alignment */ + tnf->block_size = _GET_UINT32(tnf, (tnf_uint32_t *)p); + + /* Directory size */ + p = _tnf_get_slot_named(tnf, fhdr, TNF_N_DIRECTORY_SIZE); + /* LINTED pointer cast may result in improper alignment */ + tnf->directory_size = _GET_UINT32(tnf, (tnf_uint32_t *)p); + + /* Block count */ + p = _tnf_get_slot_named(tnf, fhdr, TNF_N_BLOCK_COUNT); + /* LINTED pointer cast may result in improper alignment */ + tnf->block_count = _GET_UINT32(tnf, (tnf_uint32_t *)p); + /* + * This member tracks data block count, not total block count + * (unlike the TNF file header). Discount directory blocks. + */ + tnf->block_count -= tnf->directory_size / tnf->block_size; + + /* + * 1196886: Clients may supply file_size information obtained + * by fstat() which is incorrect. Check it now and revise + * downwards if we have to. + */ + tmpsz = tnf->directory_size + tnf->block_count * tnf->block_size; + if (tmpsz != size) { + if (tmpsz > size) + /* missing data? */ + return (TNF_ERR_BADTNF); + else { + tnf->file_size = tmpsz; + tnf->file_end = base + tmpsz; + } + } + + /* Calculate block shift */ + tmpsz = 1; + while (tmpsz != tnf->block_size) { + tmpsz <<= 1; + tnf->block_shift++; + } + + /* Calculate block mask */ + tnf->block_mask = ~(tnf->block_size - 1); + + /* Generation shift */ + p = _tnf_get_slot_named(tnf, fhdr, TNF_N_FILE_LOGICAL_SIZE); + /* LINTED pointer cast may result in improper alignment */ + tnf->generation_shift = _GET_UINT32(tnf, (tnf_uint32_t *)p); + + /* Calculate the address mask */ + /* + * Following lint complaint is unwarranted, probably an + * uninitialized variable in lint or something ... + */ + /* LINTED constant truncated by assignment */ + tnf->address_mask = 0xffffffff; + tnf->address_mask <<= tnf->generation_shift; + tnf->address_mask = ~(tnf->address_mask); + + + /* + * Examine first block header in data area + */ + + tnf->data_start = tnf->file_start + tnf->directory_size; + /* LINTED pointer cast may result in improper alignment */ + bhdr = (tnf_ref32_t *)tnf->data_start; + + /* Block generation offset */ + genp = _tnf_get_slot_named(tnf, bhdr, TNF_N_GENERATION); + tnf->block_generation_offset = genp - (caddr_t)bhdr; + + /* Block bytes valid offset */ + bvp = _tnf_get_slot_named(tnf, bhdr, TNF_N_BYTES_VALID); + tnf->block_bytes_valid_offset = bvp - (caddr_t)bhdr; + + /* + * Bootstrap taginfo system and cache important taginfo + */ + + if ((err = _tnf_init_tags(tnf)) != TNF_ERR_NONE) + return (err); + + tnf->file_header_info = _tnf_get_info(tnf, _tnf_get_tag(tnf, fhdr)); + tnf->block_header_info = _tnf_get_info(tnf, _tnf_get_tag(tnf, bhdr)); + + /* + * Return TNF handle and error status + */ + + *tnfret = tnf; + return (TNF_ERR_NONE); +} + +/* + * Terminate a reader session + */ + +tnf_errcode_t +tnf_reader_end(TNF *tnf) +{ + tnf_errcode_t err; + + /* Deallocate all taginfo */ + if ((err = _tnf_fini_tags(tnf)) != TNF_ERR_NONE) + return (err); + + /* Deallocate TNF */ + free(tnf); + + return (TNF_ERR_NONE); +} diff --git a/usr/src/lib/libtnf/record.c b/usr/src/lib/libtnf/record.c new file mode 100644 index 0000000000..b5fabb0287 --- /dev/null +++ b/usr/src/lib/libtnf/record.c @@ -0,0 +1,66 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * Check a record datum + */ + +void +_tnf_check_record(tnf_datum_t datum) +{ + CHECK_DATUM(datum); + + /* All records must be tagged */ + if (!INFO_TAGGED(DATUM_INFO(datum))) + _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH); +} + +/* + * Retrieve the tag arg, encoded in low 16 bits of tag word + */ + +tnf_datum_t +tnf_get_tag_arg(tnf_datum_t datum) +{ + TNF *tnf; + tnf_ref32_t *arg; + + CHECK_RECORD(datum); + + tnf = DATUM_TNF(datum); + + /* Should not give an error if not found */ + /* LINTED pointer cast may result in improper alignment */ + arg = _tnf_get_tag_arg(tnf, DATUM_RECORD(datum)); + + if (arg == TNF_NULL) + return (TNF_DATUM_NULL); + else /* repackage the tag arg with its taginfo */ + return (RECORD_DATUM(tnf, arg)); +} diff --git a/usr/src/lib/libtnf/ref.c b/usr/src/lib/libtnf/ref.c new file mode 100644 index 0000000000..07e0ccccfb --- /dev/null +++ b/usr/src/lib/libtnf/ref.c @@ -0,0 +1,232 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * Unoptimized versions, always dereference a cell through _GET_INT32() + * + */ + +#define LONG_SIGN_BIT 0x80000000 + +static tnf_ref32_t *vaddr_to_phys(TNF *, tnf_ref32_t *, tnf_ref32_t); + +/* + * Return target cell referred to via src_val from src_cell, after + * checking that target is valid (block was not reused). Return NULL + * otherwise. + * + * NOTE: We must check if the destination is within the valid_bytes + * range of its block, so as to correctly handle tnfxtract'ed files: + * the block containing the target cell may have been copied out + * before the block containing the source cell. + */ + +static tnf_ref32_t * +vaddr_to_phys(TNF *tnf, tnf_ref32_t *src_cell, tnf_ref32_t src_val) +{ + char *base; + unsigned shft, mask; + tnf_uint32_t src_gen, dst_gen, exp_gen; + tnf_int32_t gen_delta; + tnf_ref32_t src_off, exp_off, dst_off, *dst_blk, *dst_cell; + tnf_uint32_t bytes_valid; + + base = tnf->file_start; + shft = tnf->generation_shift; + mask = tnf->address_mask; + + /* Generation of source cell */ + /* LINTED pointer cast */ + src_gen = _GET_BLOCK_GENERATION(tnf, _GET_BLOCK(tnf, src_cell)); + /* Physical file offset of source cell */ + src_off = (tnf_ref32_t)((char *)src_cell - base); + /* Expected (unadjusted) file offset of destination cell */ + exp_off = src_off + src_val; + /* Generation delta */ + gen_delta = (tnf_int32_t)((unsigned)exp_off >> shft); + if ((exp_off & LONG_SIGN_BIT) == LONG_SIGN_BIT) { + /* sign bit was a 1 - so restore sign */ + gen_delta |= ((unsigned)mask << (32 - shft)); + } + /* Expected destination generation */ + exp_gen = src_gen + gen_delta; + /* Physical file offset of destination cell */ + dst_off = (tnf_ref32_t)((unsigned)exp_off & mask); + + /* Destination cell */ + /* LINTED pointer cast */ + dst_cell = (tnf_ref32_t *)(base + dst_off); + /* Destination block */ + /* LINTED pointer cast */ + dst_blk = _GET_BLOCK(tnf, dst_cell); + /* Generation of destination cell */ + /* LINTED pointer cast */ + dst_gen = _GET_BLOCK_GENERATION(tnf, dst_blk); + /* Bytes valid in destination block */ + /* LINTED pointer cast */ + bytes_valid = _GET_BLOCK_BYTES_VALID(tnf, dst_blk); + + if ((src_gen == (tnf_uint32_t)TNF_TAG_GENERATION_NUM) || + (dst_gen == (tnf_uint32_t)TNF_TAG_GENERATION_NUM) || + ((dst_gen == exp_gen) && + ((char *)dst_cell - (char *)dst_blk) < bytes_valid)) + return (dst_cell); + + return ((tnf_ref32_t *)NULL); +} + +/* + * Return the target referent of a cell, chasing forwarding references. + * Return TNF_NULL if cell is a TNF_NULL forwarding reference. + */ + +tnf_ref32_t * +_tnf_get_ref32(TNF *tnf, tnf_ref32_t *cell) +{ + tnf_ref32_t ref32, reftemp; + + ref32 = _GET_INT32(tnf, cell); + + if (TNF_REF32_IS_NULL(ref32)) + return (TNF_NULL); + + if (TNF_REF32_IS_RSVD(ref32)) { + _tnf_error(tnf, TNF_ERR_BADREFTYPE); + return (TNF_NULL); + } + + if (TNF_REF32_IS_PAIR(ref32)) { + /* We chase the high (tag) half */ + tnf_ref16_t tag16; + + tag16 = TNF_REF32_TAG16(ref32); + + if (TNF_TAG16_IS_ABS(tag16)) { + cell = (tnf_ref32_t *) + ((char *)tnf->file_start +/* LINTED pointer cast may result in improper alignment */ + + TNF_TAG16_ABS16(tag16)); + ref32 = _GET_INT32(tnf, cell); + + } else if (TNF_TAG16_IS_REL(tag16)) { + cell = vaddr_to_phys(tnf, cell, + (tnf_ref32_t) TNF_TAG16_REF16(tag16)); + if (cell == TNF_NULL) + return (TNF_NULL); + ref32 = _GET_INT32(tnf, cell); + + } else { + _tnf_error(tnf, TNF_ERR_BADREFTYPE); + return (TNF_NULL); + } + + } else if (TNF_REF32_IS_PERMANENT(ref32)) { + /* permanent space pointer */ + reftemp = TNF_REF32_VALUE(ref32); + reftemp = TNF_REF32_SIGN_EXTEND(reftemp); + /* LINTED pointer cast may result in improper alignment */ + cell = (tnf_ref32_t *) ((char *)tnf->file_start + reftemp); + ref32 = _GET_INT32(tnf, cell); + + } else { /* full/tag reclaimable space reference */ + cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32)); + if (cell == TNF_NULL) + return (TNF_NULL); + ref32 = _GET_INT32(tnf, cell); + } + + /* chase intermediate forwarding references */ + while (ref32 && TNF_REF32_IS_FWD(ref32)) { + if (TNF_REF32_IS_PERMANENT(ref32)) { + reftemp = TNF_REF32_VALUE(ref32); + reftemp = TNF_REF32_SIGN_EXTEND(reftemp); + cell = (tnf_ref32_t *) ((char *)tnf->file_start + + /* LINTED pointer cast may result in improper alignment */ + reftemp); + + } else { + cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32)); + if (cell == TNF_NULL) + return (TNF_NULL); + } + ref32 = _GET_INT32(tnf, cell); + } + + return (cell); +} + +/* + * Return the target referent of ref16 contained in cell. + * Return TNF_NULL if cell doesn't have a ref16. + */ + +tnf_ref32_t * +_tnf_get_ref16(TNF *tnf, tnf_ref32_t *cell) +{ + tnf_ref32_t ref32, reftemp; + + ref32 = _GET_INT32(tnf, cell); + + if (TNF_REF32_IS_PAIR(ref32)) { + tnf_ref16_t ref16; + + ref16 = TNF_REF32_REF16(ref32); + + if (TNF_REF16_VALUE(ref16) == TNF_NULL) + /* No ref16 was stored */ + return (TNF_NULL); + else { + cell = vaddr_to_phys(tnf, cell, + (tnf_ref32_t) TNF_REF16_VALUE(ref16)); + if (cell == TNF_NULL) + return (TNF_NULL); + ref32 = _GET_INT32(tnf, cell); + } + } else /* not a pair pointer */ + return (TNF_NULL); + + /* chase intermediate forwarding references */ + while (ref32 && TNF_REF32_IS_FWD(ref32)) { + if (TNF_REF32_IS_PERMANENT(ref32)) { + reftemp = TNF_REF32_VALUE(ref32); + reftemp = TNF_REF32_SIGN_EXTEND(reftemp); + cell = (tnf_ref32_t *) ((char *)tnf->file_start + + /* LINTED pointer cast may result in improper alignment */ + reftemp); + + } else { + cell = vaddr_to_phys(tnf, cell, TNF_REF32_VALUE(ref32)); + if (cell == TNF_NULL) + return (TNF_NULL); + } + ref32 = _GET_INT32(tnf, cell); + } + + return (cell); +} diff --git a/usr/src/lib/libtnf/scalar.c b/usr/src/lib/libtnf/scalar.c new file mode 100644 index 0000000000..8d37f690a1 --- /dev/null +++ b/usr/src/lib/libtnf/scalar.c @@ -0,0 +1,170 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * + */ + +#define CHECK_SCALAR(datum) check_scalar(datum) + +#define DATUM_NATIVE(x) DATUM_TNF(datum)->file_native + +/* + * + */ + +static void check_scalar(tnf_datum_t); + +static tnf_uint64_t get_uint64(TNF *tnf, caddr_t val); + +/* + * + */ + +static void +check_scalar(tnf_datum_t datum) +{ + CHECK_DATUM(datum); + if (!INFO_SCALAR(DATUM_INFO(datum))) + _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH); + /* XXX Need to check for exact scalar type match as well */ +} + +/* + * Exported scalar operations + */ + +/* No swapping required: */ + +char +tnf_get_char(tnf_datum_t datum) +{ + CHECK_SCALAR(datum); + return (*(char *)DATUM_VAL(datum)); +} + +tnf_int8_t +tnf_get_int8(tnf_datum_t datum) +{ + CHECK_SCALAR(datum); + return (*(tnf_int8_t *)DATUM_VAL(datum)); +} + +tnf_int16_t +tnf_get_int16(tnf_datum_t datum) +{ + tnf_int16_t val; + + CHECK_SCALAR(datum); + /* LINTED pointer cast may result in improper alignment */ + val = *(tnf_int16_t *)DATUM_VAL(datum); + return (DATUM_NATIVE(datum) ? val : _tnf_swap16(val)); +} + +/* 32-bit integers: */ + +tnf_int32_t +tnf_get_int32(tnf_datum_t datum) +{ + CHECK_SCALAR(datum); + /* LINTED pointer cast may result in improper alignment */ + return (_GET_INT32(DATUM_TNF(datum), DATUM_VAL(datum))); +} + +/* 64-bit integers: */ + +static tnf_uint64_t +get_uint64(TNF *tnf, caddr_t val) +{ + tnf_uint32_t hi32, lo32; /* XXX both assumed unsigned */ + + /* XXX Can't rely on address alignment */ + /* LINTED pointer cast may result in improper alignment */ + hi32 = *(tnf_uint32_t *)val; + /* LINTED pointer cast may result in improper alignment */ + lo32 = *(tnf_uint32_t *)(val + sizeof (tnf_uint32_t)); + +#ifdef _LONG_LONG_HTOL + /* eg. sparc */ + if (tnf->file_native) + return ((((tnf_uint64_t)hi32) << 32) + + (tnf_uint64_t)lo32); + else + /* XXX Assume words are swapped as well: */ + return ((((tnf_uint64_t)_tnf_swap32(lo32)) << 32) + + (tnf_uint64_t)_tnf_swap32(hi32)); +#else + /* eg. i386 */ + if (tnf->file_native) + return ((((tnf_uint64_t)lo32) << 32) + + (tnf_uint64_t)hi32); + else + /* XXX Assume words are swapped as well: */ + return ((((tnf_uint64_t)_tnf_swap32(hi32)) << 32) + + (tnf_uint64_t)_tnf_swap32(lo32)); +#endif +} + +tnf_int64_t +tnf_get_int64(tnf_datum_t datum) +{ + CHECK_SCALAR(datum); + return (get_uint64(DATUM_TNF(datum), DATUM_VAL(datum))); +} + +/* floats: */ + +tnf_float32_t +tnf_get_float32(tnf_datum_t datum) +{ + union { + tnf_uint32_t i32; + tnf_float32_t f32; + } u; + + CHECK_SCALAR(datum); + + /* LINTED pointer cast may result in improper alignment */ + u.i32 = _GET_UINT32(DATUM_TNF(datum), DATUM_VAL(datum)); /* XXX */ + return (u.f32); +} + +tnf_float64_t +tnf_get_float64(tnf_datum_t datum) +{ + union { + tnf_uint64_t i64; + tnf_float64_t f64; + } u; + + CHECK_SCALAR(datum); + + u.i64 = get_uint64(DATUM_TNF(datum), DATUM_VAL(datum)); /* XXX */ + return (u.f64); +} diff --git a/usr/src/lib/libtnf/sparcdep.c b/usr/src/lib/libtnf/sparcdep.c new file mode 100644 index 0000000000..04d006ad93 --- /dev/null +++ b/usr/src/lib/libtnf/sparcdep.c @@ -0,0 +1,40 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +tnf_uint32_t +_tnf_swap32(tnf_uint32_t x) +{ + return (((x<<24) | (((x>>8)<<24)>>8) | (((x<<8)>>24)<<8) | (x>>24))); +} + +tnf_uint16_t +_tnf_swap16(tnf_uint16_t x) +{ + return (((x<<8) | (x>>8))); +} diff --git a/usr/src/lib/libtnf/spec/Makefile b/usr/src/lib/libtnf/spec/Makefile new file mode 100644 index 0000000000..789cc7cbfa --- /dev/null +++ b/usr/src/lib/libtnf/spec/Makefile @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libtnf/spec/Makefile + +# +# no sparcv9 build of libresolv +# if it is desirable to build one then uncomment the line below and delete +# the rest of the lines. +# +#include $(SRC)/lib/Makefile.spec.arch + +i386_ARCHITECTURES = i386 +sparc_ARCHITECTURES = sparc + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint + +.KEEP_STATE: + +all install clean clobber lint: $($(MACH)_ARCHITECTURES) + +# spec files do not have msgs or catalogs +_msg catalog: + +$($(MACH)_ARCHITECTURES): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/libtnf/spec/Makefile.targ b/usr/src/lib/libtnf/spec/Makefile.targ new file mode 100644 index 0000000000..b99ce2250a --- /dev/null +++ b/usr/src/lib/libtnf/spec/Makefile.targ @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libtnf/spec/Makefile.targ + +LIBRARY = libtnf.a +VERS = .1 + +OBJECTS = tnf.o + +SPECCPP = -I.. -I../.. diff --git a/usr/src/lib/libtnf/spec/amd64/Makefile b/usr/src/lib/libtnf/spec/amd64/Makefile new file mode 100644 index 0000000000..d334868181 --- /dev/null +++ b/usr/src/lib/libtnf/spec/amd64/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS) + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libtnf/spec/i386/Makefile b/usr/src/lib/libtnf/spec/i386/Makefile new file mode 100644 index 0000000000..569932e5ab --- /dev/null +++ b/usr/src/lib/libtnf/spec/i386/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libtnf/spec/i386/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#i386_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libtnf/spec/sparc/Makefile b/usr/src/lib/libtnf/spec/sparc/Makefile new file mode 100644 index 0000000000..9f90d1bd91 --- /dev/null +++ b/usr/src/lib/libtnf/spec/sparc/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libtnf/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libtnf/spec/sparcv9/Makefile b/usr/src/lib/libtnf/spec/sparcv9/Makefile new file mode 100644 index 0000000000..cbf3eb7fa6 --- /dev/null +++ b/usr/src/lib/libtnf/spec/sparcv9/Makefile @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libtnf/spec/sparcv9/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#sparcv9_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libtnf/spec/tnf.spec b/usr/src/lib/libtnf/spec/tnf.spec new file mode 100644 index 0000000000..9ee8baa0f1 --- /dev/null +++ b/usr/src/lib/libtnf/spec/tnf.spec @@ -0,0 +1,316 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libtnf/spec/tnf.spec + +function tnf_default_error_handler +include <libtnf.h> +declaration void tnf_default_error_handler(void *arg, TNF *tnf, \ + tnf_errcode_t err) +version SUNWprivate_1.1 +end + +function tnf_error_message +include <libtnf.h> +declaration char * tnf_error_message(tnf_errcode_t err) +version SUNWprivate_1.1 +end + +function tnf_get_block_absolute +include <libtnf.h> +declaration tnf_datum_t tnf_get_block_absolute(TNF *tnf, unsigned index) +version SUNWprivate_1.1 +end + +function tnf_get_block_count +include <libtnf.h> +declaration unsigned tnf_get_block_count(TNF *tnf) +version SUNWprivate_1.1 +end + +function tnf_get_block_header +include <libtnf.h> +declaration tnf_datum_t tnf_get_block_header(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_block_relative +include <libtnf.h> +declaration tnf_datum_t tnf_get_block_relative(tnf_datum_t datum, \ + int adjust) +version SUNWprivate_1.1 +end + +function tnf_get_char +include <libtnf.h> +declaration char tnf_get_char(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_chars +include <libtnf.h> +declaration char * tnf_get_chars(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_element +include <libtnf.h> +declaration tnf_datum_t tnf_get_element(tnf_datum_t datum, unsigned) +version SUNWprivate_1.1 +end + +function tnf_get_element_count +include <libtnf.h> +declaration unsigned tnf_get_element_count(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_element_type +include <libtnf.h> +declaration tnf_datum_t tnf_get_element_type(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_elements +include <libtnf.h> +declaration caddr_t tnf_get_elements(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_file_header +include <libtnf.h> +declaration tnf_datum_t tnf_get_file_header(TNF *tnf) +version SUNWprivate_1.1 +end + +function tnf_get_float32 +include <libtnf.h> +declaration tnf_float32_t tnf_get_float32(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_float64 +include <libtnf.h> +declaration tnf_float64_t tnf_get_float64(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_int16 +include <libtnf.h> +declaration tnf_int16_t tnf_get_int16(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_int32 +include <libtnf.h> +declaration tnf_int32_t tnf_get_int32(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_int64 +include <libtnf.h> +declaration tnf_int64_t tnf_get_int64(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_int8 +include <libtnf.h> +declaration tnf_int8_t tnf_get_int8(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_kind +include <libtnf.h> +declaration tnf_kind_t tnf_get_kind(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_next_record +include <libtnf.h> +declaration tnf_datum_t tnf_get_next_record(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_raw +include <libtnf.h> +declaration caddr_t tnf_get_raw(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_size +include <libtnf.h> +declaration size_t tnf_get_size(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_slot_count +include <libtnf.h> +declaration unsigned tnf_get_slot_count(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_slot_index +include <libtnf.h> +declaration unsigned tnf_get_slot_index(tnf_datum_t datum, char *name) +version SUNWprivate_1.1 +end + +function tnf_get_slot_indexed +include <libtnf.h> +declaration tnf_datum_t tnf_get_slot_indexed(tnf_datum_t datum, \ + unsigned index) +version SUNWprivate_1.1 +end + +function tnf_get_slot_name +include <libtnf.h> +declaration char * tnf_get_slot_name(tnf_datum_t datum, unsigned index) +version SUNWprivate_1.1 +end + +function tnf_get_slot_named +include <libtnf.h> +declaration tnf_datum_t tnf_get_slot_named(tnf_datum_t datum, char *name) +version SUNWprivate_1.1 +end + +function tnf_get_tag_arg +include <libtnf.h> +declaration tnf_datum_t tnf_get_tag_arg(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_type +include <libtnf.h> +declaration tnf_datum_t tnf_get_type(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_get_type_name +include <libtnf.h> +declaration char * tnf_get_type_name(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_array +include <libtnf.h> +declaration int tnf_is_array(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_block_header +include <libtnf.h> +declaration int tnf_is_block_header(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_inline +include <libtnf.h> +declaration int tnf_is_inline(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_record +include <libtnf.h> +declaration int tnf_is_record(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_scalar +include <libtnf.h> +declaration int tnf_is_scalar(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_string +include <libtnf.h> +declaration int tnf_is_string(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_struct +include <libtnf.h> +declaration int tnf_is_struct(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_is_type +include <libtnf.h> +declaration int tnf_is_type(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_reader_begin +include <libtnf.h> +declaration tnf_errcode_t tnf_reader_begin(caddr_t base, size_t size, \ + TNF **tnfret) +version SUNWprivate_1.1 +end + +function tnf_reader_end +include <libtnf.h> +declaration tnf_errcode_t tnf_reader_end(TNF *tnf) +version SUNWprivate_1.1 +end + +function tnf_set_error_handler +include <libtnf.h> +#declaration void tnf_set_error_handler(tnf_error_handler_t *handler, void *arg) +# Using alternate binary equivalent for delaration +declaration void tnf_set_error_handler(void (*handler)(void *, TNF *, tnf_errcode_t), void *arg) +version SUNWprivate_1.1 +end + +function tnf_type_get_base +include <libtnf.h> +declaration tnf_datum_t tnf_type_get_base(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_type_get_kind +include <libtnf.h> +declaration tnf_kind_t tnf_type_get_kind(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_type_get_name +include <libtnf.h> +declaration char * tnf_type_get_name(tnf_datum_t datum) +version SUNWprivate_1.1 +end + +function tnf_type_get_property +include <libtnf.h> +declaration tnf_datum_t tnf_type_get_property(tnf_datum_t datum, char *name) +version SUNWprivate_1.1 +end + +function tnf_type_get_size +include <libtnf.h> +declaration size_t tnf_type_get_size(tnf_datum_t datum) +version SUNWprivate_1.1 +end + diff --git a/usr/src/lib/libtnf/spec/versions b/usr/src/lib/libtnf/spec/versions new file mode 100644 index 0000000000..a542a0f7fc --- /dev/null +++ b/usr/src/lib/libtnf/spec/versions @@ -0,0 +1,39 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNWprivate_1.1; +} +sparcv9 { + SUNWprivate_1.1; +} +i386 { + SUNWprivate_1.1; +} +amd64 { + SUNWprivate_1.1; +} diff --git a/usr/src/lib/libtnf/struct.c b/usr/src/lib/libtnf/struct.c new file mode 100644 index 0000000000..c7aa1e6a95 --- /dev/null +++ b/usr/src/lib/libtnf/struct.c @@ -0,0 +1,220 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * + */ + +static struct slotinfo *get_slotinfo(tnf_datum_t); +static struct slot * get_slot_named(struct slotinfo *, char *); +static struct slot * get_slot_indexed(struct slotinfo *, unsigned); +static tnf_datum_t get_slot(tnf_datum_t, struct slot *); + +/* + * + */ + +void +_tnf_check_slots(tnf_datum_t datum) +{ + struct taginfo *info; + + CHECK_DATUM(datum); + + info = DATUM_INFO(datum); + + /* Must be an aggregate */ + if (!(INFO_STRUCT(info) || INFO_ARRAY(info))) + _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH); +} + +/* + * Helpers + */ + +static struct slotinfo * +get_slotinfo(tnf_datum_t datum) +{ + struct taginfo *info, *base_info; + + info = DATUM_INFO(datum); + base_info = INFO_DERIVED(info)? info->base: info; + + /* XXX base must not be a scalar tag */ + if (INFO_SCALAR(base_info)) + _tnf_error(DATUM_TNF(datum), TNF_ERR_BADTNF); + + return (base_info->slotinfo); +} + +static struct slot * +get_slot_indexed(struct slotinfo *slotinfo, unsigned index) +{ + unsigned count; + + count = slotinfo->slot_count; + if (index >= count) + return (NULL); + else + return (&slotinfo->slots[index]); +} + +static struct slot * +get_slot_named(struct slotinfo *slotinfo, char *name) +{ + unsigned count, i; + + count = slotinfo->slot_count; + + for (i = 0; i < count; i++) + if (strcmp(name, slotinfo->slots[i].slot_name) == 0) + return (&slotinfo->slots[i]); + + return (NULL); +} + +static tnf_datum_t +get_slot(tnf_datum_t datum, struct slot *slot) +{ + if (slot == NULL) { + _tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */ + return (TNF_DATUM_NULL); + + } else if (INFO_TAGGED(slot->slot_type)) { + TNF *tnf; + tnf_ref32_t *rec; + + tnf = DATUM_TNF(datum); + /* LINTED pointer cast may result in improper alignment */ + rec = _GET_REF32(tnf, (tnf_ref32_t *) + (DATUM_VAL(datum) + slot->slot_offset)); + /* NULL slots are allowed */ + return ((rec == TNF_NULL)? TNF_DATUM_NULL : + RECORD_DATUM(tnf, rec)); + + } else /* inline */ + return DATUM(slot->slot_type, + DATUM_VAL(datum) + slot->slot_offset); +} + +/* + * + */ + +unsigned +tnf_get_slot_count(tnf_datum_t datum) +{ + struct slotinfo *slotinfo; + + CHECK_SLOTS(datum); + + slotinfo = get_slotinfo(datum); + return (slotinfo->slot_count); +} + +/* + * + */ + +unsigned +tnf_get_slot_index(tnf_datum_t datum, char *name) +{ + struct slotinfo *slotinfo; + struct slot *slot; + + CHECK_SLOTS(datum); + + slotinfo = get_slotinfo(datum); + slot = get_slot_named(slotinfo, name); + + if (slot == NULL) { + _tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */ + return (((unsigned)-1)); + } else + return (((char *)slot - (char *)&slotinfo->slots[0]) + / sizeof (struct slot)); +} + +/* + * + */ + +char * +tnf_get_slot_name(tnf_datum_t datum, unsigned index) +{ + struct slotinfo *slotinfo; + struct slot *slot; + + CHECK_SLOTS(datum); + + slotinfo = get_slotinfo(datum); + slot = get_slot_indexed(slotinfo, index); + + if (slot == NULL) { + _tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */ + return ((char *)NULL); + } else + return (slot->slot_name); +} + +/* + * + */ + +tnf_datum_t +tnf_get_slot_named(tnf_datum_t datum, char *name) +{ + struct slotinfo *slotinfo; + struct slot *slot; + + CHECK_SLOTS(datum); + + slotinfo = get_slotinfo(datum); + slot = get_slot_named(slotinfo, name); + + return (get_slot(datum, slot)); +} + +/* + * + */ + +tnf_datum_t +tnf_get_slot_indexed(tnf_datum_t datum, unsigned index) +{ + struct slotinfo *slotinfo; + struct slot *slot; + + CHECK_SLOTS(datum); + + slotinfo = get_slotinfo(datum); + slot = get_slot_indexed(slotinfo, index); + + return (get_slot(datum, slot)); +} diff --git a/usr/src/lib/libtnf/tnf.h b/usr/src/lib/libtnf/tnf.h new file mode 100644 index 0000000000..3560bbc35a --- /dev/null +++ b/usr/src/lib/libtnf/tnf.h @@ -0,0 +1,206 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#ifndef _TNF_TNF_H +#define _TNF_TNF_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <tnf/com.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque TNF handle + */ + +typedef struct TNF TNF; + +/* + * Opaque data handle + */ + +typedef unsigned long long tnf_datum_t; + +#define TNF_DATUM_NULL ((tnf_datum_t)0) + +/* + * Reader data classification + */ + +typedef enum { + TNF_K_UNKNOWN, /* unknown or error */ + TNF_K_SCALAR, /* unclassified scalar */ + TNF_K_CHAR, /* char */ + TNF_K_INT8, /* int8 */ + TNF_K_INT16, /* int16 */ + TNF_K_INT32, /* int32 */ + TNF_K_UINT8, /* uint8 */ + TNF_K_UINT16, /* uint16 */ + TNF_K_UINT32, /* uint32 */ + TNF_K_INT64, /* int64 */ + TNF_K_UINT64, /* uint64 */ + TNF_K_FLOAT32, /* float32 */ + TNF_K_FLOAT64, /* float64 */ + TNF_K_ARRAY, /* array */ + TNF_K_STRING, /* string */ + TNF_K_STRUCT, /* struct */ + TNF_K_TYPE /* type */ +} tnf_kind_t; + +/* + * Error codes + */ + +typedef enum { + TNF_ERR_NONE = 0, + + /* 1 through 1023 reserved for errno values */ +#define TNF_ERRNO_MAX 1023 + + TNF_ERR_NOTTNF = 1024, /* not TNF file */ + TNF_ERR_BADDATUM = 1025, /* bad or NULL data handle */ + TNF_ERR_TYPEMISMATCH = 1026, /* type mismatch */ + TNF_ERR_BADINDEX = 1027, /* array index out of bounds */ + TNF_ERR_BADSLOT = 1028, /* slot missing */ + TNF_ERR_BADREFTYPE = 1029, /* invalid reference type */ + TNF_ERR_ALLOCFAIL = 1030, /* memory allocation failure */ + TNF_ERR_BADTNF = 1031, /* bad TNF file */ + TNF_ERR_INTERNAL = 1032 /* internal error */ +} tnf_errcode_t; + +typedef void tnf_error_handler_t(void *, TNF *, tnf_errcode_t); + +/* + * TNF file interface + */ + +tnf_errcode_t tnf_reader_begin(caddr_t, size_t, TNF **); +tnf_errcode_t tnf_reader_end(TNF *); + +/* + * Error interface + */ + +void tnf_set_error_handler(tnf_error_handler_t *, void *); +char * tnf_error_message(tnf_errcode_t); + +tnf_error_handler_t tnf_default_error_handler; + +/* + * Data block access + */ + +unsigned tnf_get_block_count(TNF *); +tnf_datum_t tnf_get_block_absolute(TNF *, unsigned); +tnf_datum_t tnf_get_block_relative(tnf_datum_t, int); +int tnf_is_block_header(tnf_datum_t); + +/* + * Record access + */ + +tnf_datum_t tnf_get_next_record(tnf_datum_t); +tnf_datum_t tnf_get_block_header(tnf_datum_t); +tnf_datum_t tnf_get_file_header(TNF *); + +/* + * Data classification predicates + */ + +int tnf_is_inline(tnf_datum_t); +int tnf_is_scalar(tnf_datum_t); +int tnf_is_record(tnf_datum_t); +int tnf_is_array(tnf_datum_t); +int tnf_is_string(tnf_datum_t); +int tnf_is_struct(tnf_datum_t); +int tnf_is_type(tnf_datum_t); + +/* + * Data operations + */ + +tnf_kind_t tnf_get_kind(tnf_datum_t); +size_t tnf_get_size(tnf_datum_t); +tnf_datum_t tnf_get_type(tnf_datum_t); +char * tnf_get_type_name(tnf_datum_t); +caddr_t tnf_get_raw(tnf_datum_t); + +/* + * Record operations + */ + +tnf_datum_t tnf_get_tag_arg(tnf_datum_t); + +/* + * Array operations + */ + +unsigned tnf_get_element_count(tnf_datum_t); +tnf_datum_t tnf_get_element(tnf_datum_t, unsigned); +tnf_datum_t tnf_get_element_type(tnf_datum_t); +caddr_t tnf_get_elements(tnf_datum_t); +char * tnf_get_chars(tnf_datum_t); + +/* + * Struct operations + */ + +unsigned tnf_get_slot_count(tnf_datum_t); +char * tnf_get_slot_name(tnf_datum_t, unsigned); +unsigned tnf_get_slot_index(tnf_datum_t, char *); +tnf_datum_t tnf_get_slot_named(tnf_datum_t, char *); +tnf_datum_t tnf_get_slot_indexed(tnf_datum_t, unsigned); + +/* + * Scalar data conversions + */ + +char tnf_get_char(tnf_datum_t); +tnf_int8_t tnf_get_int8(tnf_datum_t); +tnf_int16_t tnf_get_int16(tnf_datum_t); +tnf_int32_t tnf_get_int32(tnf_datum_t); +tnf_int64_t tnf_get_int64(tnf_datum_t); +tnf_float32_t tnf_get_float32(tnf_datum_t); +tnf_float64_t tnf_get_float64(tnf_datum_t); + +/* + * Type (tag) record operations + */ + +tnf_kind_t tnf_type_get_kind(tnf_datum_t); +char * tnf_type_get_name(tnf_datum_t); +size_t tnf_type_get_size(tnf_datum_t); +tnf_datum_t tnf_type_get_property(tnf_datum_t, char *); +tnf_datum_t tnf_type_get_base(tnf_datum_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _TNF_TNF_H */ diff --git a/usr/src/lib/libtnf/type.c b/usr/src/lib/libtnf/type.c new file mode 100644 index 0000000000..bd18e26559 --- /dev/null +++ b/usr/src/lib/libtnf/type.c @@ -0,0 +1,137 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * All types are struct records + */ + +void +_tnf_check_type(tnf_datum_t datum) +{ + CHECK_RECORD(datum); + CHECK_SLOTS(datum); + + if (!INFO_TYPE(DATUM_INFO(datum))) + _tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH); +} + +/* + * Get data kind of a type record + */ + +tnf_kind_t +tnf_type_get_kind(tnf_datum_t datum) +{ + struct taginfo *info; + + CHECK_TYPE(datum); + + /* Note: DATUM_RECORD(), not DATUM_TAG() */ + /* LINTED pointer cast may result in improper alignment */ + info = _tnf_get_info(DATUM_TNF(datum), DATUM_RECORD(datum)); + return (info->kind); +} + +/* + * Retrieve type name for datum type record + */ + +char * +tnf_type_get_name(tnf_datum_t datum) +{ + CHECK_TYPE(datum); + /* XXX Dispatch to ABI routine; faster than taginfo lookup? */ + /* LINTED pointer cast may result in improper alignment */ + return (_tnf_get_name(DATUM_TNF(datum), DATUM_RECORD(datum))); +} + +/* + * Fetch size member of info for datum type record + */ + +size_t +tnf_type_get_size(tnf_datum_t datum) +{ + struct taginfo *info; + + CHECK_TYPE(datum); + + /* Note: DATUM_RECORD(), not DATUM_TAG() */ + /* LINTED pointer cast may result in improper alignment */ + info = _tnf_get_info(DATUM_TNF(datum), DATUM_RECORD(datum)); + + if (INFO_ARRAY(info)) + /* XXX All arrays are self-sized */ + return ((size_t)-1); + else + return (info->size); +} + +/* + * Get the base type of a type + */ + +tnf_datum_t +tnf_type_get_base(tnf_datum_t datum) +{ + struct taginfo *info; + + CHECK_TYPE(datum); + + /* Note: DATUM_RECORD(), not DATUM_TAG() */ + /* LINTED pointer cast may result in improper alignment */ + info = _tnf_get_info(DATUM_TNF(datum), DATUM_RECORD(datum)); + + if (INFO_DERIVED(info)) + return (DATUM(info->base->meta, (caddr_t)info->base->tag)); + else + return (datum); +} + +/* + * If type record has named property, return a datum for it + */ + +tnf_datum_t +tnf_type_get_property(tnf_datum_t datum, char *name) +{ + tnf_ref32_t *property; + + CHECK_TYPE(datum); + + /* Note: DATUM_RECORD(), not DATUM_TAG() */ + property = _tnf_get_property(DATUM_TNF(datum), + /* LINTED pointer cast may result in improper alignment */ + DATUM_RECORD(datum), name); + + if (property == TNF_NULL) + return (TNF_DATUM_NULL); + else + return (RECORD_DATUM(DATUM_TNF(datum), property)); +} diff --git a/usr/src/lib/libtnf/util.c b/usr/src/lib/libtnf/util.c new file mode 100644 index 0000000000..f81b8aa19c --- /dev/null +++ b/usr/src/lib/libtnf/util.c @@ -0,0 +1,129 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1994, by Sun Microsytems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "libtnf.h" + +/* + * + */ + +static struct ntop { + char *name; + tag_props_t prop; +} ntop[] = { +{ TNF_N_INLINE, TAG_PROP_INLINE }, +{ TNF_N_TAGGED, TAG_PROP_TAGGED }, +{ TNF_N_SCALAR, TAG_PROP_SCALAR }, +{ TNF_N_DERIVED, TAG_PROP_DERIVED }, +{ TNF_N_ARRAY, TAG_PROP_ARRAY }, +{ TNF_N_STRING, TAG_PROP_STRING }, +{ TNF_N_STRUCT, TAG_PROP_STRUCT }, +{ TNF_N_TYPE, TAG_PROP_TYPE }, +{ NULL, 0} +}; + +static struct ntok { + char *name; + tnf_kind_t kind; +} scalar_ntok[] = { +{ TNF_N_CHAR, TNF_K_CHAR }, +{ TNF_N_INT8, TNF_K_INT8 }, +{ TNF_N_INT16, TNF_K_INT16 }, +{ TNF_N_INT32, TNF_K_INT32 }, +{ TNF_N_UINT8, TNF_K_UINT8 }, +{ TNF_N_UINT16, TNF_K_UINT16 }, +{ TNF_N_UINT32, TNF_K_UINT32 }, +{ TNF_N_INT64, TNF_K_INT64 }, +{ TNF_N_UINT64, TNF_K_UINT64 }, +{ TNF_N_FLOAT32, TNF_K_FLOAT32 }, +{ TNF_N_FLOAT64, TNF_K_FLOAT64 }, +{ NULL, 0 } +}; + +/* + * Compute tag props + */ + +tag_props_t +_tnf_get_props(TNF *tnf, tnf_ref32_t *tag) +{ + tag_props_t props; + struct ntop *p; + + props = 0; + + p = ntop; + /* No need to get base tag for inherited properties */ + while (p->name) { + if (HAS_PROPERTY(tnf, tag, p->name)) + props |= p->prop; + p++; + } + + return (props); +} + +/* + * Data kind depends on implementation properties of base tag + */ + +tnf_kind_t +_tnf_get_kind(TNF *tnf, tnf_ref32_t *tag) +{ + tnf_ref32_t *base_tag; + char *base_name; + + base_tag = _tnf_get_base_tag(tnf, tag); + base_name = _tnf_get_name(tnf, base_tag); + + if (HAS_PROPERTY(tnf, base_tag, TNF_N_SCALAR)) { + struct ntok *p; + + p = scalar_ntok; + while (p->name) { + if (strcmp(p->name, base_name) == 0) + return (p->kind); + p++; + } + return (TNF_K_SCALAR); + + } else if (HAS_PROPERTY(tnf, base_tag, TNF_N_ARRAY)) { + if (strcmp(base_name, TNF_N_STRING) == 0) + return (TNF_K_STRING); + else + return (TNF_K_ARRAY); + + } else if (HAS_PROPERTY(tnf, base_tag, TNF_N_TYPE)) { + return (TNF_K_TYPE); + + } else if (HAS_PROPERTY(tnf, base_tag, TNF_N_STRUCT)) { + return (TNF_K_STRUCT); + + } else { /* abstract */ + return (TNF_K_UNKNOWN); + } +} |