home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / useful / dist / disk / cdrom / amicdrom / checkcd.c < prev    next >
C/C++ Source or Header  |  1994-02-07  |  13KB  |  498 lines

  1. /* Checkcd.c:
  2.  *
  3.  * Performs consistency checks on a ISO 9660 CD.
  4.  *
  5.  * ----------------------------------------------------------------------
  6.  * This code is (C) Copyright 1994 by Frank Munkert.
  7.  * All rights reserved.
  8.  * This software may be freely distributed and redistributed for
  9.  * non-commercial purposes, provided this notice is included.
  10.  * ----------------------------------------------------------------------
  11.  * History:
  12.  * 
  13.  */
  14.  
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18.  
  19. #include <dos/var.h>
  20. #include <clib/dos_protos.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/exec_protos.h>
  23. #include <clib/utility_protos.h>
  24.  
  25. #include "cdrom.h"
  26. #include "iso9660.h"
  27. #include "rock.h"
  28.  
  29. #ifdef AZTEC_C
  30. #include <pragmas/dos_lib.h>
  31. #include <pragmas/exec_lib.h>
  32. #include <pragmas/utility_lib.h>
  33. #endif
  34.  
  35. #ifdef LATTICE
  36. #include <pragmas/dos_pragmas.h>
  37. #include <pragmas/exec_pragmas.h>
  38. #include <pragmas/utility_pragmas.h>
  39. extern struct Library *SysBase, *DOSBase;
  40. #endif
  41.  
  42. #if defined(_DCC) && defined(REGISTERED)
  43. #include <pragmas/dos_pragmas.h>
  44. #include <pragmas/exec_pragmas.h>
  45. extern struct Library *SysBase, *DOSBase;
  46. #endif
  47.  
  48. #define STD_BUFFERS 20
  49. #define FILE_BUFFERS 2
  50.  
  51. CDROM *g_cd = NULL;
  52. char g_the_device[80];
  53. int g_the_unit;
  54. t_ulong g_memory_type = MEMF_CHIP;
  55. t_ulong g_check_sector;
  56. char *g_check_name;
  57. prim_vol_desc g_pvd;
  58. int g_path_table_records = 0;
  59.  
  60. struct Library *UtilityBase;
  61.  
  62. #define TU(x,o)  (t_ulong)(((unsigned char *)(x))[o])
  63. #define GET721(x) (TU(x,0) + (TU(x,1) << 8))
  64. #define GET722(x) (TU(x,1) + (TU(x,0) << 8))
  65. #define GET731(x) (TU(x,0) + (TU(x,1) << 8) + (TU(x,2) << 16) + (TU(x,3) << 24))
  66. #define GET732(x) (TU(x,3) + (TU(x,2) << 8) + (TU(x,1) << 16) + (TU(x,0) << 24))
  67.  
  68. /* Check consistency of a 7.2.3 field: */
  69.  
  70. void Check_723 (void *p_buf, int p_offset)
  71. {
  72.   t_uchar *buf = (t_uchar *) (p_buf) + (p_offset - 1);
  73.   t_ulong l = buf[0] + (buf[1] << 8);
  74.   t_ulong m = buf[3] + (buf[2] << 8);
  75.   if (l != m) {
  76.     printf ("ERROR: %s, sector %lu, offset %d - not recorded according to 7.2.3\n",
  77.             g_check_name, g_check_sector, p_offset);
  78.   }
  79. }
  80.  
  81. /* Check consistency of a 7.3.3 field: */
  82.  
  83. void Check_733 (void *p_buf, int p_offset)
  84. {
  85.   t_uchar *buf = (t_uchar *) p_buf + (p_offset - 1);
  86.   t_ulong l = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
  87.   t_ulong m = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24);
  88.   if (l != m) {
  89.     printf ("ERROR: %s, sector %lu, offset %d - not recorded according to 7.3.3\n",
  90.             g_check_name, g_check_sector, p_offset);
  91.   }
  92. }
  93.  
  94. /* Check optional path tables: */
  95.  
  96. void Check_Optional_Path_Tables (void)
  97. {
  98.   t_ulong loc1, loc2;
  99.   t_uchar *buf1;
  100.   t_uchar *buf2;
  101.   int i;
  102.   
  103.   for (i=0; i<=1; i++) {
  104.   
  105.     int remain = g_pvd.path_size_m;
  106.  
  107.     if (i == 0)
  108.       loc1 = GET731((char*) &g_pvd.l_table),
  109.       loc2 = GET731((char *) &g_pvd.opt_l_table);
  110.     else
  111.       loc1 = g_pvd.m_table, loc2 = g_pvd.opt_m_table;
  112.     if (!loc2)
  113.       continue;
  114.  
  115.     for (;;) {
  116.     
  117.       if (!Read_Sector (g_cd, loc1)) {
  118.         printf ("ERROR: illegal sector %lu\n", loc1);
  119.         exit (1);
  120.       }
  121.       buf1 = g_cd->buffer;
  122.     
  123.       if (!Read_Sector (g_cd, loc2)) {
  124.         printf ("ERROR: illegal sector %lu\n", loc2);
  125.         exit (1);
  126.       }
  127.       buf2 = g_cd->buffer;
  128.  
  129.       if (memcmp (buf1, buf2, remain > 2048 ? 2048 : remain) != 0) {
  130.         printf ("ERROR: %c path table and optional %c path table differ"
  131.         " in sectors %lu and %lu\n",
  132.         i ? 'M' : 'L', i ? 'M' : 'L', loc1, loc2);
  133.       }
  134.  
  135.       if (remain > 2048)
  136.         remain -= 2048;
  137.       else
  138.         break;
  139.  
  140.       loc1++, loc2++;
  141.     }
  142.   }
  143. }
  144.  
  145. /* Get the path table record in sector p_loc with offset *p_offset. */
  146.  
  147. void Get_Path_Table_Record (t_uchar *p_buf, t_ulong p_loc, t_ulong *p_offset)
  148. {
  149.   t_ulong sector = p_loc + (*p_offset >> 11);
  150.   int len;
  151.  
  152.   if (!Read_Sector (g_cd, sector)) {
  153.     printf ("ERROR: illegal sector %lu\n", sector);
  154.     exit (1);
  155.   }
  156.   len = g_cd->buffer[*p_offset & 2047] + 8;
  157.   if (len & 1)
  158.     len++;
  159.  
  160.   if (len + (*p_offset & 2047) > 2048) {
  161.     int part1_len = 2048 - (*p_offset & 2047);
  162.     memcpy (p_buf, g_cd->buffer + (*p_offset & 2047), part1_len);
  163.     if (!Read_Sector (g_cd, sector+1)) {
  164.       printf ("ERROR: illegal sector %lu\n", sector+1);
  165.       exit (1);
  166.     }
  167.     memcpy (p_buf + part1_len, g_cd->buffer, len - part1_len);
  168.   } else
  169.     memcpy (p_buf, g_cd->buffer + (*p_offset & 2047), len);
  170.   
  171.   *p_offset += len;
  172. }
  173.  
  174. /* Test whether the L and the M path tables contain the same information: */
  175.  
  176. void Compare_L_And_M_Path_Table (void)
  177. {
  178.   t_ulong loc1 = GET731((char*) &g_pvd.l_table);
  179.   t_ulong loc2 = g_pvd.m_table;
  180.   t_ulong offset1 = 0;
  181.   t_ulong offset2 = 0;
  182.   static t_uchar buf1[256];
  183.   static t_uchar buf2[256];
  184.  
  185.   while (offset1 < g_pvd.path_size_m) {
  186.  
  187.     t_ulong tmp = offset1;
  188.  
  189.     Get_Path_Table_Record (buf1, loc1, &offset1);
  190.     Get_Path_Table_Record (buf2, loc2, &offset2);
  191.  
  192.     if (offset1 != offset2) {
  193.       printf ("ERROR: Length mismatch in L and M path table at offset %lu\n",
  194.                 tmp);
  195.       return;
  196.     }
  197.  
  198.     if (buf1[1] != buf2[1])
  199.       printf ("ERROR: Extended attribute record lengths differ in L and M"
  200.               " path table at offset %lu\n", offset1);
  201.  
  202.     if (memcmp (buf1+8, buf2+8, buf1[0]) != 0)
  203.       printf ("ERROR: directory identifiers differ in L and M path table "
  204.               "at offset %lu\n", offset1);
  205.  
  206.     if (GET731 (buf1+2) != GET732 (buf2+2))
  207.       printf ("ERROR: extent locations differ in L and M path table at"
  208.               " offset %lu\n", offset1);
  209.  
  210.     if (GET721 (buf1+6) != GET722 (buf2+6))
  211.       printf ("ERROR: parent directory numbers differ in L and M path table at"
  212.               " offset %lu\n", offset1);
  213.  
  214.     g_path_table_records++;
  215.   }
  216. }
  217.  
  218. /* Check consistency of path table and directory records: */
  219.  
  220. void Compare_Path_Table_With_Directory_Records (void)
  221. {
  222.   t_ulong loc = g_pvd.m_table;
  223.   t_ulong offset = 0;
  224.   static t_uchar buf[256];
  225.   int rec = 1;
  226.   VOLUME *vol;
  227.   CDROM_OBJ *obj;
  228.   CDROM_INFO info;
  229.   t_ulong pos;
  230.   t_bool warn_case = 0;
  231.  
  232.   vol = Open_Volume (g_cd, 0);
  233.   if (!vol) {
  234.     printf ("ERROR: cannot open volume\n");
  235.     exit (10);
  236.   }
  237.  
  238.   for (; offset < g_pvd.path_size_m; rec++) {
  239.     t_ulong tmp = offset;
  240.  
  241.     if ((rec & 7) == 1) {
  242.       printf ("\r   (%d of %d)",
  243.                 rec, g_path_table_records);
  244.       fflush (stdout);
  245.     }
  246.     Get_Path_Table_Record (buf, loc, &offset);
  247.     /* skip root record: */
  248.     if (rec == 1)
  249.       continue;
  250.     pos = GET732 (buf+2);
  251.     obj = Iso_Create_Directory_Obj (vol, pos);
  252.     if (!obj || !CDROM_Info (obj, &info)) {
  253.       printf ("\nERROR: cannot get information for directory at location %lu\n"
  254.               "(Path table offset = %lu)\n", pos, tmp);
  255.       exit (10);
  256.     }
  257.     if (info.name_length != buf[0] ||
  258.         Strnicmp ((UBYTE*) info.name, (UBYTE*) buf+8, info.name_length) != 0) {
  259.       printf ("\nERROR: names in path table and directory record differ for "
  260.               "directory at location %lu\n", pos);
  261.       printf ("Name in path table = ");
  262.       fwrite (buf+8, 1, info.name_length, stdout);
  263.       printf ("\nName in directory record = ");
  264.       fwrite (info.name, 1, info.name_length, stdout);
  265.       putchar ('\n');
  266.     } else if (!warn_case && memcmp (info.name, buf+8, info.name_length) != 0) {
  267.       printf ("\nWARNING: Directory names in path table and directory records "
  268.               "differ in case.\n");
  269.       warn_case = 1;
  270.     }
  271.     Close_Object (obj);
  272.   }
  273.   printf ("\r%75s\r", "");
  274.   Close_Volume (vol);
  275. }
  276.  
  277. /* Check optional path tables: */
  278.  
  279. void Check_Path_Tables (void)
  280. {
  281.   Check_Optional_Path_Tables ();
  282.   Compare_L_And_M_Path_Table ();
  283. }
  284.  
  285. /* Check primary volume descriptor: */
  286.  
  287. void Check_PVD (void)
  288. {
  289.   int loc = 16;
  290.   int pvd_pos = 0;
  291.   prim_vol_desc *pvd;
  292.  
  293.   do {
  294.     if (!Read_Sector (g_cd, loc)) {
  295.       printf ("ERROR: illegal sector %d\n", loc);
  296.       exit (1);
  297.     }
  298.     pvd = (prim_vol_desc *) g_cd->buffer;
  299.     if (memcmp (pvd->id, "CD001", 5) != 0) {
  300.       printf ("ERROR: missing standard identifier at sector %d\n", loc);
  301.       exit (10);
  302.     }
  303.     if (pvd->type > 4 && pvd->type < 255)
  304.       printf ("WARNING: unknown volume descriptor type at sector %d\n", loc);
  305.     if (