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