/* * 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); }