home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / crc-check / crc.c < prev    next >
C/C++ Source or Header  |  1989-03-07  |  10KB  |  399 lines

  1. /* updcrc(3), crc(1) - calculate crc polynomials
  2.  *
  3.  * Calculate, intelligently, the CRC of a dataset incrementally given a 
  4.  * buffer full at a time.
  5.  * 
  6.  * Usage:
  7.  *     newcrc = updcrc( oldcrc, bufadr, buflen )
  8.  *         unsigned int oldcrc, buflen;
  9.  *         char *bufadr;
  10.  *
  11.  * Compiling with -DTEST creates a program to print the CRC of stdin to stdout.
  12.  * Compile with -DMAKETAB to print values for crctab to stdout.  If you change
  13.  *    the CRC polynomial parameters, be sure to do this and change
  14.  *    crctab's initial value.
  15.  *
  16.  * Notes:
  17.  *  Regards the data stream as an integer whose MSB is the MSB of the first
  18.  *  byte recieved.  This number is 'divided' (using xor instead of subtraction)
  19.  *  by the crc-polynomial P.
  20.  *  XMODEM does things a little differently, essentially treating the LSB of
  21.  * the first data byte as the MSB of the integer. Define SWAPPED to make
  22.  * things behave in this manner.
  23.  *
  24.  * Author:    Mark G. Mendel, 7/86
  25.  *        UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm
  26.  */
  27.  
  28. #define TEST
  29.  
  30. /* The CRC polynomial.
  31.  * These 4 values define the crc-polynomial.
  32.  * If you change them, you must change crctab[]'s initial value to what is
  33.  * printed by initcrctab() [see 'compile with -DMAKETAB' above].
  34.  */
  35.  
  36. /* Value used by:                CITT    XMODEM    ARC      */
  37. #define    P     0xA001     /* the poly:    0x1021    0x1021    A001    */
  38. #define INIT_CRC 0L     /* init value:    -1    0    0    */
  39. #define SWAPPED         /* bit order:    undef    defined    defined */
  40. #define W    16     /* bits in CRC:16    16    16    */
  41.  
  42. /* data type that holds a W-bit unsigned integer */
  43. #if W <= 16
  44. #  define WTYPE    unsigned short
  45. #else
  46. #  define WTYPE   unsigned long
  47. #endif
  48.  
  49. /* the number of bits per char: don't change it. */
  50. #define B    8
  51.  
  52. static WTYPE crctab[1<<B] = /* as calculated by initcrctab() */ {
  53.    0x0,  0xc0c1,  0xc181,  0x140,  0xc301,  0x3c0,  0x280,  0xc241,
  54.    0xc601,  0x6c0,  0x780,  0xc741,  0x500,  0xc5c1,  0xc481,  0x440,
  55.    0xcc01,  0xcc0,  0xd80,  0xcd41,  0xf00,  0xcfc1,  0xce81,  0xe40,
  56.    0xa00,  0xcac1,  0xcb81,  0xb40,  0xc901,  0x9c0,  0x880,  0xc841,
  57.    0xd801,  0x18c0,  0x1980,  0xd941,  0x1b00,  0xdbc1,  0xda81,  0x1a40,
  58.    0x1e00,  0xdec1,  0xdf81,  0x1f40,  0xdd01,  0x1dc0,  0x1c80,  0xdc41,
  59.    0x1400,  0xd4c1,  0xd581,  0x1540,  0xd701,  0x17c0,  0x1680,  0xd641,
  60.    0xd201,  0x12c0,  0x1380,  0xd341,  0x1100,  0xd1c1,  0xd081,  0x1040,
  61.    0xf001,  0x30c0,  0x3180,  0xf141,  0x3300,  0xf3c1,  0xf281,  0x3240,
  62.    0x3600,  0xf6c1,  0xf781,  0x3740,  0xf501,  0x35c0,  0x3480,  0xf441,
  63.    0x3c00,  0xfcc1,  0xfd81,  0x3d40,  0xff01,  0x3fc0,  0x3e80,  0xfe41,
  64.    0xfa01,  0x3ac0,  0x3b80,  0xfb41,  0x3900,  0xf9c1,  0xf881,  0x3840,
  65.    0x2800,  0xe8c1,  0xe981,  0x2940,  0xeb01,  0x2bc0,  0x2a80,  0xea41,
  66.    0xee01,  0x2ec0,  0x2f80,  0xef41,  0x2d00,  0xedc1,  0xec81,  0x2c40,
  67.    0xe401,  0x24c0,  0x2580,  0xe541,  0x2700,  0xe7c1,  0xe681,  0x2640,
  68.    0x2200,  0xe2c1,  0xe381,  0x2340,  0xe101,  0x21c0,  0x2080,  0xe041,
  69.    0xa001,  0x60c0,  0x6180,  0xa141,  0x6300,  0xa3c1,  0xa281,  0x6240,
  70.    0x6600,  0xa6c1,  0xa781,  0x6740,  0xa501,  0x65c0,  0x6480,  0xa441,
  71.    0x6c00,  0xacc1,  0xad81,  0x6d40,  0xaf01,  0x6fc0,  0x6e80,  0xae41,
  72.    0xaa01,  0x6ac0,  0x6b80,  0xab41,  0x6900,  0xa9c1,  0xa881,  0x6840,
  73.    0x7800,  0xb8c1,  0xb981,  0x7940,  0xbb01,  0x7bc0,  0x7a80,  0xba41,
  74.    0xbe01,  0x7ec0,  0x7f80,  0xbf41,  0x7d00,  0xbdc1,  0xbc81,  0x7c40,
  75.    0xb401,  0x74c0,  0x7580,  0xb541,  0x7700,  0xb7c1,  0xb681,  0x7640,
  76.    0x7200,  0xb2c1,  0xb381,  0x7340,  0xb101,  0x71c0,  0x7080,  0xb041,
  77.    0x5000,  0x90c1,  0x9181,  0x5140,  0x9301,  0x53c0,  0x5280,  0x9241,
  78.    0x9601,  0x56c0,  0x5780,  0x9741,  0x5500,  0x95c1,  0x9481,  0x5440,
  79.    0x9c01,  0x5cc0,  0x5d80,  0x9d41,  0x5f00,  0x9fc1,  0x9e81,  0x5e40,
  80.    0x5a00,  0x9ac1,  0x9b81,  0x5b40,  0x9901,  0x59c0,  0x5880,  0x9841,
  81.    0x8801,  0x48c0,  0x4980,  0x8941,  0x4b00,  0x8bc1,  0x8a81,  0x4a40,
  82.    0x4e00,  0x8ec1,  0x8f81,  0x4f40,  0x8d01,  0x4dc0,  0x4c80,  0x8c41,
  83.    0x4400,  0x84c1,  0x8581,  0x4540,  0x8701,  0x47c0,  0x4680,  0x8641,
  84.    0x8201,  0x42c0,  0x4380,  0x8341,  0x4100,  0x81c1,  0x8081,  0x4040,
  85. };
  86.  
  87.  
  88. void perror();
  89. char *strcpy(); 
  90. void exit();
  91.  
  92. WTYPE
  93. updcrc( icrc, icp, icnt )
  94. WTYPE icrc;
  95. unsigned char    *icp;
  96. int    icnt;
  97. {
  98.    register WTYPE crc = icrc;
  99.    register unsigned char    *cp = icp;
  100.    register int    cnt = icnt;
  101.  
  102.    while ( cnt--) {
  103. #ifndef SWAPPED
  104.       crc = (crc << B) ^ crctab[(crc>>(W-B)) ^ *cp++];
  105. #else
  106.       crc = (crc >> B) ^ crctab[(crc & ((1<<B)-1)) ^ *cp++];
  107. #endif 
  108.    }
  109.  
  110.    return( crc );
  111. }
  112.  
  113.  
  114. #ifdef MAKETAB
  115.  
  116. #include <stdio.h>
  117. main()
  118. {
  119.    initcrctab();
  120. }
  121.  
  122.  
  123. initcrctab()
  124. {
  125.    register int    b, i;
  126.    WTYPE v;
  127.  
  128.  
  129.    for ( b = 0; b <= (1 << B) - 1; ++b ) {
  130. #ifndef SWAPPED
  131.       for ( v = b << (W - B), i = B; --i >= 0; )
  132.          v = v & ((WTYPE)1 << (W - 1)) ? (v << 1) ^ P : v << 1;
  133. #else
  134.       for ( v = b, i = B; --i >= 0; )
  135.          v = v & 1 ? (v >> 1) ^ P : v >> 1;
  136. #endif        
  137.       crctab[b] = v;
  138.  
  139.       (void)  printf( "0x%lx,", v & ((1L << W) - 1L));
  140.       if ( (b & 7) == 7 )
  141.          (void)  printf("\n" );
  142.       else
  143.          (void)  printf("  ");
  144.    }
  145. }
  146.  
  147.  
  148. #endif
  149.  
  150. #ifdef TEST
  151.  
  152. #include <stdio.h>
  153. #include <fcntl.h>
  154. #include <sys/types.h>
  155. #include <sys/stat.h>
  156. #include <pwd.h>
  157. #include <grp.h>
  158. #define MAXBUF    4096
  159.  
  160. #ifndef S_IRGRP
  161. #define S_IRGRP    (S_IREAD >> 3)
  162. #define S_IWGRP (S_IWRITE >> 3)
  163. #define S_IXGRP (S_IEXEC >> 3)
  164. #define S_IROTH (S_IREAD >> 6)
  165. #define S_IWOTH (S_IWRITE >> 6)
  166. #define S_IXOTH (S_IEXEC >> 6)
  167. #endif
  168.  
  169. struct stat stat_buf;
  170. int    initial_crc = INIT_CRC;
  171.  
  172. extern char    *optarg;
  173. extern int    optind;
  174. extern int    opterr;
  175.  
  176. main( argc, argv )
  177. int    argc;
  178. char    **argv;
  179. {
  180.    int    stats_flag = 0;
  181.  
  182.    int    c;
  183.  
  184.    if (argc == 1) {
  185.       print_crc((char *)0, 0);
  186.       return 0;
  187.    }
  188.  
  189.    /* process all arguments */
  190.  
  191.    while ((c = getopt(argc, argv, "VvI:i:")) != EOF) {
  192.  
  193.       switch (c) {
  194.  
  195.       case 'V':
  196.       case 'v':
  197.          stats_flag = 1;
  198.          break;
  199.  
  200.       case 'I':
  201.       case 'i':
  202.          initial_crc = atoi(optarg);
  203.          break;
  204.  
  205.       default:
  206.          (void) fprintf(stderr, "crc:  -v (verbose listing)\n");
  207.          (void) fprintf(stderr, "      -i value (initial crc value)\n");
  208.          exit(1);
  209.       }
  210.    }
  211.  
  212.    for (; optind < argc ; optind++)
  213.       print_crc(argv[optind], stats_flag);
  214.  
  215.    return 0;
  216. }
  217.  
  218.  
  219. print_crc(name, stat_flag)
  220. char    *name;
  221. int    stat_flag;
  222. {
  223.    int    fd;
  224.    int    nr;
  225.    unsigned char    buf[MAXBUF];
  226.    WTYPE crc;
  227. #ifdef MAGICCHECK
  228.    WTYPE crc2;
  229. #endif
  230.  
  231.    fd = 0;
  232.  
  233.    /* quietly ignore files we can't stat */
  234.  
  235.    if (name != NULL && stat(name, &stat_buf) != 0)
  236.       return;
  237.  
  238.    /* don't do a crc on strange files */
  239.  
  240.    crc = nr = 0;
  241.  
  242.    if (name == NULL || (stat_buf.st_mode & S_IFMT) == S_IFREG) {
  243.  
  244.       /* open the file and do a crc on it */
  245.  
  246.       if (name != NULL && (fd = open( name, O_RDONLY )) < 0 ) {
  247.          perror( name );
  248.          exit( -1 );
  249.       }
  250. #ifdef MAGICCHECK
  251.       crc2 = 
  252. #endif
  253.       crc = initial_crc;
  254.  
  255.       while ( (nr = read( fd, (char *)buf, MAXBUF )) > 0 ) {
  256.          crc = updcrc(crc, buf, nr );
  257.       }
  258.       (void) close(fd);
  259.  
  260.    }
  261.    if ( nr != 0 ) {
  262.       perror( "read error" );
  263.    } else {
  264.       (void)  printf("%4.4x", (unsigned) crc );
  265.       if (stat_flag)
  266.          stats(name);
  267.       else
  268.          (void)  printf("\n");
  269.  
  270.    }
  271.  
  272. #ifdef MAGICCHECK
  273.    /* tack one's complement of crc onto data stream, and
  274.        continue crc calculation.  Should get a constant (magic number)
  275.        dependent only on P, not the data.
  276.      */
  277.    crc2 = crc ^ -1L;
  278.    for ( nr = W - B; nr >= 0; nr -= B ) {
  279.       buf[0] = (crc2 >> nr);
  280.       crc = updcrc(crc, buf, 1);
  281.    }
  282.  
  283.    /* crc should now equal magic */
  284.    buf[0] = buf[1] = buf[2] = buf[3] = 0;
  285.    (void)  printf( "magic test: %lx =?= %lx\n", crc, updcrc((WTYPE) - 1, buf, W / B));
  286. #endif 
  287.  
  288.  
  289. }
  290.  
  291.  
  292. stats(name)
  293. char    *name;
  294. {
  295.  
  296.    struct passwd *entry;
  297.    struct group *group_entry;
  298.    static char    owner[20];
  299.    static char    group[20];
  300.    char    a_time[50];
  301.  
  302.    struct passwd *getpwuid();
  303.    struct group *getgrgid();
  304.    char    *ctime();
  305.  
  306.    static int    prev_uid = -9999;
  307.    static int    prev_gid = -9999;
  308.  
  309.    if (stat_buf.st_uid != prev_uid) {
  310.       entry = getpwuid((int)stat_buf.st_uid);
  311.       if (entry)
  312.          (void) strcpy(owner, entry->pw_name);
  313.       else
  314.          (void) sprintf(owner, "%d", stat_buf.st_uid);
  315.       prev_uid = stat_buf.st_uid;
  316.    }
  317.    if (stat_buf.st_gid != prev_gid) {
  318.       group_entry = getgrgid((int)stat_buf.st_gid);
  319.       if (group_entry)
  320.          (void) strcpy(group, group_entry->gr_name);
  321.       else
  322.          (void) sprintf(group, "%d", stat_buf.st_gid);
  323.       prev_gid = stat_buf.st_gid;
  324.    }
  325.  
  326.    (void) strcpy(a_time, ctime(&stat_buf.st_mtime));
  327.    a_time[24] = '\0';
  328.  
  329.    print_perm(stat_buf.st_mode);
  330.  
  331.    (void)  printf(" %s\t%s\t%s %s\n", owner, group, a_time + 4, name);
  332.  
  333. }
  334.  
  335.  
  336. print_perm(perm)
  337. unsigned int    perm;
  338. {
  339.  
  340.    char    string[20];
  341.    (void) strcpy(string, "----------");
  342.  
  343.    switch (perm & S_IFMT) {
  344.  
  345.    case S_IFDIR:
  346.       string[0] = 'd';
  347.       break;
  348.  
  349.    case S_IFBLK:
  350.       string[0] = 'b';
  351.       break;
  352.  
  353.    case S_IFCHR:
  354.       string[0] = 'c';
  355.       break;
  356.  
  357.    case S_IFIFO:
  358.       string[0] = 'p';
  359.       break;
  360.    }
  361.    if (perm & S_IREAD)
  362.       string[1] = 'r';
  363.    if (perm & S_IWRITE)
  364.       string[2] = 'w';
  365.    if (perm & S_ISUID && perm & S_IEXEC)
  366.       string[3] = 's';
  367.    else if (perm & S_IEXEC)
  368.       string[3] = 'x';
  369.    else if (perm & S_ISUID)
  370.       string[3] = 'S';
  371.  
  372.    if (perm & S_IRGRP)
  373.       string[4] = 'r';
  374.    if (perm & S_IWGRP)
  375.       string[5] = 'w';
  376.    if (perm & S_ISUID && perm & S_IXGRP)
  377.       string[6] = 's';
  378.    else if (perm & S_IXGRP)
  379.       string[6] = 'x';
  380.    else if (perm & S_ISUID)
  381.       string[6] = 'l';
  382.  
  383.    if (perm & S_IROTH)
  384.       string[7] = 'r';
  385.    if (perm & S_IWOTH)
  386.       string[8] = 'w';
  387.    if (perm & S_ISVTX && perm & S_IXOTH)
  388.       string[9] = 't';
  389.    else if (perm & S_IXOTH)
  390.       string[9] = 'x';
  391.    else if (perm & S_ISVTX)
  392.       string[9] = 'T';
  393.  
  394.    (void) printf(" %s", string);
  395. }
  396.  
  397. #endif
  398.  
  399.