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