home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / cops_104.zip / cops_104 / src / crc.c < prev    next >
C/C++ Source or Header  |  1992-03-10  |  10KB  |  401 lines

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