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