home *** CD-ROM | disk | FTP | other *** search
- #define VERSION 1.10
- #define LAST_CHANGED 900924
-
- /*--------------------------------------*
- | File: DT.c - Rev. 1.10 900924 |
- +--------------------------------------+
- | DT: disk test, a la Norton Utilities |
- +--------------------------------------+---------------*
- | Author: Maurizio Loreti, aka MLO or I3NOO. |
- | Address: University of Padova - Deparment of Physics |
- | Via F. Marzolo, 8 - 35131 PADOVA - Italy |
- | Phone: (39)(49) 844-313 FAX: (39)(49) 844-245 |
- | E-Mail: LORETI at IPDINFN (BITNET) or VAXFPD::LORETI |
- | (DECnet). VAXFPD is node 38.257, i.e. 39169. |
- | Home: Via G. Donizetti, 6 - 35010 CADONEGHE (Padova) |
- *------------------------------------------------------*/
-
- /**
- | #include's
- **/
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <dos.h>
- #include <exec/types.h>
- #include <exec/exec.h>
- #include <devices/trackdisk.h>
- #include "mlo.h"
-
- /**
- | #define's. The first two should be in TRACKDISK.H, the fourth in
- | STDIO.H for ANSI compilers - but are not there in the Lattice
- | Include files. TD_CYL is the number of bytes per cylinder.
- **/
-
- #define NUMCYLS 80
- #define NUMHEADS 2
- #define TD_CYL (TD_SECTOR * NUMSECS)
- #define FILENAME_MAX 108
- #define ON 1
- #define OFF 0
-
- /**
- | A structure definition for directory entries; for Lattice C, only one
- | call to dfind/dnext can be active at a time: so, scanning directories,
- | we check all files first and, only then, all subdirectories one by one.
- **/
-
- typedef struct sdirEntry {
- char *name;
- struct sdirEntry *next;
- } dirEntry;
-
- /**
- | Global variables: Intuition pointers; the disk change
- | number, and the total number of errors found reading files;
- | the number of checked files and directories; and a flag
- | "scheduled from WB or CLI".
- **/
-
- struct MsgPort *diskPort = NULL;
- struct IOExtTD *diskReq = NULL;
- BYTE *diskBuffer = NULL;
- ULONG diskChangeCount;
- int nErFil = 0;
- int nDirs = 0;
- int nFiles = 0;
- Boolean fromWorkBench;
-
- /**
- | The ANSI procedure prototypes
- **/
-
- void checkDir(char *path, Boolean root);
- void checkFile(char *name);
- void cleanup(int code);
- void motor(int action);
- void pcl(int n, char *fmt, ...);
- void readCyl(int cyl, int hd);
- void seekFullRange(SHORT howmany);
- void syntax(void);
-
- main(
- int argc,
- char **argv
- ){
- int drive, cyl, head;
- SHORT error;
- char driveName[5];
-
- /**
- | To be called from CLI, with DT DFx[:] ; if called from the
- | Workbench, a prompt for the floppy unit is sent to the console
- | window (created from the Lattice initialisation routine).
- | Pass 1: a seek over full range;
- | Pass 2: read all cylinders;
- | Pass 3: read all files record by record.
- | But first, check the input arguments and open Intuition.
- **/
-
- fprintf(stdout, "\n\t\"DT\" - V%.2f MLO %d\n", VERSION, LAST_CHANGED);
-
- if (argc == 0) {
- do {
- fprintf(stdout, "\nDrive to test (DF0-DF4) ? ");
- fgets(driveName, sizeof(driveName), stdin);
- } while (strnicmp(driveName, "df", 2) ||
- (drive = atoi(driveName + 2)) < 0 || drive > 4);
- fromWorkBench = True;
- } else {
- fromWorkBench = False;
- if (argc != 2 || strnicmp(*++argv, "df", 2)) syntax();
- if ((drive = atoi(*argv+2)) < 0 || drive > 4) syntax();
- }
-
- if ((diskBuffer = (BYTE *) AllocMem(TD_CYL, MEMF_CHIP)) == NULL) {
- fprintf(stderr, "Can't allocate chip memory ...\n");
- cleanup(SYS_ABORT_CODE);
- }
-
- /**
- | Pass 1
- **/
-
- if (!(diskPort = (struct MsgPort *) CreatePort(0, 0))) {
- fprintf(stderr, "Can't create I/O port ...\n");
- cleanup(SYS_ABORT_CODE);
- }
-
- if (!(diskReq = (struct IOExtTD *)
- CreateExtIO(diskPort, sizeof(struct IOExtTD))) ) {
- fprintf(stderr, "Can't obtain I/O request block ...\n");
- cleanup(SYS_ABORT_CODE);
- }
-
- sprintf(driveName, "DF%d:", drive);
- if (error = OpenDevice(TD_NAME, drive, diskReq, 0)) {
- fprintf(stderr,
- "Error 0x%X returned by OpenDevice for drive %s ...\n",
- error, driveName);
- cleanup(SYS_ABORT_CODE);
- }
-
- diskReq->iotd_Req.io_Command = TD_CHANGENUM;
- DoIO(diskReq);
- diskChangeCount = diskReq->iotd_Req.io_Actual;
- fprintf(stdout, "\nChange number for drive %s is %d;\n",
- driveName, diskChangeCount);
- motor(ON);
- seekFullRange(1);
-
- /**
- | Pass 2
- **/
-
- fprintf(stdout, "Checking all disk tracks:\n");
- for (cyl=0; cyl<NUMCYLS; cyl++) {
- for (head=0; head<NUMHEADS; head++) {
- fprintf(stdout, " reading cylinder %d, head %d ...\r", cyl, head);
- readCyl(cyl, head);
- if (error = diskReq->iotd_Req.io_Error) {
- motor(OFF);
- fprintf(stdout,
- "Error 0x%X detected for cylinder %d, head %d\n",
- error, cyl, head);
- cleanup(SYS_ABORT_CODE);
- }
- }
- }
- motor(OFF);
- fprintf(stdout, " no errors detected reading drive %s.\n", driveName);
-
- /**
- | Pass 3
- **/
-
- fprintf(stdout, "Checking all files in drive %s\n", driveName);
- checkDir(driveName, True);
- pcl(2, "%d director%s and %d file%s checked: %d error%s detected.",
- nDirs, (nDirs == 1 ? "y" : "ies"),
- nFiles, (nFiles == 1 ? "" : "s"),
- nErFil, (nErFil == 1 ? "" : "s"));
- cleanup(SYS_NORMAL_CODE);
- }
-
- void checkDir(
- char *path,
- Boolean root
- ){
- struct FILEINFO info;
- char fileName[FILENAME_MAX];
- int error;
- dirEntry *rdE = NULL;
- dirEntry *pdE;
-
- /**
- | Check a directory; path contains the full directory name, and root is
- | non zero for the root directory. We scan all directory files, checking
- | 'true' files at first and all subdirectories at the end, one by one.
- **/
-
- nDirs++;
- pcl(1, " checking files in%s directory %s ...",
- (root ? " root" : ""), path);
- strcpy(fileName, path);
- strcat(fileName, (root ? "#?" : "/#?"));
-
- error = dfind(&info, fileName, True);
- while (!error) {
- strcpy(fileName, path);
- if (!root) strcat(fileName, "/");
- strcat(fileName, info.fib_FileName);
- if (info.fib_DirEntryType < 0) {
- checkFile(fileName);
- } else {
- if ((pdE = malloc(sizeof(dirEntry))) == NULL) {
- fprintf(stderr, "Can't allocate heap memory ...\n");
- cleanup(SYS_ABORT_CODE);
- }
- if ((pdE->name = malloc(strlen(fileName) + 1)) == NULL) {
- fprintf(stderr, "Can't allocate heap memory ...\n");
- cleanup(SYS_ABORT_CODE);
- }
- strcpy(pdE->name, fileName);
- pdE->next = rdE;
- rdE = pdE;
- }
- error = dnext(&info);
- }
-
- while (rdE != NULL) {
- checkDir(rdE->name, False);
- free(rdE->name);
- pdE = rdE->next;
- free(rdE);
- rdE = pdE;
- }
- }
-
- void checkFile(
- char *name
- ){
- struct FileHandle *pFH;
- long ier;
-
- /**
- | Check a file, opening and reading record by record; this procedure
- | is performed using the standard AmigaDOS disk file interface.
- **/
-
- nFiles++;
- pcl(0, " file %s ...", name);
- if ((pFH = (struct FileHandle *) Open(name, MODE_OLDFILE)) == NULL) {
- pcl(1, "* Error opening file \"%s\": file not found.", name);
- nErFil++;
- } else {
- while ((ier = Read(pFH, diskBuffer, TD_CYL)) > 0) { }
- if (ier < 0) {
- pcl(1, "* AmigaDOS error %d reading file \"%s\".", IoErr(), name);
- nErFil++;
- }
- }
- Close(pFH);
- }
-
- void cleanup(
- int code
- ){
- if (diskBuffer != NULL) {
- FreeMem(diskBuffer, TD_CYL);
- }
- if (diskReq != NULL) {
- CloseDevice(diskReq);
- DeleteExtIO(diskReq, sizeof(struct IOExtTD));
- }
- if (diskPort != NULL) DeletePort(diskPort);
-
- if (fromWorkBench) {
- int i;
- fprintf(stdout, "Strike <CR> to continue ...");
- while ( (i = getchar()) != '\n' && i != EOF) { }
- }
- exit(code);
- }
-
- void motor(
- int action
- ){
- diskReq->iotd_Req.io_Length = action;
- diskReq->iotd_Req.io_Command = TD_MOTOR;
- DoIO(diskReq);
- }
-
- void pcl(
- int n,
- char *fmt,
- ...
- ){
- va_list vl;
- static length = 0;
- int nc;
-
- /**
- | What the hell is the delete-to-end-of-line sequence on the Amiga?
- | The AmigaDOS manual refers to the ANSI sequence <ESC>[1K - that do
- | not work in my NewCon windows; so I wrote this simple interface. When
- | overprinting, we check if the length of the new line is greater than
- | the old one - if not, we output some blanks. "n" is the number of
- | newlines at the end, or zero for no newline but carriage return.
- **/
-
- va_start(vl, fmt);
- nc = vfprintf(stdout, fmt, vl);
- va_end(vl);
- length -= nc;
- if (length > 0) fprintf(stdout, "%*s", length, " ");
- if (n) {
- while (n--) fprintf(stdout, "\n");
- length = 0;
- } else {
- fprintf(stdout, "\r");
- length = nc;
- }
- }
-
- void readCyl(
- int cyl,
- int hd
- ){
- LONG offset;
-
- diskReq->iotd_Req.io_Length = TD_CYL;
- diskReq->iotd_Req.io_Data = (APTR) diskBuffer;
- diskReq->iotd_Req.io_Command = ETD_READ;
- diskReq->iotd_Count = diskChangeCount;
- offset = TD_SECTOR * (NUMSECS * (hd + NUMHEADS * cyl));
- diskReq->iotd_Req.io_Offset = offset;
- DoIO(diskReq);
- }
-
- void seekFullRange(
- SHORT howmany
- ){
- int i;
- SHORT error;
-
- for (i=1; i<=howmany; i++) {
- diskReq->iotd_Req.io_Offset =
- ((NUMCYLS - 1) * NUMSECS * NUMHEADS - 1) * TD_SECTOR;
- diskReq->iotd_Req.io_Command = TD_SEEK;
- DoIO(diskReq);
- if (error = diskReq -> iotd_Req.io_Error) {
- fprintf(stdout, "\nSeek cycle %d, error 0x%X ...\n", i, error);
- cleanup(SYS_ABORT_CODE);
- }
-
- diskReq->iotd_Req.io_Offset = 0;
- diskReq->iotd_Req.io_Command = TD_SEEK;
- DoIO(diskReq);
- if (error = diskReq->iotd_Req.io_Error) {
- fprintf(stdout, "\nSeek cycle %d, error 0x%X ...\n", i, error);
- cleanup(SYS_ABORT_CODE);
- }
- }
- fprintf(stdout, "no errors detected seeking over full disk range.\n");
- }
-
- void syntax(void)
- {
- fprintf(stdout,
- "\n\tUsage:\t\tDT DFn, where 'n' (0-4) is the drive number.\n");
- fprintf(stdout,
- "\tPurpose:\tDisk test.\n\n");
- cleanup(SYS_NORMAL_CODE);
- }
-