Home | History | Annotate | Download | only in libtnf
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  *	Copyright (c) 1994, by Sun Microsytems, Inc.
     24  */
     25 
     26 #pragma	ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include "libtnf.h"
     29 
     30 /*
     31  * Initiate a reader session
     32  */
     33 
     34 tnf_errcode_t
     35 tnf_reader_begin(caddr_t base, size_t size, TNF **tnfret)
     36 {
     37 	tnf_uint32_t 	magic;
     38 	int 		native;
     39 	TNF 		*tnf;
     40 	tnf_ref32_t	*fhdr, *bhdr;
     41 	size_t		tmpsz;
     42 	caddr_t		p, genp, bvp;
     43 	tnf_errcode_t	err;
     44 
     45 	/*
     46 	 * Check magic number
     47 	 */
     48 
     49 	/* LINTED pointer cast may result in improper alignment */
     50 	if ((magic = *(tnf_uint32_t *)base) == TNF_MAGIC)
     51 		native = 1;	/* same endian */
     52 	else if (magic == TNF_MAGIC_1)
     53 		native = 0;	/* other endian */
     54 	else
     55 		return (TNF_ERR_NOTTNF);
     56 
     57 	/*
     58 	 * Allocate TNF struct, initialize members
     59 	 */
     60 
     61 	if ((tnf = (TNF*)calloc(1, sizeof (*tnf))) == (TNF*)NULL)
     62 		return (TNF_ERR_ALLOCFAIL);
     63 
     64 	tnf->file_magic 	= magic;
     65 	tnf->file_native 	= native;
     66 	tnf->file_start 	= base;
     67 	tnf->file_size 		= size;
     68 	tnf->file_end 		= base + size;
     69 
     70 	/*
     71 	 * Examine file header
     72 	 */
     73 
     74 	/* LINTED pointer cast may result in improper alignment */
     75 	fhdr = (tnf_ref32_t *)(base + sizeof (magic)); /* second word */
     76 	tnf->file_header = fhdr;
     77 
     78 	/* Block size */
     79 	p = _tnf_get_slot_named(tnf, fhdr, TNF_N_BLOCK_SIZE);
     80 	/* LINTED pointer cast may result in improper alignment */
     81 	tnf->block_size	= _GET_UINT32(tnf, (tnf_uint32_t *)p);
     82 
     83 	/* Directory size */
     84 	p = _tnf_get_slot_named(tnf, fhdr, TNF_N_DIRECTORY_SIZE);
     85 	/* LINTED pointer cast may result in improper alignment */
     86 	tnf->directory_size = _GET_UINT32(tnf, (tnf_uint32_t *)p);
     87 
     88 	/* Block count */
     89 	p = _tnf_get_slot_named(tnf, fhdr, TNF_N_BLOCK_COUNT);
     90 	/* LINTED pointer cast may result in improper alignment */
     91 	tnf->block_count = _GET_UINT32(tnf, (tnf_uint32_t *)p);
     92 	/*
     93 	 * This member tracks data block count, not total block count
     94 	 * (unlike the TNF file header).   Discount directory blocks.
     95 	 */
     96 	tnf->block_count -= tnf->directory_size / tnf->block_size;
     97 
     98 	/*
     99 	 * 1196886: Clients may supply file_size information obtained
    100 	 * by fstat() which is incorrect.  Check it now and revise
    101 	 * downwards if we have to.
    102 	 */
    103 	tmpsz = tnf->directory_size + tnf->block_count * tnf->block_size;
    104 	if (tmpsz != size) {
    105 		if (tmpsz > size)
    106 			/* missing data? */
    107 			return (TNF_ERR_BADTNF);
    108 		else {
    109 			tnf->file_size = tmpsz;
    110 			tnf->file_end = base + tmpsz;
    111 		}
    112 	}
    113 
    114 	/* Calculate block shift */
    115 	tmpsz = 1;
    116 	while (tmpsz != tnf->block_size) {
    117 		tmpsz <<= 1;
    118 		tnf->block_shift++;
    119 	}
    120 
    121 	/* Calculate block mask */
    122 	tnf->block_mask = ~(tnf->block_size - 1);
    123 
    124 	/* Generation shift */
    125 	p = _tnf_get_slot_named(tnf, fhdr, TNF_N_FILE_LOGICAL_SIZE);
    126 	/* LINTED pointer cast may result in improper alignment */
    127 	tnf->generation_shift	= _GET_UINT32(tnf, (tnf_uint32_t *)p);
    128 
    129 	/* Calculate the address mask */
    130 	/*
    131 	 * Following lint complaint is unwarranted, probably an
    132 	 * uninitialized variable in lint or something ...
    133 	 */
    134 	/* LINTED constant truncated by assignment */
    135 	tnf->address_mask = 0xffffffff;
    136 	tnf->address_mask <<= tnf->generation_shift;
    137 	tnf->address_mask = ~(tnf->address_mask);
    138 
    139 
    140 	/*
    141 	 * Examine first block header in data area
    142 	 */
    143 
    144 	tnf->data_start = tnf->file_start + tnf->directory_size;
    145 	/* LINTED pointer cast may result in improper alignment */
    146 	bhdr = (tnf_ref32_t *)tnf->data_start;
    147 
    148 	/* Block generation offset */
    149 	genp = _tnf_get_slot_named(tnf, bhdr, TNF_N_GENERATION);
    150 	tnf->block_generation_offset = genp - (caddr_t)bhdr;
    151 
    152 	/* Block bytes valid offset */
    153 	bvp = _tnf_get_slot_named(tnf, bhdr, TNF_N_BYTES_VALID);
    154 	tnf->block_bytes_valid_offset = bvp - (caddr_t)bhdr;
    155 
    156 	/*
    157 	 * Bootstrap taginfo system and cache important taginfo
    158 	 */
    159 
    160 	if ((err = _tnf_init_tags(tnf)) != TNF_ERR_NONE)
    161 		return (err);
    162 
    163 	tnf->file_header_info 	= _tnf_get_info(tnf, _tnf_get_tag(tnf, fhdr));
    164 	tnf->block_header_info 	= _tnf_get_info(tnf, _tnf_get_tag(tnf, bhdr));
    165 
    166 	/*
    167 	 * Return TNF handle and error status
    168 	 */
    169 
    170 	*tnfret = tnf;
    171 	return (TNF_ERR_NONE);
    172 }
    173 
    174 /*
    175  * Terminate a reader session
    176  */
    177 
    178 tnf_errcode_t
    179 tnf_reader_end(TNF *tnf)
    180 {
    181 	tnf_errcode_t	err;
    182 
    183 	/* Deallocate all taginfo */
    184 	if ((err = _tnf_fini_tags(tnf)) != TNF_ERR_NONE)
    185 		return (err);
    186 
    187 	/* Deallocate TNF */
    188 	free(tnf);
    189 
    190 	return (TNF_ERR_NONE);
    191 }
    192