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