home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1995 May / Simtel-MSDOS-May1995-CD2.iso / utils / lookup.c < prev    next >
C/C++ Source or Header  |  1995-04-11  |  8KB  |  344 lines

  1. /*
  2.  *    lookup.c
  3.  *
  4.  *
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <memory.h>
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <fcntl.h>
  14. #include <assert.h>
  15. #ifdef unix
  16. #include <unistd.h>
  17. /*#include <strerror.h>*/
  18. #define strnicmp  strncasecmp
  19. #else
  20. #include <io.h>
  21. #endif
  22. #include "rockridg.h"
  23. #include "datadef.h"
  24.  
  25. #ifndef O_BINARY
  26. #define O_BINARY 0
  27. #endif
  28.  
  29. static void Read(int fd, void *buf, int n, int swap);
  30. #if 0
  31. static void _Read(int fd, void *buf, int n, int swap, int line, char *file);
  32. #define  Read(fd, buf, n, swap) _Read((fd), (buf), (n), (swap), __LINE__, __FILE__)
  33. #endif
  34.  
  35. #ifdef unix
  36. static const char datafile[] = "utils/lookup.dat";
  37. #else
  38. static const char datafile[] = "/utils/lookup.dat";
  39. #endif
  40. static char word[256];
  41. static struct file_header hdr;
  42. static long rehash6;
  43. static long rehash16;
  44. static int fd;
  45.  
  46. static long
  47. hash2(const unsigned char *s) {
  48.   unsigned long h, g, r;
  49.   int c;
  50.   int i;
  51.  
  52.   r = h = ((long) s[0] << 16) + (s[1] << 8);
  53.   for (i = 0; s[i] != 0; ++i) {
  54.       h += ((long) s[i] << i) + s[i];
  55.       h ^= h >> i;
  56.   }
  57.   while ((c = *s++) != '\0') {
  58.       h <<= 4;
  59.       h += c;
  60.       g = h & 0xf0000000;
  61.       h ^= g;
  62.       h ^= (g >> 24);
  63.       r ^= h;
  64.   }
  65.   rehash6 = r % 61;
  66.   rehash16 = r % 65521;
  67.   return h % hdr.hash_prime;
  68. }
  69.  
  70. static int
  71. search_file(const char *filename) {
  72.     FILE *fp;
  73.     int rv;
  74.     static char line[257];
  75.     char *s;
  76.     int lc, uc, len;
  77.  
  78.  
  79. /*    fprintf(stderr, "searching file %s\n", filename); */
  80.  
  81.     lc = *word;
  82.     if (islower(lc)) {
  83.         uc = lc + 'A' - 'a';
  84.     } else {
  85.         uc = lc;
  86.     }
  87.     len = strlen(word);
  88. #ifdef unix
  89.     if (*filename == '/') {
  90.     ++filename;
  91.     }
  92. #endif    
  93.     if ((fp = fopen(filename, "rt")) == NULL) {
  94.         fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
  95.         return 0;
  96.     }
  97.     rv = 0;
  98.     while (fgets(line, 256, fp) != NULL) {
  99.     line[255] = '\n';
  100.     line[256] = '\0';
  101.         for (s = line; *s != 0; ++s) {
  102.             if (*s == lc || (*s == uc && isupper(*s))) {
  103.                 if (strnicmp(s, word, len) == 0) {
  104.                     ++rv;
  105.                     printf("%s: %s", filename, line);
  106.             break;
  107.                 }
  108.             }
  109.         }
  110.     }
  111.     fclose(fp);
  112.     return rv;
  113. }
  114.  
  115. static char *
  116. lookup_dir(int n) {
  117.     static char path[1024];
  118.     unsigned char buf[300];
  119.     unsigned char *p;
  120.     short dir_num;
  121.     long x;
  122.  
  123.     if (n == 0) {
  124.         path[0] = '\0';
  125.         return path;
  126.     }
  127.     lseek(fd, hdr.dir_table_offset + n * sizeof(long), SEEK_SET);
  128.     Read(fd, &x, sizeof(x), 1);
  129.     lseek(fd, x, SEEK_SET);
  130.     Read(fd, buf, sizeof(buf), 0);
  131.     dir_num = buf[0] + (buf[1] << 8);
  132.     p = lookup_dir(dir_num);
  133.     strcat(p, "/");
  134.     strcat(p, buf + 2);
  135.     return p;
  136. }
  137.  
  138. static char *
  139. lookup_filename(long n) {
  140.     unsigned char buf[300];
  141.     unsigned char *p;
  142.     short dir_num;
  143.  
  144.     lseek(fd, n, SEEK_SET);
  145.     Read(fd, buf, sizeof(buf), 0);
  146.     dir_num = buf[0] + (buf[1] << 8);
  147.     p = lookup_dir(dir_num);
  148.     strcat(p, "/");
  149.     strcat(p, buf + 2);
  150.     return p;
  151. }
  152.  
  153. static int
  154. search_block(int block) {
  155.     int rv, i;
  156.     long *p;
  157.     long b[2];
  158.     int nfiles;
  159.  
  160. /*    fprintf(stderr, "searching_block( %d == %x )\n", block, block);  */
  161.     if (lseek(fd, hdr.block_table_offset + block * 4, SEEK_SET) < 0) {
  162.     fprintf(stderr, "lseek <1> failed: %s\n", strerror(errno));
  163.     exit(1);
  164.     }
  165.     Read(fd, &b, sizeof(b), 1);
  166.     if (block == (hdr.num_blocks - 1)) {
  167.         nfiles = hdr.num_files - b[0];
  168.     assert(nfiles > 0);
  169.     } else {
  170.         nfiles = b[1] - b[0];
  171.     assert(nfiles > 0);
  172.     }
  173.     p = malloc(nfiles * sizeof(*p));
  174.     if (lseek(fd, hdr.file_table_offset + (b[0] * 4), SEEK_SET) < 0) {
  175.     fprintf(stderr, "lseek <2> failed: %s\n", strerror(errno));
  176.     exit(1);
  177.     }
  178.     assert(lseek(fd, 0L, SEEK_CUR) ==
  179.            hdr.file_table_offset + (b[0] * 4));
  180.     Read(fd, p, nfiles * 4, 1);
  181.     for (rv = i = 0; i < nfiles; ++i) {
  182. #ifndef unix
  183.     char dir[3];
  184.  
  185.     sprintf(dir, "%c:", getdisk() + 'A');
  186.         rv += search_file(get_real_filename(dir, lookup_filename(p[i])));
  187. #else    
  188.         rv += search_file(lookup_filename(p[i]));
  189. #endif    
  190.     }
  191.     free(p);
  192.     return rv;
  193. }
  194.  
  195. static int
  196. search(unsigned long x) {
  197.     int rv;
  198.     unsigned char p[512];
  199.     int i, j, n, b;
  200.     long offset;
  201.  
  202.     rv = 0;
  203.     offset = x & 0xffffffL;
  204.     switch ((x >> 30) & 0x3) {
  205.  
  206.     case 0:
  207.         lseek(fd, offset, SEEK_SET);
  208.         Read(fd, p, sizeof(p), 0);
  209.         for (i = 0; i < hdr.num_blocks; ++i) {
  210.             if (p[i/8] & (1 << (i % 8))) {
  211.                 rv += search_block(i);
  212.             }
  213.         }
  214.         break;
  215.  
  216.     case 1:
  217.         rv = search_block(x & 0xfff);
  218.         break;
  219.  
  220.     case 2:
  221.         rv =  search_block(x & 0xfff);
  222.         rv += search_block((x >> 12) & 0xfff);
  223.         break;
  224.  
  225.     case 3:
  226.  
  227.         lseek(fd, offset, SEEK_SET);
  228.         Read(fd, p, sizeof(p), 0);
  229.         j = 0;
  230.         n = p[j++];
  231.         n += ((p[j] & 0x0f) << 8);
  232.         for (i = 1; i < n + 1; ++i) {
  233.             if (i & 1) {
  234.                 b = (p[j++] & 0xf0) >> 4;
  235.                 b += p[j++] << 4;
  236.             } else {
  237.                 b = p[j++];
  238.                 b += (p[j] & 0x0f) << 8;
  239.             }
  240.             rv += search_block(b);
  241.         }
  242.         break;
  243.     }
  244.     return rv;
  245. }
  246.  
  247. void
  248. main(int argc, char **argv) {
  249.     unsigned int len;
  250.     unsigned int match;
  251.     unsigned long h;
  252.     unsigned long x;
  253.     unsigned short i;
  254.  
  255.     if (argc != 2) {
  256.         fprintf(stderr,
  257.         "usage: lookup <word>\n"
  258.         "       Search a CDROM for all files containing\n"
  259.             "       the specified word.\n");
  260.         exit(1);
  261.     }
  262.     strcpy(word, argv[1]);
  263.     len = strlen(word);
  264.     for (i = 0; i < len; ++i) {
  265.         if (isupper(word[i])) {
  266.             word[i] = tolower(word[i]);
  267.         }
  268.     }
  269.     if ((fd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
  270.         fprintf(stderr, "cannot open %s: %s\n",
  271.         datafile, strerror(errno));
  272.         exit(1);
  273.     }
  274.     Read(fd, &hdr, sizeof(hdr), 1);
  275.     assert(hdr.header_size == sizeof(hdr));
  276.     assert(hdr.filesize == lseek(fd, 0L, SEEK_END));
  277.     h = hash2(word);
  278.     match = 0;
  279.     for (i = 0;; ++i) {
  280.         lseek(fd, (h * 4) + hdr.hash_table_offset, SEEK_SET);
  281.         Read(fd, &x, sizeof(x), 1);
  282.         if (x == 0) {
  283.             break;
  284.         }
  285.         if (((x >> 30) == 1 && ((x >> 12) & 0xffff) == rehash16) ||
  286.             ((x >> 30) != 1 && ((x >> 24) & 0x003f) == rehash6)) {
  287.             match = search(x);
  288.             break;
  289.         }
  290.         h = (h + rehash6 + i) % hdr.hash_prime;
  291.     }
  292.     if (match == 0) {
  293.         printf("sorry, no match\n");
  294.     }
  295.     exit(match == 0);
  296. }
  297.  
  298. static void
  299. Read(int fd, void *buf, int n, int swap) {
  300.  
  301.     assert(n > 0);
  302.     assert(swap == 0 || (n & 3) == 0);
  303.     if (read(fd, buf, n) < 0) {
  304.         fprintf(stderr, "read failed: %s\n", strerror(errno));
  305.         exit(1);
  306.     }
  307. #ifdef sparc
  308.     if (swap) {
  309.         int i;
  310.         unsigned char c;
  311.         unsigned char *p;
  312.  
  313.         p = buf;
  314.         for (i = 0; i < n; i += 4) {
  315.             c = p[i];
  316.             p[i] = p[i + 3];
  317.             p[i + 3] = c;
  318.             c = p[i + 1];
  319.             p[i + 1] = p[i + 2];
  320.             p[i + 2] = c;
  321.         }
  322.     }
  323. #endif
  324.     return;
  325. }
  326.  
  327. #ifdef sparc
  328. const char *
  329. strerror(error)
  330.     int error;
  331. {
  332.     static char defaultMsg[32];
  333.     extern int sys_nerr;
  334.     extern char *sys_errlist[];
  335.  
  336.     if ((error < sys_nerr) && (error > 0)) {
  337.         return sys_errlist[error];
  338.     }
  339.     (void) sprintf(defaultMsg, "unknown error (%d)", error);
  340.     return defaultMsg;
  341. }
  342. #endif
  343.  
  344.