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 * 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 38 byteorder_destroy(struct byteorder_ctx *ctx) 39 { 40 if (ctx != NULL) 41 (void) free((char *)ctx); 42 } 43 44 void 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 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 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 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 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 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 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