home *** CD-ROM | disk | FTP | other *** search
- /* Checkcd.c:
- *
- * Performs consistency checks on a ISO 9660 CD.
- *
- * ----------------------------------------------------------------------
- * This code is (C) Copyright 1994 by Frank Munkert.
- * All rights reserved.
- * This software may be freely distributed and redistributed for
- * non-commercial purposes, provided this notice is included.
- * ----------------------------------------------------------------------
- * History:
- *
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <dos/var.h>
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/utility_protos.h>
-
- #include "cdrom.h"
- #include "iso9660.h"
- #include "rock.h"
-
- #ifdef AZTEC_C
- #include <pragmas/dos_lib.h>
- #include <pragmas/exec_lib.h>
- #include <pragmas/utility_lib.h>
- #endif
-
- #ifdef LATTICE
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/utility_pragmas.h>
- extern struct Library *SysBase, *DOSBase;
- #endif
-
- #if defined(_DCC) && defined(REGISTERED)
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/exec_pragmas.h>
- extern struct Library *SysBase, *DOSBase;
- #endif
-
- #define STD_BUFFERS 20
- #define FILE_BUFFERS 2
-
- CDROM *g_cd = NULL;
- char g_the_device[80];
- int g_the_unit;
- t_ulong g_memory_type = MEMF_CHIP;
- t_ulong g_check_sector;
- char *g_check_name;
- prim_vol_desc g_pvd;
- int g_path_table_records = 0;
-
- struct Library *UtilityBase;
-
- #define TU(x,o) (t_ulong)(((unsigned char *)(x))[o])
- #define GET721(x) (TU(x,0) + (TU(x,1) << 8))
- #define GET722(x) (TU(x,1) + (TU(x,0) << 8))
- #define GET731(x) (TU(x,0) + (TU(x,1) << 8) + (TU(x,2) << 16) + (TU(x,3) << 24))
- #define GET732(x) (TU(x,3) + (TU(x,2) << 8) + (TU(x,1) << 16) + (TU(x,0) << 24))
-
- /* Check consistency of a 7.2.3 field: */
-
- void Check_723 (void *p_buf, int p_offset)
- {
- t_uchar *buf = (t_uchar *) (p_buf) + (p_offset - 1);
- t_ulong l = buf[0] + (buf[1] << 8);
- t_ulong m = buf[3] + (buf[2] << 8);
- if (l != m) {
- printf ("ERROR: %s, sector %lu, offset %d - not recorded according to 7.2.3\n",
- g_check_name, g_check_sector, p_offset);
- }
- }
-
- /* Check consistency of a 7.3.3 field: */
-
- void Check_733 (void *p_buf, int p_offset)
- {
- t_uchar *buf = (t_uchar *) p_buf + (p_offset - 1);
- t_ulong l = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
- t_ulong m = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24);
- if (l != m) {
- printf ("ERROR: %s, sector %lu, offset %d - not recorded according to 7.3.3\n",
- g_check_name, g_check_sector, p_offset);
- }
- }
-
- /* Check optional path tables: */
-
- void Check_Optional_Path_Tables (void)
- {
- t_ulong loc1, loc2;
- t_uchar *buf1;
- t_uchar *buf2;
- int i;
-
- for (i=0; i<=1; i++) {
-
- int remain = g_pvd.path_size_m;
-
- if (i == 0)
- loc1 = GET731((char*) &g_pvd.l_table),
- loc2 = GET731((char *) &g_pvd.opt_l_table);
- else
- loc1 = g_pvd.m_table, loc2 = g_pvd.opt_m_table;
- if (!loc2)
- continue;
-
- for (;;) {
-
- if (!Read_Sector (g_cd, loc1)) {
- printf ("ERROR: illegal sector %lu\n", loc1);
- exit (1);
- }
- buf1 = g_cd->buffer;
-
- if (!Read_Sector (g_cd, loc2)) {
- printf ("ERROR: illegal sector %lu\n", loc2);
- exit (1);
- }
- buf2 = g_cd->buffer;
-
- if (memcmp (buf1, buf2, remain > 2048 ? 2048 : remain) != 0) {
- printf ("ERROR: %c path table and optional %c path table differ"
- " in sectors %lu and %lu\n",
- i ? 'M' : 'L', i ? 'M' : 'L', loc1, loc2);
- }
-
- if (remain > 2048)
- remain -= 2048;
- else
- break;
-
- loc1++, loc2++;
- }
- }
- }
-
- /* Get the path table record in sector p_loc with offset *p_offset. */
-
- void Get_Path_Table_Record (t_uchar *p_buf, t_ulong p_loc, t_ulong *p_offset)
- {
- t_ulong sector = p_loc + (*p_offset >> 11);
- int len;
-
- if (!Read_Sector (g_cd, sector)) {
- printf ("ERROR: illegal sector %lu\n", sector);
- exit (1);
- }
- len = g_cd->buffer[*p_offset & 2047] + 8;
- if (len & 1)
- len++;
-
- if (len + (*p_offset & 2047) > 2048) {
- int part1_len = 2048 - (*p_offset & 2047);
- memcpy (p_buf, g_cd->buffer + (*p_offset & 2047), part1_len);
- if (!Read_Sector (g_cd, sector+1)) {
- printf ("ERROR: illegal sector %lu\n", sector+1);
- exit (1);
- }
- memcpy (p_buf + part1_len, g_cd->buffer, len - part1_len);
- } else
- memcpy (p_buf, g_cd->buffer + (*p_offset & 2047), len);
-
- *p_offset += len;
- }
-
- /* Test whether the L and the M path tables contain the same information: */
-
- void Compare_L_And_M_Path_Table (void)
- {
- t_ulong loc1 = GET731((char*) &g_pvd.l_table);
- t_ulong loc2 = g_pvd.m_table;
- t_ulong offset1 = 0;
- t_ulong offset2 = 0;
- static t_uchar buf1[256];
- static t_uchar buf2[256];
-
- while (offset1 < g_pvd.path_size_m) {
-
- t_ulong tmp = offset1;
-
- Get_Path_Table_Record (buf1, loc1, &offset1);
- Get_Path_Table_Record (buf2, loc2, &offset2);
-
- if (offset1 != offset2) {
- printf ("ERROR: Length mismatch in L and M path table at offset %lu\n",
- tmp);
- return;
- }
-
- if (buf1[1] != buf2[1])
- printf ("ERROR: Extended attribute record lengths differ in L and M"
- " path table at offset %lu\n", offset1);
-
- if (memcmp (buf1+8, buf2+8, buf1[0]) != 0)
- printf ("ERROR: directory identifiers differ in L and M path table "
- "at offset %lu\n", offset1);
-
- if (GET731 (buf1+2) != GET732 (buf2+2))
- printf ("ERROR: extent locations differ in L and M path table at"
- " offset %lu\n", offset1);
-
- if (GET721 (buf1+6) != GET722 (buf2+6))
- printf ("ERROR: parent directory numbers differ in L and M path table at"
- " offset %lu\n", offset1);
-
- g_path_table_records++;
- }
- }
-
- /* Check consistency of path table and directory records: */
-
- void Compare_Path_Table_With_Directory_Records (void)
- {
- t_ulong loc = g_pvd.m_table;
- t_ulong offset = 0;
- static t_uchar buf[256];
- int rec = 1;
- VOLUME *vol;
- CDROM_OBJ *obj;
- CDROM_INFO info;
- t_ulong pos;
- t_bool warn_case = 0;
-
- vol = Open_Volume (g_cd, 0);
- if (!vol) {
- printf ("ERROR: cannot open volume\n");
- exit (10);
- }
-
- for (; offset < g_pvd.path_size_m; rec++) {
- t_ulong tmp = offset;
-
- if ((rec & 7) == 1) {
- printf ("\r (%d of %d)",
- rec, g_path_table_records);
- fflush (stdout);
- }
- Get_Path_Table_Record (buf, loc, &offset);
- /* skip root record: */
- if (rec == 1)
- continue;
- pos = GET732 (buf+2);
- obj = Iso_Create_Directory_Obj (vol, pos);
- if (!obj || !CDROM_Info (obj, &info)) {
- printf ("\nERROR: cannot get information for directory at location %lu\n"
- "(Path table offset = %lu)\n", pos, tmp);
- exit (10);
- }
- if (info.name_length != buf[0] ||
- Strnicmp ((UBYTE*) info.name, (UBYTE*) buf+8, info.name_length) != 0) {
- printf ("\nERROR: names in path table and directory record differ for "
- "directory at location %lu\n", pos);
- printf ("Name in path table = ");
- fwrite (buf+8, 1, info.name_length, stdout);
- printf ("\nName in directory record = ");
- fwrite (info.name, 1, info.name_length, stdout);
- putchar ('\n');
- } else if (!warn_case && memcmp (info.name, buf+8, info.name_length) != 0) {
- printf ("\nWARNING: Directory names in path table and directory records "
- "differ in case.\n");
- warn_case = 1;
- }
- Close_Object (obj);
- }
- printf ("\r%75s\r", "");
- Close_Volume (vol);
- }
-
- /* Check optional path tables: */
-
- void Check_Path_Tables (void)
- {
- Check_Optional_Path_Tables ();
- Compare_L_And_M_Path_Table ();
- }
-
- /* Check primary volume descriptor: */
-
- void Check_PVD (void)
- {
- int loc = 16;
- int pvd_pos = 0;
- prim_vol_desc *pvd;
-
- do {
- if (!Read_Sector (g_cd, loc)) {
- printf ("ERROR: illegal sector %d\n", loc);
- exit (1);
- }
- pvd = (prim_vol_desc *) g_cd->buffer;
- if (memcmp (pvd->id, "CD001", 5) != 0) {
- printf ("ERROR: missing standard identifier at sector %d\n", loc);
- exit (10);
- }
- if (pvd->type > 4 && pvd->type < 255)
- printf ("WARNING: unknown volume descriptor type at sector %d\n", loc);
- if (pvd->version != 1)
- printf ("WARNING: unknown volume descriptor version at sector %d\n", loc);
- if (pvd->type == 1 && !pvd_pos)
- pvd_pos = loc;
- loc++;
- } while (pvd->type != 255);
-
- if (!Read_Sector (g_cd, pvd_pos)) {
- printf ("ERROR: illegal sector %d\n", loc);
- exit (1);
- }
- pvd = (prim_vol_desc *) g_cd->buffer;
- g_check_name = "primary volume descriptor";
- g_check_sector = pvd_pos;
- Check_733 (pvd, 81);
- Check_723 (pvd, 121);
- Check_723 (pvd, 125);
- Check_723 (pvd, 129);
- Check_733 (pvd, 133);
- memcpy (&g_pvd, pvd, sizeof (g_pvd));
- }
-
- void Check_Subdirectory (CDROM_OBJ *p_home, char *p_name)
- {
- CDROM_OBJ *obj;
- CDROM_INFO info;
- /* VOLUME *vol = p_home->volume; */
-
- printf (" %s\r", p_name);
- fflush (stdout);
-
- if (obj = Open_Object (p_home, p_name)) {
- unsigned long offset = 0;
-
- while (Examine_Next (obj, &info, &offset)) {
- directory_record *dir = info.suppl_info;
- g_check_name = "directory record";
- g_check_sector = offset;
- Check_733 (dir, 3);
- Check_733 (dir, 11);
- Check_723 (dir, 29);
- }
-
- Close_Object (obj);
- } else {
- printf ("ERROR: Object '%s': iso_errno = %d\n", p_name, iso_errno);
- return;
- }
-
- if (obj = Open_Object (p_home, p_name)) {
- unsigned long offset = 0;
-
- while (Examine_Next (obj, &info, &offset)) {
- if (info.directory_f) {
- char *name = malloc (strlen (p_name) + info.name_length + 2);
- int len;
- if (!name) {
- fprintf (stderr, "out of memory\n");
- exit (10);
- }
- if (Is_Top_Level_Object (obj))
- name[0] = 0;
- else
- sprintf (name, "%s/", p_name);
- len = strlen (name) + info.name_length;
- memcpy (name + strlen (name), info.name, info.name_length);
- name[len] = 0;
- Check_Subdirectory (p_home, name);
- free (name);
- }
- }
- Close_Object (obj);
- } else {
- printf ("ERROR: Object '%s': iso_errno = %d\n", p_name, iso_errno);
- }
-
- printf (" %*s\r", strlen (p_name), "");
- }
-
- void Check_Directories (void)
- {
- VOLUME *vol;
- CDROM_OBJ *home;
-
- if (!(vol = Open_Volume (g_cd, 1))) {
- printf ("ERROR: cannot open volume; iso_errno = %d\n", iso_errno);
- exit (10);
- }
-
- if (!(home = Open_Top_Level_Directory (vol))) {
- printf ("ERROR: cannot open top level directory; iso_errno = %d\n", iso_errno);
- Close_Volume (vol);
- exit (1);
- }
-
- Check_Subdirectory (home, ":");
-
- Close_Object (home);
- Close_Volume (vol);
- }
-
- void Cleanup (void)
- {
- if (g_cd)
- Cleanup_CDROM (g_cd);
-
- if (UtilityBase)
- CloseLibrary (UtilityBase);
- }
-
- int Get_Device_And_Unit (void)
- {
- int len;
- char buf[10];
-
- len = GetVar ((UBYTE *) "CDROM_DEVICE", (UBYTE *) g_the_device,
- sizeof (g_the_device), 0);
- if (len < 0)
- return 0;
- if (len >= sizeof (g_the_device)) {
- fprintf (stderr, "CDROM_DEVICE too long\n");
- exit (1);
- }
- g_the_device[len] = 0;
-
- len = GetVar ((UBYTE *) "CDROM_UNIT", (UBYTE *) buf,
- sizeof (buf), 0);
- if (len < 0)
- return 0;
- if (len >= sizeof (buf)) {
- fprintf (stderr, "CDROM_UNIT too long\n");
- exit (1);
- }
- buf[len] = 0;
- g_the_unit = atoi (buf);
-
- if (GetVar ((UBYTE *) "CDROM_FASTMEM", (UBYTE *) buf,
- sizeof (buf), 0) > 0) {
- fprintf (stderr, "using fastmem\n");
- g_memory_type = MEMF_FAST;
- }
-
- return 1;
- }
-
- void main (int argc, char *argv[])
- {
- atexit (Cleanup);
-
- if (!(UtilityBase = (struct Library *)
- OpenLibrary ((UBYTE *) "utility.library", 37))) {
- fprintf (stderr, "cannot open utility.library\n");
- exit (1);
- }
-
- if (!Get_Device_And_Unit ()) {
- fprintf (stderr,
- "Please set the following environment variables:\n"
- " CDROM_DEVICE name of SCSI device\n"
- " CDROM_UNIT unit number of CDROM drive\n"
- "e.g.\n"
- " setenv CDROM_DEVICE scsi.device\n"
- " setenv CDROM_UNIT 2\n"
- "Set the variable CDROM_FASTMEM to any value if you\n"
- "want to use fast memory for SCSI buffers (does not work\n"
- "with all SCSI devices!)\n"
- );
- exit (1);
- }
-
- g_ignore_blocklength = TRUE;
-
- g_cd = Open_CDROM (g_the_device, g_the_unit, 1, g_memory_type,
- STD_BUFFERS, FILE_BUFFERS);
- if (!g_cd) {
- fprintf (stderr, "cannot open CDROM, error code = %d\n", g_cdrom_errno);
- exit (1);
- }
-
- printf ("Checking primary volume descriptor...\n");
- Check_PVD ();
- printf ("Checking path tables...\n");
- Check_Path_Tables ();
- printf ("Comparing path table with directory records...\n");
- Compare_Path_Table_With_Directory_Records ();
-
- printf ("Checking directories...\n");
- Check_Directories ();
-
- printf ("All checks completed.\n");
-
- exit (0);
- }
-