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 * File header operations
32 */
33
34 tnf_datum_t
tnf_get_file_header(TNF * tnf)35 tnf_get_file_header(TNF *tnf)
36 {
37 return (DATUM(tnf->file_header_info, (caddr_t)tnf->file_header));
38 }
39
40 /*
41 * Block access operations
42 */
43
44 unsigned
tnf_get_block_count(TNF * tnf)45 tnf_get_block_count(TNF *tnf)
46 {
47 return (tnf->block_count);
48 }
49
50 tnf_datum_t
tnf_get_block_absolute(TNF * tnf,unsigned index)51 tnf_get_block_absolute(TNF *tnf, unsigned index)
52 {
53 if (index >= tnf->block_count)
54 /*
55 * access to non-existent block:
56 * no error as per spec
57 */
58 return (TNF_DATUM_NULL);
59 else
60 /*
61 * XXX Require a single block header tag
62 */
63 /* LINTED pointer cast may result in improper alignment */
64 return (DATUM(tnf->block_header_info,
65 (caddr_t)_GET_INDEX_BLOCK(tnf, index)));
66 }
67
68 tnf_datum_t
tnf_get_block_relative(tnf_datum_t datum,int adjust)69 tnf_get_block_relative(tnf_datum_t datum, int adjust)
70 {
71 TNF *tnf;
72 tnf_ref32_t *bhdr;
73 unsigned index;
74
75 CHECK_DATUM(datum);
76
77 tnf = DATUM_TNF(datum);
78 bhdr = _GET_BLOCK(tnf, DATUM_VAL(datum));
79 index = _GET_BLOCK_INDEX(tnf, bhdr);
80
81 return (tnf_get_block_absolute(tnf, index + adjust));
82 }
83
84 int
tnf_is_block_header(tnf_datum_t datum)85 tnf_is_block_header(tnf_datum_t datum)
86 {
87 struct taginfo *info;
88 caddr_t val;
89 tnf_ref32_t *bhdr;
90
91 CHECK_DATUM(datum);
92
93 info = DATUM_INFO(datum);
94 val = DATUM_VAL(datum);
95 bhdr = _GET_BLOCK(info->tnf, val);
96
97 return (((caddr_t)bhdr == val) &&
98 (info == info->tnf->block_header_info));
99 }
100
101 tnf_datum_t
tnf_get_block_header(tnf_datum_t datum)102 tnf_get_block_header(tnf_datum_t datum)
103 {
104 TNF *tnf;
105 caddr_t val;
106
107 CHECK_DATUM(datum);
108
109 tnf = DATUM_TNF(datum);
110 val = DATUM_VAL(datum);
111 /*
112 * XXX Require a single block header tag
113 */
114 return (DATUM(tnf->block_header_info, (caddr_t)_GET_BLOCK(tnf, val)));
115 }
116
117 /*
118 * Sequential record access
119 */
120
121 tnf_datum_t
tnf_get_next_record(tnf_datum_t datum)122 tnf_get_next_record(tnf_datum_t datum)
123 {
124 TNF *tnf;
125 tnf_ref32_t *bhdr, *cell, ref32;
126 caddr_t val, nval, bval, blim;
127 size_t size, bytes;
128
129 CHECK_RECORD(datum);
130
131 tnf = DATUM_TNF(datum);
132 val = DATUM_VAL(datum);
133
134 size = tnf_get_size(datum);
135 nval = val + size;
136
137 /* Check file bounds */
138 if (nval < tnf->data_start)
139 return (tnf_get_block_absolute(tnf, 0));
140 else if (nval >= tnf->file_end)
141 return (TNF_DATUM_NULL);
142
143 /*
144 * OK, nval is in data area, start looking in block
145 */
146 bhdr = _GET_BLOCK(tnf, nval);
147 /* LINTED pointer cast may result in improper alignment */
148 bytes = _GET_BLOCK_BYTES_VALID(tnf, bhdr);
149 bval = (caddr_t)bhdr;
150 blim = bval + bytes;
151
152 /* sequentially examine valid cells in block from nval onwards */
153 while (nval < blim) {
154 /* LINTED pointer cast may result in improper alignment */
155 cell = (tnf_ref32_t *)nval;
156 ref32 = _GET_INT32(tnf, cell);
157
158 switch (TNF_REF32_TYPE(ref32)) {
159 case TNF_REF32_T_FWD: /* skip forwarding cells */
160 nval += sizeof (tnf_ref32_t);
161 break;
162 case TNF_REF32_T_RSVD: /* catch bogus cells */
163 _tnf_error(tnf, TNF_ERR_BADTNF);
164 return (TNF_DATUM_NULL);
165 default: /* PAIR or TAG: record header */
166 return (RECORD_DATUM(tnf, cell));
167 }
168 }
169
170 /*
171 * Couldn't find it: return next non-zero block header
172 */
173 while ((bval += tnf->block_size) < tnf->file_end)
174 /* Gotta check that there is a real bhdr here */
175 /* LINTED pointer cast may result in improper alignment */
176 if (*(tnf_ref32_t *)bval != TNF_NULL)
177 /* LINTED pointer cast may result in improper alignment */
178 return (RECORD_DATUM(tnf, (tnf_ref32_t *)bval));
179
180 /*
181 * default: we're off the end of the file
182 */
183 return (TNF_DATUM_NULL);
184 }
185