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