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