1 /*
2 * Copyright 1996, 1998, 2002-2003 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
9 /*
10 * Copyright (c) 1983 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/vnode.h>
19 #include <locale.h>
20 #include <stdlib.h>
21 #include <sys/fs/ufs_inode.h>
22 #include <sys/fs/ufs_fsdir.h>
23 #include <sys/fs/ufs_acl.h>
24 #include <byteorder.h>
25
26 struct byteorder_ctx *
byteorder_create(void)27 byteorder_create(void)
28 {
29 struct byteorder_ctx *rc;
30
31 /* LINTED: assignment value is used */
32 if ((rc = (struct byteorder_ctx *)calloc(1, sizeof (*rc))) == NULL)
33 return (NULL);
34 return (rc);
35 }
36
37 void
byteorder_destroy(struct byteorder_ctx * ctx)38 byteorder_destroy(struct byteorder_ctx *ctx)
39 {
40 if (ctx != NULL)
41 (void) free((char *)ctx);
42 }
43
44 void
byteorder_banner(struct byteorder_ctx * ctx,FILE * filep)45 byteorder_banner(struct byteorder_ctx *ctx, FILE *filep)
46 {
47 if ((! ctx->initialized) || (filep == NULL))
48 return;
49
50 if (ctx->Bcvt)
51 (void) fprintf(filep, gettext("Note: doing byte swapping\n"));
52 }
53
54 /*
55 * Control string (cp) is a sequence of optional numeric repeat counts
56 * and format specifiers. s/w/h indicate a 16-bit quantity is to be
57 * byte-swapped, l indicates a 32-bit quantity. A repeat count is
58 * identical in effect to having the following format character appear
59 * N times (e.g., "3h" is equivalent to "hhh").
60 *
61 * The byte-swapping is performed in-place, in the buffer sp.
62 */
63 void
swabst(char * cp,uchar_t * sp)64 swabst(char *cp, uchar_t *sp)
65 {
66 int n = 0;
67 uchar_t c;
68
69 while (*cp) {
70 switch (*cp) {
71 case '0': case '1': case '2': case '3': case '4':
72 case '5': case '6': case '7': case '8': case '9':
73 n = (n * 10) + (*cp++ - '0');
74 continue;
75
76 case 's': case 'w': case 'h':
77 /* LINTED: type punning ok here */
78 c = sp[0]; sp[0] = sp[1]; sp[1] = c;
79 sp++;
80 break;
81
82 case 'l':
83 c = sp[0]; sp[0] = sp[3]; sp[3] = c;
84 c = sp[2]; sp[2] = sp[1]; sp[1] = c;
85 sp += 3;
86 }
87 /* Any other character, like 'b' counts as byte. */
88 sp++;
89 if (n <= 1) {
90 n = 0; cp++;
91 } else
92 n--;
93 }
94 }
95
96 uint32_t
swabl(uint32_t x)97 swabl(uint32_t x)
98 {
99 uint32_t l = x;
100
101 swabst("l", (uchar_t *)&l);
102 /* LINTED: type punning ok here */
103 return (l);
104 }
105
106 static int
checksum(struct byteorder_ctx * ctx,int * b,int size)107 checksum(struct byteorder_ctx *ctx, int *b, int size)
108 {
109 uint_t i, j;
110
111 if (! ctx->initialized)
112 return (-1);
113
114 /*
115 * We should only be called on to checksum u_spcl's, so make
116 * sure that's what we got.
117 */
118 if ((unsigned)size < tp_bsize)
119 return (-1);
120
121 j = tp_bsize / sizeof (int);
122 i = 0;
123 if (!ctx->Bcvt) {
124 do
125 i += (uint_t)*b++;
126 while (--j);
127 } else {
128 /*
129 * What happens if we want to read restore tapes
130 * for a 16bit int machine???
131 */
132 do
133 i += swabl(*b++);
134 while (--j);
135 }
136
137 return (i != CHECKSUM);
138 }
139
140 /*
141 * normspcl() checks that a spclrec is valid. it does byte/quad
142 * swapping if necessary, and checks the checksum. it does NOT convert
143 * from the old filesystem format; gethead() in tape.c does that.
144 *
145 * ctx is the context for this package
146 * sp is a pointer to a current-format spclrec, that may need to be
147 * byteswapped.
148 * cs is a pointer to the thing we want to checksum. if we're
149 * converting from the old filesystem format, it might be different
150 * from sp.
151 * css is the size of the thing we want to checksum.
152 * magic is the magic number we compare against.
153 */
154
155 int
normspcl(struct byteorder_ctx * ctx,struct s_spcl * sp,int * cs,int css,int magic)156 normspcl(struct byteorder_ctx *ctx, struct s_spcl *sp, int *cs,
157 int css, int magic)
158 {
159 u_offset_t sv;
160
161 if ((! ctx->initialized) && (sp->c_magic != magic)) {
162 if (swabl(sp->c_magic) != (uint32_t)magic)
163 return (-1);
164 ctx->Bcvt = 1;
165 }
166 ctx->initialized = 1;
167
168 if (checksum(ctx, cs, css))
169 return (-1);
170
171 /*
172 * Unless our caller is actively trying to break us, a
173 * successful checksum() means that *sp is at least as
174 * big as what we think it should be as far as byte
175 * swapping goes. Therefore, we don't need to do any
176 * more size checks here.
177 */
178
179 /* handle byte swapping */
180 if (ctx->Bcvt) {
181 /*
182 * byteswap
183 * c_type, c_date, c_ddate, c_volume, c_tapea, c_inumber,
184 * c_magic, c_checksum,
185 * all of c_dinode, and c_count.
186 */
187
188 swabst("8l4s31l", (uchar_t *)sp);
189
190 /*
191 * byteswap
192 * c_flags, c_firstrec, and c_spare.
193 */
194
195 swabst("34l", (uchar_t *)&(sp->c_flags));
196
197 /* byteswap the inodes if necessary. */
198
199 #ifndef lint /* lint won't shut up about sprintf below */
200 if (sp->c_flags & DR_INODEINFO) {
201 char buffy[BUFSIZ];
202 /* Can't overflow, max len is %d format (20)+`l'+\0 */
203 /* LINTED lint can't tell diff between %ld and %dl */
204 (void) sprintf(buffy, "%dl", TP_NINOS);
205 swabst(buffy, (uchar_t *)sp->c_data.s_inos);
206 }
207 #endif /* lint */
208
209 /* if no metadata, byteswap the level */
210
211 if (! (sp->c_flags & DR_HASMETA))
212 swabst("1l", (uchar_t *)&(sp->c_level));
213 }
214
215 /* handle quad swapping (note -- we no longer perform this check */
216 /* we now do quad swapping iff we're doing byte swapping.) */
217
218 /*
219 * the following code is being changed during the large file
220 * project. This code needed to be changed because ic_size
221 * is no longer a quad, it has been changed to ic_lsize, which is
222 * an offset_t, and the field "val" doesn't exist anymore.
223 */
224
225 /*
226 * This is the old code. (before large file project.)
227 *
228 * sv = sp->c_dinode.di_ic.ic_size.val;
229 *
230 * if (ctx->Bcvt) {
231 * long foo;
232 *
233 * foo = sv[1];
234 * sv[1] = sv[0];
235 * sv[0] = foo;
236 * }
237 */
238
239 /* swap the upper 32 bits of ic_lsize with the lower 32 bits */
240
241 if (ctx->Bcvt) {
242 sv = sp->c_dinode.di_ic.ic_lsize;
243 sv = (sv << 32) | (sv >> 32);
244 sp->c_dinode.di_ic.ic_lsize = sv;
245 }
246
247 if (sp->c_magic != magic)
248 return (-1);
249 return (0);
250 }
251
252 void
normdirect(ctx,d)253 normdirect(ctx, d)
254 struct byteorder_ctx *ctx;
255 struct direct *d;
256 {
257 assert(ctx->initialized);
258
259 if (ctx->Bcvt)
260 swabst("l2s", (uchar_t *)d);
261 }
262
263 void
normacls(struct byteorder_ctx * ctx,ufs_acl_t * acl,int n)264 normacls(struct byteorder_ctx *ctx, ufs_acl_t *acl, int n)
265 {
266 static int complained = 0;
267 int i;
268 uid32_t uid;
269
270 assert(ctx->initialized);
271
272 if (! ctx->Bcvt)
273 return;
274
275 for (i = 0; i < n; i++) {
276 swabst("1s", (uchar_t *)&(acl[i].acl_tag)); /* u_short */
277 swabst("1s", (uchar_t *)&(acl[i].acl_perm)); /* o_mode_t */
278
279 /* LINTED explicitly checking for truncation below */
280 uid = (uid32_t)(acl[i].acl_who);
281 if (!complained && ((uid_t)uid) != acl[i].acl_who) {
282 /*
283 * The problem is that acl_who is a uid_t,
284 * and we know that the on-tape version is
285 * definitely 32 bits. To avoid getting
286 * burned if/when uid_t becomes bigger
287 * than that, we need to do the explicit
288 * conversion and check.
289 */
290 (void) fprintf(stderr,
291 "Some ACL uids have been truncated\n");
292 complained = 1;
293 }
294 swabst("1l", (uchar_t *)&(uid)); /* uid32_t */
295 }
296 }
297