1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * diagcode library, Sun Private API (PSARC/2004/601) 29 * 30 * undocumented debugging interface: 31 * set environment variable _FM_DC_DEBUG for debug prints to stderr. 32 * set it to 1 for extended error messages only. 33 * set it to 2 to include success info too on interesting functions. 34 * set it to 3 to include success info on trivial functions too. 35 * note that this environment variable is only examined in fm_dc_opendict(). 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <ctype.h> 44 #include <alloca.h> 45 #include <errno.h> 46 47 #include <fm/diagcode.h> 48 49 /* private (opaque to callers) handle information */ 50 struct fm_dc_handle { 51 const char *dictname; 52 FILE *fp; 53 unsigned maxkey; 54 int version; 55 int debug; 56 /* name/value pairs from .dict header */ 57 struct fm_dc_prop { 58 struct fm_dc_prop *next; 59 const char *lhs; 60 const char *rhs; 61 } *props; 62 }; 63 64 /* 65 * parameters of the various sizes of diagcodes 66 * 67 * table must be in ascending order from smallest databits value to largest. 68 * when faced with more databits than the last entry, we know we have 69 * something that won't fit into a diagcode. 70 */ 71 static const struct info { 72 int databits; /* number of bits used to hold dictionary value */ 73 int numx; /* number of digits (also called X's) in code */ 74 int csumbits; /* number of bits used for checksum */ 75 int sizeval; /* value encoded into "size" field of code */ 76 unsigned long long offset; /* databits==0 stands for this value */ 77 } Info[] = { 78 /* diagcode is: dictname-XXXX-XX */ 79 { 21, 6, 5, 0, 0ULL }, 80 81 /* diagcode is: dictname-XXXX-XXXX-XX */ 82 { 38, 10, 8, 1, 2097152ULL }, 83 84 /* diagcode is: dictname-XXXX-XXXX-XXXX-XX */ 85 { 55, 14, 11, 2, 274880004096ULL }, 86 87 /* diagcode is: dictname-XXXX-XXXX-XXXX-XXXX-XX */ 88 { 72, 18, 14, 3, 36029071898968064ULL } 89 }; 90 #define MAXDATABITS 72 /* highest entry in table above */ 91 #define MAXCODELEN 25 /* big enough to hold the X's, dashes, and \0 */ 92 93 /* forward references for functions private to this file */ 94 typedef struct bitv bitv; 95 static const struct info *dictval2info(const bitv *bv); 96 static const struct info *numx2info(int numx); 97 static void sortkey(const char *key[]); 98 static const char *keymatch(const char *linebuf, const char *key[]); 99 static int buildcode(fm_dc_handle_t *dhp, const char *rhsp, 100 char *code, size_t maxcode, char *debugstr); 101 static bitv *code2dictval(fm_dc_handle_t *dhp, const char *code); 102 struct parsestate { 103 char *parseptr; /* next unparsed character in buffer */ 104 char *rhsp; /* rhs associated with last lhs (or NULL) */ 105 }; 106 static void startparse(struct parsestate *ps, char *ptr); 107 static char *nextlhs(struct parsestate *ps); 108 static char *nextrhs(struct parsestate *ps); 109 static bitv *bitv_alloc(void); 110 static void bitv_free(bitv *bv); 111 static void bitv_shift(bitv *bv, unsigned bits); 112 static void bitv_setlo(bitv *bv, unsigned bits, unsigned val); 113 static void bitv_shiftin(bitv *bv, unsigned bits, unsigned val); 114 static void bitv_shiftinv(bitv *bv, unsigned bits, const bitv *inbv); 115 static int bitv_bits(const bitv *bv); 116 static unsigned bitv_chunk(const bitv *bv, unsigned limbit, unsigned lobit); 117 static int bitv_mul(bitv *bv, unsigned long long val); 118 static int bitv_add(bitv *bv, unsigned long long val); 119 static int bitv_sub(bitv *bv, unsigned long long val); 120 static int bitv_ge(const bitv *bv, unsigned long long val); 121 static bitv *bitv_strparse(const char *s, int bits); 122 static int bitv_cmp(const bitv *bv1, const bitv *bv2); 123 static void crc(unsigned long *crcp, unsigned val); 124 125 #define DICTMAXLINE 10240 /* maximum expected dictionary line length */ 126 127 #define MAXDEBUGSTR 100 /* for debug messages */ 128 129 static const char Suffix[] = ".dict"; /* suffix on dictionary filename */ 130 static const char Defaultpath[] = "/usr/lib/fm/dict"; 131 static const char Debugenv[] = "_FM_DC_DEBUG"; /* debug environment var */ 132 133 /* properties we look for at top of dictionary */ 134 static const char Header[] = "FMDICT: "; 135 static const char Name[] = "name"; 136 static const char Version[] = "version"; 137 static const char Maxkey[] = "maxkey"; 138 139 /* the alphabet used to encode information in a diagcode (base32 digits) */ 140 static const char Alphabet[] = "0123456789ACDEFGHJKLMNPQRSTUVWXY"; 141 142 /* open a dictionary, return opaque handle */ 143 fm_dc_handle_t * 144 fm_dc_opendict(int version, const char *dirpath, const char *dictname) 145 { 146 int debug = 0; /* set by environment variable */ 147 char *debugstr = ""; /* error path debug prefix text */ 148 fm_dc_handle_t *dhp = NULL; 149 char *fname; /* full dict file name */ 150 char linebuf[DICTMAXLINE]; /* line read from dict */ 151 int line = 0; /* line number in dict */ 152 unsigned prop_version = 0; /* version property from dict */ 153 char *prop_name = ""; /* name property from dict */ 154 char *lhsp; /* prop left-hand-side */ 155 char *rhsp; /* prop right-hand-side */ 156 struct parsestate pstate; /* for startparse(), nextlhs(), etc */ 157 158 /* undocumented flag, given via environment variable */ 159 if ((rhsp = getenv(Debugenv)) != NULL) 160 debug = atoi(rhsp); 161 162 if (debug > 1) 163 (void) fprintf(stderr, 164 "fm_dc_opendict: ver %d path \"%s\" dict \"%s\": ", 165 version, (dirpath == NULL) ? "NULL" : dirpath, dictname); 166 else if (debug) 167 debugstr = "fm_dc_opendict: "; /* used in error paths */ 168 169 /* verify caller expects an API version we support */ 170 if (version < 0 || version > FM_DC_VERSION) { 171 if (debug) 172 (void) fprintf(stderr, "%sENOTSUP ver not in [0-%d]\n", 173 debugstr, FM_DC_VERSION); 174 errno = ENOTSUP; 175 return (NULL); 176 } 177 178 /* caller can pass in NULL for default dirpath */ 179 if (dirpath == NULL) 180 dirpath = Defaultpath; 181 182 /* 183 * allocate buffer for dirpath, slash, dictname, and suffix 184 * (sizeof (Suffix) includes the null). 185 */ 186 fname = alloca(strlen(dirpath) + 1 + 187 strlen(dictname) + sizeof (Suffix)); 188 189 /* 190 * allocate the handle. 191 * 192 * allocate the dictname copy kept in the handle. 193 * 194 * if any of these fail, send back ENOMEM. 195 */ 196 if ((dhp = malloc(sizeof (*dhp))) == NULL || 197 (dhp->dictname = strdup(dictname)) == NULL) { 198 if (dhp) 199 free(dhp); 200 if (debug) 201 (void) fprintf(stderr, "%sENOMEM\n", debugstr); 202 errno = ENOMEM; 203 return (NULL); 204 } 205 206 /* initialize the handle */ 207 (void) strcpy(fname, dirpath); 208 (void) strcat(fname, "/"); 209 (void) strcat(fname, dictname); 210 (void) strcat(fname, Suffix); 211 dhp->fp = NULL; 212 dhp->maxkey = 0; 213 dhp->version = version; 214 dhp->debug = debug; 215 dhp->props = NULL; 216 217 /* open the dictionary */ 218 if (debug > 1) 219 (void) fprintf(stderr, "\"%s\": ", fname); 220 if ((dhp->fp = fopen(fname, "r")) == NULL) { 221 int oerrno = errno; /* fopen() set errno to something */ 222 223 if (debug > 1) 224 perror("fopen"); 225 else if (debug) { 226 (void) fprintf(stderr, "%s%s: ", debugstr, fname); 227 errno = oerrno; 228 perror("fopen"); 229 } 230 fm_dc_closedict(dhp); 231 errno = oerrno; 232 return (NULL); 233 } 234 235 /* pull in the header line and parse it */ 236 while (fgets(linebuf, DICTMAXLINE, dhp->fp) != NULL) { 237 line++; 238 if (*linebuf == '\n' || *linebuf == '#') 239 continue; 240 241 /* first non-comment, non-blank line must be header */ 242 if (strncmp(linebuf, Header, sizeof (Header) - 1)) { 243 fm_dc_closedict(dhp); 244 if (debug) 245 (void) fprintf(stderr, 246 "%sEINVAL: line %d: header expected.\n", 247 debugstr, line); 248 errno = EINVAL; 249 return (NULL); 250 } 251 252 /* just wanted header line for now */ 253 break; 254 } 255 256 /* walk through name=value pairs in line after Header string */ 257 startparse(&pstate, &linebuf[sizeof (Header) - 1]); 258 while ((lhsp = nextlhs(&pstate)) != NULL) { 259 struct fm_dc_prop *propp; 260 261 if ((rhsp = nextrhs(&pstate)) == NULL) { 262 if (debug) 263 (void) fprintf(stderr, "%sEINVAL " 264 "%s prop has no value\n", debugstr, lhsp); 265 fm_dc_closedict(dhp); 266 errno = EINVAL; 267 return (NULL); 268 } 269 270 propp = malloc(sizeof (*propp)); 271 if (propp == NULL || 272 (propp->lhs = strdup(lhsp)) == NULL || 273 (propp->rhs = strdup(rhsp)) == NULL) { 274 if (debug) 275 (void) fprintf(stderr, "%sENOMEM\n", debugstr); 276 if (propp != NULL) { 277 if (propp->lhs != NULL) 278 free((void *) propp->lhs); 279 free((void *) propp); 280 } 281 fm_dc_closedict(dhp); 282 errno = ENOMEM; 283 return (NULL); 284 } 285 propp->next = dhp->props; 286 dhp->props = propp; 287 288 if (strcmp(lhsp, Name) == 0) 289 prop_name = rhsp; 290 else if (strcmp(lhsp, Version) == 0) 291 prop_version = strtoul(rhsp, NULL, 0); 292 else if (strcmp(lhsp, Maxkey) == 0) 293 dhp->maxkey = strtoul(rhsp, NULL, 0); 294 } 295 296 /* 297 * require version 1, expected dict name, and maxkey values 298 * (note we use "1" here and not FM_DC_VERSION because this code 299 * implements version 1, so the check below should not float to 300 * newer version numbers if the header file defines them.) 301 */ 302 if (prop_version != 1UL || strcmp(prop_name, dictname) || 303 dhp->maxkey == 0) { 304 fm_dc_closedict(dhp); 305 if (debug) 306 (void) fprintf(stderr, 307 "%sEINVAL ver %d name \"%s\" maxkey %d\n", 308 debugstr, prop_version, prop_name, dhp->maxkey); 309 errno = EINVAL; 310 return (NULL); 311 } 312 313 if (debug > 1) 314 (void) fprintf(stderr, "fm_dc_opendict: dhp 0x%p\n", 315 (void *)dhp); 316 return (dhp); 317 } 318 319 /* close a dictionary */ 320 void 321 fm_dc_closedict(fm_dc_handle_t *dhp) 322 { 323 struct fm_dc_prop *props; 324 struct fm_dc_prop *oprops; 325 326 if (dhp->debug > 1) 327 (void) fprintf(stderr, "fm_dc_closedict: dhp 0x%p\n", 328 (void *)dhp); 329 if (dhp->fp) 330 (void) fclose(dhp->fp); 331 332 free((void *) dhp->dictname); 333 334 props = dhp->props; 335 while (props) { 336 if (props->lhs != NULL) 337 free((void *) props->lhs); 338 if (props->rhs != NULL) 339 free((void *) props->rhs); 340 oprops = props; 341 props = props->next; 342 free((void *) oprops); 343 } 344 345 free(dhp); 346 } 347 348 /* return maximum length (in bytes) of diagcodes for a given dictionary */ 349 size_t 350 fm_dc_codelen(fm_dc_handle_t *dhp) 351 { 352 size_t len = strlen(dhp->dictname); 353 354 /* only one version so far, so dhp->version isn't checked */ 355 356 if (dhp->debug > 2) 357 (void) fprintf(stderr, "fm_dc_codelen: dhp 0x%p: %d\n", 358 (void *)dhp, (int)(len + MAXCODELEN)); 359 return (len + MAXCODELEN); 360 } 361 362 /* return number of strings in key for a given dictionary */ 363 int 364 fm_dc_maxkey(fm_dc_handle_t *dhp) 365 { 366 /* only one version so far, so dhp->version isn't checked */ 367 368 /* this interface counts the NULL entry */ 369 if (dhp->debug > 2) 370 (void) fprintf(stderr, "fm_dc_maxkey: dhp 0x%p: maxkey %d\n", 371 (void *)dhp, dhp->maxkey + 1); 372 return (dhp->maxkey + 1); 373 } 374 375 /* given a key, construct a diagcode */ 376 int 377 fm_dc_key2code(fm_dc_handle_t *dhp, 378 const char *key[], char *code, size_t maxcode) 379 { 380 char *debugstr = ""; /* error path debug prefix text */ 381 int line = 0; /* line number in dict */ 382 char linebuf[DICTMAXLINE]; /* line read from dict */ 383 const char *rhsp; /* right-hand-side of entry */ 384 385 /* only one version so far, so dhp->version isn't checked */ 386 387 if (dhp->debug > 1) { 388 int nel; 389 390 (void) fprintf(stderr, 391 "fm_dc_key2code: dhp 0x%p maxcode %lu ", (void *)dhp, 392 (ulong_t)maxcode); 393 for (nel = 0; key[nel]; nel++) 394 (void) fprintf(stderr, "\"%s\" ", key[nel]); 395 } else if (dhp->debug) 396 debugstr = "fm_dc_key2code: "; 397 398 /* sort the keys */ 399 sortkey(key); 400 401 rewind(dhp->fp); 402 403 while (fgets(linebuf, DICTMAXLINE, dhp->fp) != NULL) { 404 line++; 405 if (*linebuf == '\n' || *linebuf == '#') 406 continue; 407 408 /* first non-comment, non-blank line must be header */ 409 if (strncmp(linebuf, Header, sizeof (Header) - 1) == 0) 410 continue; 411 412 if ((rhsp = keymatch(linebuf, key)) != NULL) { 413 char ndebugstr[MAXDEBUGSTR]; 414 415 if (dhp->debug > 1) 416 (void) fprintf(stderr, "match line %d: ", line); 417 else { 418 (void) snprintf(ndebugstr, MAXDEBUGSTR, 419 "fm_dc_key2code: dictionary line %d", 420 line); 421 debugstr = ndebugstr; 422 } 423 424 return (buildcode(dhp, rhsp, code, maxcode, debugstr)); 425 } 426 } 427 428 /* no match */ 429 if (dhp->debug) 430 (void) fprintf(stderr, "%sENOMSG no match\n", debugstr); 431 errno = ENOMSG; 432 return (-1); 433 } 434 435 /* given a diagcode, return the key (array of strings) */ 436 int 437 fm_dc_code2key(fm_dc_handle_t *dhp, const char *code, 438 char *key[], int maxkey) 439 { 440 char *debugstr = ""; /* error path debug prefix text */ 441 int line = 0; 442 char linebuf[DICTMAXLINE]; 443 bitv *dictval; 444 445 /* only one version so far, so dhp->version isn't checked */ 446 447 if (dhp->debug > 1) 448 (void) fprintf(stderr, 449 "fm_dc_code2key: dhp 0x%p code \"%s\" maxkey %d: ", 450 (void *)dhp, code, maxkey); 451 else if (dhp->debug) 452 debugstr = "fm_dc_code2key: "; 453 454 /* convert code back to bit vector */ 455 if ((dictval = code2dictval(dhp, code)) == NULL) { 456 /* code2dictval() sets errno */ 457 if (dhp->debug) { 458 int oerrno = errno; 459 460 /* handle expected types without printing a number */ 461 if (errno == ENOMEM) 462 (void) fprintf(stderr, 463 "%sENOMEM code2dictval\n", 464 debugstr); 465 else if (errno == EINVAL) 466 (void) fprintf(stderr, 467 "%sEINVAL code2dictval\n", 468 debugstr); 469 else 470 (void) fprintf(stderr, 471 "%scode2dictval error %d\n", 472 debugstr, oerrno); 473 errno = oerrno; 474 } 475 return (-1); 476 } 477 478 rewind(dhp->fp); 479 480 while (fgets(linebuf, DICTMAXLINE, dhp->fp) != NULL) { 481 char *ptr; 482 bitv *thisval; 483 char *beginp; 484 char *endp; 485 int nel; 486 487 line++; 488 if (*linebuf == '\n' || *linebuf == '#') 489 continue; 490 491 /* first non-comment, non-blank line must be header */ 492 if (strncmp(linebuf, Header, sizeof (Header) - 1) == 0) 493 continue; 494 495 if ((ptr = strchr(linebuf, '=')) == NULL) 496 continue; /* ignore malformed entries */ 497 498 *ptr++ = '\0'; 499 500 /* pull in value from dictionary */ 501 if ((thisval = bitv_strparse(ptr, MAXDATABITS)) == NULL) { 502 /* bitv_strparse() sets errno */ 503 if (errno == ENOMEM) { 504 bitv_free(dictval); 505 if (dhp->debug) 506 (void) fprintf(stderr, 507 "%sENOMEM bitv_strparse\n", 508 debugstr); 509 errno = ENOMEM; 510 return (-1); 511 } 512 /* other than ENOMEM, trudge on... */ 513 continue; 514 } 515 516 if (bitv_cmp(thisval, dictval)) { 517 bitv_free(thisval); 518 continue; 519 } 520 521 /* if we got here, we found the match */ 522 bitv_free(thisval); 523 bitv_free(dictval); 524 beginp = linebuf; 525 nel = 0; 526 for (;;) { 527 while (*beginp && isspace(*beginp)) 528 beginp++; 529 if (*beginp == '\0') { 530 /* all done */ 531 key[nel] = NULL; 532 return (0); 533 } 534 if (nel >= maxkey - 1) { 535 if (dhp->debug) 536 (void) fprintf(stderr, 537 "%sENOMEM maxkey %d\n", 538 debugstr, maxkey); 539 errno = ENOMEM; 540 return (-1); 541 } 542 for (endp = beginp; *endp && !isspace(*endp); endp++) 543 ; 544 if (*endp) 545 *endp++ = '\0'; 546 if ((key[nel++] = strdup(beginp)) == NULL) { 547 if (dhp->debug) 548 (void) fprintf(stderr, 549 "%sENOMEM strdup\n", debugstr); 550 errno = ENOMEM; 551 return (-1); 552 } 553 beginp = endp; 554 } 555 } 556 557 bitv_free(dictval); 558 if (dhp->debug) 559 (void) fprintf(stderr, "%sENOMSG\n", debugstr); 560 errno = ENOMSG; 561 return (-1); 562 } 563 564 /* return the right-hand side of a names property from the dict header */ 565 const char * 566 fm_dc_getprop(fm_dc_handle_t *dhp, const char *name) 567 { 568 struct fm_dc_prop *props; 569 570 /* only one version so far, so dhp->version isn't checked */ 571 572 if (dhp->debug > 2) 573 (void) fprintf(stderr, "fm_dc_getprop: dhp 0x%p: \"%s\"", 574 (void *)dhp, name); 575 576 for (props = dhp->props; props; props = props->next) 577 if (strcmp(name, props->lhs) == 0) 578 break; 579 580 if (dhp->debug > 2) 581 (void) fprintf(stderr, "= \"%s\"\n", 582 (props == NULL) ? "NULL" : props->rhs); 583 584 return ((props == NULL) ? NULL : props->rhs); 585 } 586 587 /* find the appropriate diagcode format for a given dictval */ 588 static const struct info * 589 dictval2info(const bitv *bv) 590 { 591 int i; 592 593 for (i = 0; i < sizeof (Info) / sizeof (*Info) - 1; i++) 594 if (!bitv_ge(bv, Info[i + 1].offset)) 595 return (&Info[i]); 596 597 /* return largest format */ 598 return (&Info[sizeof (Info) / sizeof (*Info) - 1]); 599 } 600 601 /* lookup the diagcode parameters given the number of X's used */ 602 static const struct info * 603 numx2info(int numx) 604 { 605 int i; 606 607 for (i = 0; i < sizeof (Info) / sizeof (*Info); i++) 608 if (numx == Info[i].numx) 609 return (&Info[i]); 610 611 return (NULL); 612 } 613 614 /* for use with qsort() */ 615 static int 616 mycmp(const void *a, const void *b) 617 { 618 return (strcmp(*(char **)a, *(char **)b)); 619 } 620 621 /* 622 * sortkey -- make sure key[] array is lexically sorted and without repeats 623 */ 624 static void 625 sortkey(const char *key[]) 626 { 627 int nel; 628 int srci; /* source index when iterating through key[] */ 629 int dsti; /* dest index when storing elements in key[] */ 630 631 /* count the number of elements in key[] */ 632 for (nel = 0; key[nel]; nel++) 633 ; 634 635 if (nel < 2) 636 return; /* nothing to sort */ 637 638 qsort((void *)key, nel, sizeof (char *), mycmp); 639 640 /* go through array and remove repeats */ 641 dsti = 1; 642 for (srci = 1; srci < nel; srci++) 643 if (strcmp(key[srci], key[dsti - 1]) != 0) 644 key[dsti++] = key[srci]; 645 key[dsti] = NULL; 646 } 647 648 /* 649 * keymatch -- check for matching line from the dictionary 650 * 651 * assumes that the key[] array has already been lexically sorted. 652 * returns NULL if no match, otherwise pointer to first character of RHS. 653 */ 654 static const char * 655 keymatch(const char *linebuf, const char *key[]) 656 { 657 int keynum = 0; 658 const char *ptr; 659 660 while (linebuf) { 661 /* skip any initial whitespace in front of name */ 662 while (*linebuf && isspace(*linebuf)) 663 linebuf++; 664 665 ptr = key[keynum]; 666 667 if (ptr == NULL && *linebuf == '=') { 668 /* match */ 669 linebuf++; 670 while (*linebuf && isspace(*linebuf)) 671 linebuf++; 672 return (linebuf); 673 } else if (ptr == NULL) 674 return (NULL); /* dict had more strings for key */ 675 676 /* match the string */ 677 while (*linebuf) 678 if (*ptr == '\0') { 679 if (isspace(*linebuf) || *linebuf == '=') 680 break; /* match */ 681 else 682 return (NULL); /* dict string longer */ 683 } else if (*linebuf != *ptr) 684 return (NULL); /* string don't match */ 685 else { 686 linebuf++; 687 ptr++; 688 } 689 690 keynum++; 691 } 692 693 return (NULL); /* no match */ 694 } 695 696 /* 697 * buildcode -- given the val from the dictionary, create the diagcode 698 */ 699 static int 700 buildcode(fm_dc_handle_t *dhp, const char *rhsp, 701 char *code, size_t maxcode, char *debugstr) 702 { 703 char *codebegin = code; /* remember start of code buffer */ 704 const struct info *infop; /* Info[] table entry */ 705 unsigned long csum = 0; /* checksum (CRC) of diagcode */ 706 const char *ptr; 707 bitv *dictval; /* value from dictionary */ 708 bitv *allbits; /* assembled diagcode in binary */ 709 int bit; /* for looping through bits */ 710 int limbit; /* upper bit limit when looping */ 711 712 /* sanity check that buffer is large enough for diagcode */ 713 if (maxcode < fm_dc_codelen(dhp)) { 714 if (dhp->debug) 715 (void) fprintf(stderr, 716 "%sENOMEM maxcode %lu < codelen %lu\n", 717 debugstr, (ulong_t)maxcode, 718 (ulong_t)fm_dc_codelen(dhp)); 719 errno = ENOMEM; 720 return (-1); 721 } 722 723 /* handle dictname part of checksum */ 724 for (ptr = dhp->dictname; *ptr; ptr++) { 725 crc(&csum, (unsigned)*ptr); 726 *code++ = *ptr; 727 } 728 729 /* pull in value from dictionary */ 730 if ((dictval = bitv_strparse(rhsp, MAXDATABITS)) == NULL) { 731 /* bitv_strparse() sets errno */ 732 if (dhp->debug) { 733 int oerrno = errno; 734 735 /* handle expected types without printing a number */ 736 if (errno == ENOMEM) 737 (void) fprintf(stderr, 738 "%sENOMEM bitv_strparse\n", 739 debugstr); 740 else if (errno == ERANGE) 741 (void) fprintf(stderr, 742 "%sERANGE bitv_strparse\n", 743 debugstr); 744 else 745 (void) fprintf(stderr, 746 "%sbitv_strparse error %d\n", 747 debugstr, oerrno); 748 errno = oerrno; 749 } 750 return (-1); 751 } 752 753 /* determine which format of code we're using */ 754 infop = dictval2info(dictval); 755 756 /* subtract off the offset appropriate for format of code */ 757 if (dhp->debug > 3) 758 (void) fprintf(stderr, 759 "%ssubtract offset %llu\n", debugstr, infop->offset); 760 if (bitv_sub(dictval, infop->offset) < 0) { 761 /* 762 * this "cannot happen" since code format was chosen 763 * so that offset will be smaller than dictval, and 764 * dictval cannot be out of range since bitv_strparse() 765 * should have caught it. 766 */ 767 if (dhp->debug) 768 (void) fprintf(stderr, 769 "%sERANGE from bitv_sub\n", debugstr); 770 bitv_free(dictval); 771 errno = ERANGE; 772 return (-1); 773 } 774 775 /* assemble all the bits for the diagcode */ 776 if ((allbits = bitv_alloc()) == NULL) { 777 bitv_free(dictval); 778 if (dhp->debug) 779 (void) fprintf(stderr, 780 "%sENOMEM from bitv_alloc\n", debugstr); 781 errno = ENOMEM; 782 return (-1); 783 } 784 785 /* 786 * construct the full diagcode by shifting in information: 787 * - 2 bit code type, set to 01 788 * - 2 bit size field 789 * - the databits of the dictionary code itself 790 */ 791 792 bitv_shiftin(allbits, 2, 1); 793 bitv_shiftin(allbits, 2, infop->sizeval); 794 bitv_shiftinv(allbits, infop->databits, dictval); 795 796 /* insert zeros for checksum */ 797 bitv_shiftin(allbits, infop->csumbits, 0); 798 799 /* compute checksum */ 800 limbit = infop->numx * 5; 801 for (bit = 0; bit < infop->numx; bit++) { 802 crc(&csum, bitv_chunk(allbits, limbit, limbit - 5)); 803 limbit -= 5; 804 } 805 806 /* insert the computed checksum */ 807 bitv_setlo(allbits, infop->csumbits, (unsigned)csum); 808 809 /* encode binary values according to alphabet */ 810 limbit = infop->numx * 5; 811 for (bit = 0; bit < infop->numx; bit++) { 812 if (bit % 4 == 0) 813 *code++ = '-'; 814 *code++ = Alphabet[bitv_chunk(allbits, limbit, limbit - 5)]; 815 limbit -= 5; 816 } 817 818 *code = '\0'; 819 bitv_free(allbits); 820 bitv_free(dictval); 821 822 if (dhp->debug > 1) 823 (void) fprintf(stderr, "code \"%s\"\n", codebegin); 824 return (0); 825 } 826 827 /* 828 * code2dictval -- convert a diagcode back to a bit vector 829 */ 830 static bitv * 831 code2dictval(fm_dc_handle_t *dhp, const char *code) 832 { 833 const struct info *infop; 834 int len = strlen(dhp->dictname); 835 bitv *allbits; 836 bitv *dictval; 837 int numx; /* number of X's we count */ 838 unsigned long ocsum; /* original checksum in code */ 839 unsigned long csum; /* our computed checksum */ 840 int bit; /* for looping through bits */ 841 int limbit; /* upper bit limit when looping */ 842 const char *ptr; 843 844 /* check dictname part of code */ 845 if (strncasecmp(code, dhp->dictname, len) || 846 code[len] != '-') { 847 errno = EINVAL; 848 return (NULL); 849 } 850 851 /* convert code back to a bit vector */ 852 if ((allbits = bitv_alloc()) == NULL) { 853 errno = ENOMEM; 854 return (NULL); 855 } 856 857 /* we verified it began with dictname and a dash, so skip it */ 858 code = &code[len + 1]; 859 numx = 0; 860 /* be forgiving about misplaced dashes */ 861 for (; *code; code++) 862 if (*code == '-') 863 continue; 864 else { 865 unsigned val; 866 867 for (val = 0; Alphabet[val]; val++) 868 if (*code == Alphabet[val]) 869 break; 870 if (Alphabet[val] == '\0') { 871 bitv_free(allbits); 872 errno = EINVAL; 873 return (NULL); 874 } 875 bitv_shiftin(allbits, 5, val); 876 numx++; 877 } 878 879 if ((infop = numx2info(numx)) == NULL) { 880 bitv_free(allbits); 881 errno = EINVAL; 882 return (NULL); 883 } 884 885 /* now pull out the csum */ 886 ocsum = bitv_chunk(allbits, infop->csumbits, 0); 887 888 /* set the csum bits to zero */ 889 bitv_setlo(allbits, infop->csumbits, 0); 890 891 /* calculate the checksum and see if it matches */ 892 csum = 0; 893 for (ptr = dhp->dictname; *ptr; ptr++) 894 crc(&csum, (unsigned)*ptr); 895 limbit = numx * 5; 896 for (bit = 0; bit < numx; bit++) { 897 crc(&csum, bitv_chunk(allbits, limbit, limbit - 5)); 898 limbit -= 5; 899 } 900 csum &= (1 << infop->csumbits) - 1; 901 902 if (csum != ocsum) { 903 bitv_free(allbits); 904 errno = EINVAL; 905 return (NULL); 906 } 907 908 /* code looks okay, just return dictval portion */ 909 if ((dictval = bitv_alloc()) == NULL) { 910 bitv_free(allbits); 911 errno = ENOMEM; 912 return (NULL); 913 } 914 limbit = infop->csumbits + infop->databits; 915 while (limbit > infop->csumbits) { 916 bitv_shiftin(dictval, 1, 917 bitv_chunk(allbits, limbit, limbit - 1)); 918 limbit--; 919 } 920 bitv_free(allbits); 921 922 /* add in the offset appropriate for the length of code being used */ 923 if (bitv_add(dictval, infop->offset) < 0) { 924 /* 925 * overflow "cannot happen" since we've pulled in 926 * a given number of bits from the code and the offset 927 * is designed not to overflow... 928 */ 929 bitv_free(dictval); 930 errno = ERANGE; 931 return (NULL); 932 } 933 934 return (dictval); 935 } 936 937 938 /* 939 * private routines to parse a line into name/value pairs... 940 * 941 */ 942 943 /* 944 * startparse -- record starting of buffer containing name=value pairs 945 */ 946 static void 947 startparse(struct parsestate *ps, char *ptr) 948 { 949 ps->parseptr = ptr; 950 } 951 952 /* 953 * nextlhs -- return next left-hand-side of name=value pair, or NULL 954 * 955 * whitespace around the '=' is allowed for, but not required. the 956 * lhs is a simple string that does not contain any whitespace or an 957 * embedded equals sign. no escaped characters, quotes, etc. are 958 * honored here. 959 * 960 * this routine also parses the rhs and saves a pointer to it 961 * in Rhsp so that nextrhs() can return it. if nextrhs() never 962 * gets called, we continue looking for the next lhs *after* any 963 * rhs that was there. 964 */ 965 static char * 966 nextlhs(struct parsestate *ps) 967 { 968 char *lhsp; 969 char *copyto; 970 int equals = 0; 971 int quote = 0; 972 int backslash = 0; 973 974 /* skip whitespace */ 975 while (*ps->parseptr && isspace(*ps->parseptr)) 976 ps->parseptr++; 977 978 /* anything left? */ 979 if (*ps->parseptr == '\0') 980 return (NULL); 981 982 /* remember start of lhs, assume no rhs until we see '=' */ 983 lhsp = ps->parseptr; 984 985 /* find end of token, no escaped chars, quotes, etc. on lhs */ 986 while (*ps->parseptr && !isspace(*ps->parseptr)) 987 if (*ps->parseptr == '=') { 988 equals = 1; 989 break; 990 } else 991 ps->parseptr++; 992 993 /* null terminate the token, possibly nuking the '=' itself */ 994 *ps->parseptr++ = '\0'; 995 996 /* if we haven't seen an '=', see if it happens after whitespace */ 997 if (!equals) { 998 while (*ps->parseptr && isspace(*ps->parseptr)) 999 ps->parseptr++; 1000 if (*ps->parseptr == '=') { 1001 equals = 1; 1002 ps->parseptr++; 1003 } 1004 } 1005 1006 /* skip whitespace */ 1007 while (*ps->parseptr && isspace(*ps->parseptr)) 1008 ps->parseptr++; 1009 1010 /* isolate the rhs if it is there */ 1011 if (!equals || *ps->parseptr == '\0') { 1012 ps->rhsp = NULL; 1013 return (lhsp); 1014 } 1015 1016 if (*ps->parseptr == '"') { 1017 quote = 1; 1018 ps->parseptr++; 1019 } 1020 1021 /* remember the beginning of the rhs */ 1022 ps->rhsp = copyto = ps->parseptr; 1023 1024 /* now scan to the end of the rhs */ 1025 while (*ps->parseptr) { 1026 if (backslash) { 1027 switch (*ps->parseptr) { 1028 case 't': 1029 *copyto++ = '\t'; 1030 break; 1031 1032 case 'r': 1033 *copyto++ = '\r'; 1034 break; 1035 1036 case 'n': 1037 *copyto++ = '\n'; 1038 break; 1039 1040 case 'f': 1041 *copyto++ = '\f'; 1042 break; 1043 1044 default: 1045 *copyto++ = *ps->parseptr; 1046 break; 1047 } 1048 1049 backslash = 0; 1050 } else if (*ps->parseptr == '\\') 1051 backslash = 1; 1052 else if (quote) { 1053 if (*ps->parseptr == '"') { 1054 ps->parseptr++; 1055 break; /* end of quoted string */ 1056 } else 1057 *copyto++ = *ps->parseptr; 1058 } else if (!isspace(*ps->parseptr)) 1059 *copyto++ = *ps->parseptr; 1060 else { 1061 ps->parseptr++; 1062 break; /* rhs terminated by whitespace */ 1063 } 1064 1065 ps->parseptr++; 1066 } 1067 *copyto = '\0'; 1068 1069 return (lhsp); 1070 } 1071 1072 /* 1073 * nextrhs -- return right-hand-side of name=value pair, or NULL 1074 * 1075 * this routine can only be used after a lhs has been found with 1076 * nextlhs(). the rhs consists of a string with no whitespace in it, 1077 * unless the whitespace is escaped with a backslash. surrounding 1078 * a string with double quotes is also supported here, as are the 1079 * common C escape sequences like \t and \n. 1080 * 1081 * nextlhs() actually does all the hard work. we just return any 1082 * rhs that was found by that routine. 1083 */ 1084 static char * 1085 nextrhs(struct parsestate *ps) 1086 { 1087 return (ps->rhsp); 1088 } 1089 1090 1091 /* 1092 * private routines to manipulate bit vectors (i.e. large integers) 1093 * 1094 * if these bit vector routines are ever supposed to be more 1095 * general, the desired length should be passed in to bitv_alloc() 1096 * instead of defining a maximum here. but knowing the max ahead 1097 * of time allows for simpler code and we know the max that will 1098 * fit into a diagcode. on the minimum side, the below define 1099 * must be at least sizeof (unsigned). 1100 */ 1101 #define BITV_MAX_BYTES 15 1102 1103 /* data structure used to hold a bit vector */ 1104 struct bitv { 1105 unsigned char v[BITV_MAX_BYTES]; 1106 }; 1107 1108 /* allocate a new, zeroed out bit vector */ 1109 static bitv * 1110 bitv_alloc(void) 1111 { 1112 int i; 1113 struct bitv *bv = malloc(sizeof (*bv)); 1114 1115 if (bv) 1116 for (i = 0; i < BITV_MAX_BYTES; i++) 1117 bv->v[i] = 0; 1118 1119 return (bv); 1120 } 1121 1122 /* free a bit vector that was allocated with bitv_alloc() */ 1123 static void 1124 bitv_free(bitv *bv) 1125 { 1126 free(bv); 1127 } 1128 1129 /* shift left a bit vector by a given number of bits. fill with zeros. */ 1130 static void 1131 bitv_shift(bitv *bv, unsigned bits) 1132 { 1133 while (bits > 0) { 1134 unsigned iterbits = bits; 1135 int i; 1136 1137 /* how many bits this iteration? 8 max. */ 1138 if (iterbits > 8) 1139 iterbits = 8; 1140 1141 for (i = BITV_MAX_BYTES - 1; i > 0; i--) { 1142 bv->v[i] <<= iterbits; 1143 bv->v[i] |= bv->v[i - 1] >> (8 - iterbits); 1144 } 1145 bv->v[0] <<= iterbits; 1146 1147 bits -= iterbits; 1148 } 1149 } 1150 1151 /* force a given number of bits to a specific value */ 1152 static void 1153 bitv_setlo(bitv *bv, unsigned bits, unsigned val) 1154 { 1155 int i = 0; 1156 1157 /* assumption: bits * 8 <= sizeof (val) */ 1158 1159 while (bits > 0) { 1160 unsigned iterbits = bits; 1161 unsigned mask; 1162 1163 if (iterbits > 8) 1164 iterbits = 8; 1165 1166 mask = (1 << iterbits) - 1; 1167 1168 bv->v[i] &= ~mask; 1169 bv->v[i] |= val & mask; 1170 1171 val >>= iterbits; 1172 bits -= iterbits; 1173 /* 1174 * the following can't go off end of bv->v[] since 1175 * BITV_MAX_BYTES is assumed to be at least sizeof 1176 * unsigned and val can't be more than sizeof unsigned 1177 * bytes long. 1178 */ 1179 i++; 1180 } 1181 } 1182 1183 /* given a value and number of bits, shift it in from the right */ 1184 static void 1185 bitv_shiftin(bitv *bv, unsigned bits, unsigned val) 1186 { 1187 bitv_shift(bv, bits); 1188 bitv_setlo(bv, bits, val); 1189 } 1190 1191 /* given a bit vector and a number of bits, shift it in from the right */ 1192 static void 1193 bitv_shiftinv(bitv *bv, unsigned bits, const bitv *inbv) 1194 { 1195 int byteindex = bits / 8; 1196 int iterbits = bits % 8; 1197 1198 /* first handle partial byte shift in */ 1199 bitv_shiftin(bv, iterbits, inbv->v[byteindex--]); 1200 1201 /* now handle any remaining full byte shift ins */ 1202 while (byteindex >= 0) 1203 bitv_shiftin(bv, 8, inbv->v[byteindex--]); 1204 } 1205 1206 /* return the number of bits required to hold the current bit vector's value */ 1207 static int 1208 bitv_bits(const bitv *bv) 1209 { 1210 int i; 1211 1212 for (i = BITV_MAX_BYTES - 1; i >= 0; i--) 1213 if (bv->v[i]) { 1214 int bit; 1215 1216 for (bit = 7; bit >= 0; bit--) 1217 if ((bv->v[i] >> bit) & 1) 1218 return (i * 8 + bit + 1); 1219 1220 /* this can't happen, so do *something* */ 1221 return ((i + 1) * 8); 1222 } 1223 1224 return (0); 1225 } 1226 1227 /* extract chunks of bits from bit vector */ 1228 static unsigned 1229 bitv_chunk(const bitv *bv, unsigned limbit, unsigned lobit) 1230 { 1231 unsigned retval = 0; 1232 int bit; 1233 1234 /* 1235 * entry assumptions: 1236 * limbit > lobit 1237 * limbit - lobit <= sizeof (unsigned) * 8 1238 */ 1239 1240 for (bit = limbit - 1; bit >= 0 && bit >= lobit; bit--) { 1241 retval <<= 1; 1242 retval |= (bv->v[bit / 8] >> (bit % 8)) & 1; 1243 } 1244 1245 return (retval); 1246 } 1247 1248 /* 1249 * multiply by a given value 1250 * 1251 * on overflow, bit vector will hold least significant BITV_MAX_BYTES, 1252 * return value will be -1, and errno will be ERANGE. otherwise 1253 * return is zero and bit vector holds the product. 1254 */ 1255 static int 1256 bitv_mul(bitv *bv, unsigned long long val) 1257 { 1258 unsigned short result; 1259 unsigned char prod[BITV_MAX_BYTES]; 1260 unsigned k = 0; 1261 int valbyte; 1262 int bvbyte; 1263 int i; 1264 1265 /* start with a zeroed out bit vector to hold result */ 1266 for (i = 0; i < BITV_MAX_BYTES; i++) 1267 prod[i] = 0; 1268 1269 /* from most-significant byte of val to least... */ 1270 for (valbyte = 0; valbyte < sizeof (val); valbyte++) 1271 /* from most significant byte of bv to least */ 1272 for (bvbyte = 0; bvbyte < BITV_MAX_BYTES; bvbyte++) { 1273 result = ((val >> (valbyte * 8)) & 0xff) * 1274 bv->v[bvbyte] + k; 1275 1276 if (valbyte + bvbyte >= BITV_MAX_BYTES) { 1277 /* 1278 * we're not storing digits past 1279 * BITV_MAX_BYTES, so if they aren't 1280 * zeros, then signal an overflow. 1281 */ 1282 if (result & 0xff) { 1283 errno = ERANGE; 1284 return (-1); 1285 } 1286 } else 1287 prod[valbyte + bvbyte] += result & 0xff; 1288 1289 /* "carry the 1..." */ 1290 k = result >> 8; 1291 } 1292 1293 /* store result in bv */ 1294 for (i = 0; i < BITV_MAX_BYTES; i++) 1295 bv->v[i] = prod[i]; 1296 1297 return (0); 1298 } 1299 1300 /* 1301 * add in a given value 1302 * 1303 * on overflow, bit vector will hold least significant BITV_MAX_BYTES, 1304 * return value will be -1, and errno will be ERANGE. otherwise 1305 * return is zero and bit vector holds the sum. 1306 */ 1307 static int 1308 bitv_add(bitv *bv, unsigned long long val) 1309 { 1310 int cf = 0; /* carry flag */ 1311 unsigned short result; 1312 int i; 1313 1314 for (i = 0; i < BITV_MAX_BYTES; i++) { 1315 if (i < sizeof (val)) 1316 result = cf + bv->v[i] + ((val >> (i * 8)) & 0xff); 1317 else 1318 result = cf + bv->v[i]; 1319 1320 cf = (result >> 8) & 1; 1321 bv->v[i] = result & 0xff; 1322 } 1323 1324 if (cf) { 1325 errno = ERANGE; 1326 return (-1); 1327 } 1328 return (0); 1329 } 1330 1331 /* 1332 * subtract out a given value 1333 * 1334 * on underflow, bit vector will hold least significant BITV_MAX_BYTES, 1335 * return value will be -1, and errno will be ERANGE. otherwise 1336 * return is zero and bit vector holds the difference. 1337 */ 1338 static int 1339 bitv_sub(bitv *bv, unsigned long long val) 1340 { 1341 int bf = 0; /* borrow flag */ 1342 unsigned short minuend; 1343 unsigned short subtrahend; 1344 int i; 1345 1346 for (i = 0; i < BITV_MAX_BYTES; i++) { 1347 minuend = bv->v[i]; 1348 if (i < sizeof (val)) 1349 subtrahend = bf + ((val >> (i * 8)) & 0xff); 1350 else 1351 subtrahend = bf; 1352 if (subtrahend > minuend) { 1353 bf = 1; 1354 minuend += 1 << 8; 1355 } else 1356 bf = 0; 1357 1358 bv->v[i] = minuend - subtrahend; 1359 } 1360 1361 if (bf) { 1362 errno = ERANGE; 1363 return (-1); 1364 } 1365 return (0); 1366 } 1367 1368 /* 1369 * see if bv is greater than or equal to a given value 1370 */ 1371 static int 1372 bitv_ge(const bitv *bv, unsigned long long val) 1373 { 1374 int bf = 0; /* borrow flag */ 1375 unsigned short minuend; 1376 unsigned short subtrahend; 1377 int i; 1378 1379 for (i = 0; i < BITV_MAX_BYTES; i++) { 1380 minuend = bv->v[i]; 1381 if (i < sizeof (val)) 1382 subtrahend = bf + ((val >> (i * 8)) & 0xff); 1383 else 1384 subtrahend = bf; 1385 if (subtrahend > minuend) 1386 bf = 1; 1387 else 1388 bf = 0; 1389 } 1390 1391 return (!bf); 1392 } 1393 1394 /* parse a string into bit vector, honor leading 0/0x for octal/hex */ 1395 static bitv * 1396 bitv_strparse(const char *s, int bits) 1397 { 1398 unsigned long long base = 10; 1399 unsigned long long val; 1400 bitv *bv = bitv_alloc(); 1401 1402 if (bv == NULL) { 1403 errno = ENOMEM; 1404 return (NULL); 1405 } 1406 1407 if (*s == '0') { 1408 s++; 1409 if (*s == 'x') { 1410 s++; 1411 base = 16; 1412 } else 1413 base = 8; 1414 } 1415 1416 while (isxdigit(*s)) { 1417 /* isxdigit() let's in too much, depending on base */ 1418 if (base == 8 && (*s < '0' || *s > '7')) 1419 break; 1420 else if (base == 10 && !isdigit(*s)) 1421 break; 1422 1423 /* convert the digit to binary */ 1424 if (isdigit(*s)) 1425 val = *s - '0'; 1426 else 1427 val = tolower(*s) - 'a' + 10; 1428 1429 /* 1430 * multiply our big integer by base, 1431 * add in the most recent digit, 1432 * and check for overflow 1433 */ 1434 if (bitv_mul(bv, base) < 0 || 1435 bitv_add(bv, val) < 0 || 1436 bitv_bits(bv) > bits) { 1437 bitv_free(bv); 1438 errno = ERANGE; 1439 return (NULL); 1440 } 1441 1442 s++; 1443 } 1444 1445 return (bv); 1446 } 1447 1448 /* return 0 if two bit vectors represent the same number */ 1449 static int 1450 bitv_cmp(const bitv *bv1, const bitv *bv2) 1451 { 1452 int i; 1453 1454 for (i = BITV_MAX_BYTES - 1; i >= 0; i--) 1455 if (bv1->v[i] < bv2->v[i]) 1456 return (-1); 1457 else if (bv1->v[i] > bv2->v[i]) 1458 return (1); 1459 return (0); 1460 } 1461 1462 1463 /* CRC code... */ 1464 static unsigned crctab[256] = { 1465 0x00000000, 1466 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 1467 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 1468 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 1469 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 1470 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 1471 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 1472 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 1473 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 1474 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 1475 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE, 1476 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, 1477 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 1478 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, 1479 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 1480 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 1481 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 1482 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 1483 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 1484 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 1485 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 1486 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 1487 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 1488 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 1489 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 1490 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 1491 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 1492 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 1493 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 1494 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629, 1495 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 1496 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 1497 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 1498 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 1499 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 1500 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 1501 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 1502 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 1503 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 1504 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 1505 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 1506 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 1507 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087, 1508 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 1509 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 1510 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 1511 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 1512 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 1513 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09, 1514 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 1515 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 1516 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 1517 }; 1518 1519 static void 1520 crc(unsigned long *crcp, unsigned val) 1521 { 1522 *crcp = (*crcp<<8) ^ crctab[(unsigned char)((*crcp>>24)^val)]; 1523 } 1524