xref: /illumos-gate/usr/src/lib/libtnf/reader.c (revision 7c478bd9)
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
tnf_reader_begin(caddr_t base,size_t size,TNF ** tnfret)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
tnf_reader_end(TNF * tnf)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