Path: utzoo!mnetor!uunet!husc6!purdue!i.cc.purdue.edu!j.cc.purdue.edu!ain From: ain@j.cc.purdue.edu (Patrick White) Newsgroups: comp.sources.amiga Subject: MRBackup (part 3 of 4) Message-ID: <6292@j.cc.purdue.edu> Date: 28 Jan 88 16:27:14 GMT Organization: PUCC Land, USA Lines: 2138 Keywords: MRBackup, untested, source, part 3 of 4. Approved: ain@j.cc.purdue.edu (Pat White) Program Name: MRBackup Submitted By: uiucdcs!amanpt1.ZONE1.COM!mrr@ee.ecn.purdue.edu (Mark Rinfret) Summary: A hard disk backup utility. Poster Boy: Pat White (ain@j.cc.purdue.edu) Untested. NOTES: I reshar'ed all of the source to get rid of some explicit path references in where the files get put. Now it will unshar on unix and the Amiga into the current directory. I did *not* change the explicit path references to include files in the .c files. I also included the docs that were sent with the binary version, so these 4 parts are complete source with docs. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # Console.c # CopyFile.c # DateRequest.c # DiskMisc.c # Error.c # FileMisc.c # FormatDisk.c # This archive created: Thu Jan 28 11:10:10 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting Console.c '(3138 characters)' cat << \SHAR_EOF > Console.c /* MRBackup Console Routines * Filename: Console.c * Date: 11/22/87 * * Console I/O Routines from Rob Peck's "Programmer's Guide to the Amiga". */ #include "MRBackup.h" ConIOBlocks * CreateConsole(window) struct Window *window; { ConIOBlocks *c; struct MsgPort *tpw; if (!(c = AllocMem((long) sizeof(ConIOBlocks), MEMF_CLEAR | MEMF_PUBLIC))) goto cleanup1; if (!(tpw = CreatePort(0L, 0L))) goto cleanup2; if (!(c->tpr = CreatePort(0L, 0L))) goto cleanup3; if (!(c->writeReq = CreateStdIO(tpw))) goto cleanup4; if (!(c->readReq = CreateStdIO(c->tpr))) goto cleanup5; c->writeReq->io_Data = (APTR)window; c->writeReq->io_Length = sizeof(struct Window); if (OpenDevice("console.device", 0L, c->writeReq, 0L)) goto cleanup6; /* Read and write are both talking to the same instance of a console. */ c->readReq->io_Device = c->writeReq->io_Device; c->readReq->io_Unit = c->writeReq->io_Unit; return c; cleanup6: DeleteStdIO(c->readReq); cleanup5: DeletePort(c->tpr); cleanup4: DeleteStdIO(c->writeReq); cleanup3: DeletePort(tpw); cleanup2: FreeMem(c, (long) sizeof(ConIOBlocks)); cleanup1: return NULL; } int DeleteConsole(c) ConIOBlocks *c; { struct MsgPort *mp; AbortIO(c->readReq); /* abort any read in progress */ CloseDevice(c->writeReq); /* close the console device */ mp = c->writeReq->io_Message.mn_ReplyPort; DeleteStdIO(c->writeReq); DeletePort(mp); mp = c->readReq->io_Message.mn_ReplyPort; DeleteStdIO(c->readReq); DeletePort(mp); FreeMem(c, (long) sizeof(ConIOBlocks)); return 0; } #define CONREAD c->readReq #define CONWRITE c->writeReq void EnqueueRead(c, location) ConIOBlocks *c; char *location; { struct IOStdReq *conr; conr = CONREAD; conr->io_Command = CMD_READ; conr->io_Length = 1; conr->io_Data = (APTR) location; SendIO(conr); /* asynchronous read request */ } /* Write a specified number of characters from a buffer to a particular * console device. */ void ConWrite(c, data, length) ConIOBlocks *c; char *data; WORD length; { struct IOStdReq *conw; if (length == 0) length = strlen(data); conw = CONWRITE; conw->io_Command = CMD_WRITE; conw->io_Length = length; conw->io_Data = (APTR) data; DoIO(conw); /* synchronous write request */ } /* Get a character from the console, with optional wait. * Called with: * c: console control structure * wait: 0 => asynchronous read (no wait) * 1 => synchronous read (wait) * Returns: * character or -1 (async and no character) */ int CGetCharacter(c, wait) ConIOBlocks *c; BOOL wait; { struct MsgPort *mp; struct IOStdReq *conr; char *dataAddr; int temp; mp = c->tpr; if (wait) { WaitPort(mp); } conr = (struct IOStdReq *) GetMsg(mp); if (conr == NULL) return -1; else { dataAddr = (char *)conr->io_Data; temp = *dataAddr; /* get the value */ EnqueueRead(c, dataAddr); /* continue the read */ return temp; } } #ifdef DEBUG DebugWrite(msg) char *msg; { ConWrite(debugConsole, msg, strlen(msg)); } #endif /* Write string to progress window. */ WriteConsole(msg) char *msg; { ConWrite(progressConsole, msg, strlen(msg)); } SHAR_EOF if test 3138 -ne "`wc -c Console.c`" then echo shar: error transmitting Console.c '(should have been 3138 characters)' fi echo shar: extracting CopyFile.c '(2405 characters)' cat << \SHAR_EOF > CopyFile.c /* MRBackup: File Copy Routine. * Date: 09/04/87 * Notes: * To enhance the performance of MRBackup, this package was copied * from my Misc library and modified to couple it more tightly with * MRBackup. It now uses a global buffer area allocated during * initialization. * * History: (most recent change first) * * 09/04/87 -MRR- CopyFile, upon failure, now returns the error status * code from IoErr(). */ #include "MRBackup.h" /* * Copy file, preserving date. * Depends upon file date routines in FileMisc.c * Original author: Jeff Lydiatt, Vancouver, Canada */ #include #include #include #include #include #define MAXSTR 127 extern long Chk_Abort(); extern BOOL GetFileDate(), SetFileDate(); extern long IoErr(); /* Copy the last modified date from one file to another. * Called with: * from: name of source file * to: name of destination file * Returns: * 0 => success, 1 => failure * Note: * Dynamic memory allocation of the DateStamp struction is * necessary to insure longword alignment. */ BOOL CopyFileDate(from,to) char *from, *to; { struct DateStamp *date; int status = 1; /* default is fail code */ if (date = (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC)) { if (GetFileDate(from,date)) if (SetFileDate(to,date)) status = 0; FreeMem(date, (long) sizeof(struct DateStamp)); } return status; } int CopyFile(from, to) char *from, *to; { long status, count; struct FileHandle *fin = NULL, *fout = NULL; #ifdef DEBUG char errmsg[256]; static char *errfmt = "CopyFile I/O error %ld, file %s\n"; #endif if (! (fin = Open(from, MODE_OLDFILE) ) ) { badcopy: status = IoErr(); #ifdef DEBUG sprintf(errmsg, errfmt, status, from); print_err: DebugWrite(errmsg); #endif if (fin) Close(fin); if (fout) { Close(fout); unlink(to); /* delete the bad copy */ } return (int) status; } if ( !(fout = Open(to, MODE_NEWFILE)) ) goto badcopy; status = 0; while ( !status && (count = Read( fin, buffer, bufSize )) == bufSize ) if ( Write(fout, buffer, count) != count) status = IoErr(); if (!status && count > 0 ) { if (Write(fout, buffer, count) != count) status = IoErr(); } if (status) goto badcopy; Close(fin); Close(fout); return CopyFileDate(from, to); } SHAR_EOF if test 2405 -ne "`wc -c CopyFile.c`" then echo shar: error transmitting CopyFile.c '(should have been 2405 characters)' fi echo shar: extracting DateRequest.c '(21886 characters)' cat << \SHAR_EOF > DateRequest.c /* Date Requester Package * Author: Mark R. Rinfret * Description: * This source file contains a canned date requester routine which * supports time and date entry in MM/DD/YY HH:MM:SS notation (time is * optional) to a DateStamp structure. This package is dependent upon * the package "MRDates.c" (same author) for DateStamp/string conversions. * * History: (most recent change first) * * 08/18/87 -MRR- Added up/down arrows to gadgetry * 07/20/87 -MRR- Created this file. */ #include #include #include #include #include #include #include #include #include #include <:src/lib/MRDates.h> #define DATEREQWIDTH 260 #define DATEREQHEIGHT 80 /********************************************************************** * Gadget Structure Definitions * * Some of the following structures were defined using EGAD! * (by the Programmer's Network) and further modified by the author. * **********************************************************************/ /* Gadget ID Definitions */ #define DATEGAD 0 #define UPMONTHGAD 1 #define UPDAYGAD 2 #define UPYEARGAD 3 #define UPHOURGAD 4 #define UPMINGAD 5 #define UPSECGAD 6 #define DOWNMONTHGAD 7 #define DOWNDAYGAD 8 #define DOWNYEARGAD 9 #define DOWNHOURGAD 10 #define DOWNMINGAD 11 #define DOWNSECGAD 12 #define NOWGAD 13 #define OKGAD 14 /********************************************************************** * Text attribute structures used in rendering IntuiTexts **********************************************************************/ static char def_font[] ="topaz.font"; static struct TextAttr TxtAt_Plain = { (UBYTE *)def_font, 8, FS_NORMAL, FPF_ROMFONT }; /********************************************************************** * String information for the dategad string gadget. **********************************************************************/ static UBYTE dategad_sbuf_1[19] = "00/00/00 00:00:00"; static UBYTE dategad_ubuf_1[19]; static struct StringInfo dategad_txstr_1 = { dategad_sbuf_1, dategad_ubuf_1, /* Buffer, UndoBuffer */ 0, 18, 0, /* BufferPos, MaxChars, DispPos */ 0, 18, /* UndoPos, NumChars */ 0, 0, 0, /* DispCount, CLeft, CTop */ 0x0, 0, /* LayerPtr, LongInt */ 0x0 /* AltKeyMap */ }; /********************************************************************** * Gadget Structure definition for the dategad gadget. **********************************************************************/ static struct Gadget dategad = { NULL, /* NextGadget pointer */ 64, 50, /* LeftEdge, TopEdge */ 8 * 17, /* Width (8 pixels * 17 characters) */ 8, /* Height */ GADGHCOMP, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | STRGADGET, /* GadgetType */ NULL, /* GadgetRender - no border */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ (APTR)&dategad_txstr_1, /* SpecialInfo */ DATEGAD, /* GadgetID */ NULL /* UserData Pointer */ }; static struct IntuiText nowtext = { 1, 0, /* FrontPen / BackPen */ JAM2, /* DrawMode */ 0, /* LeftEdge */ 0, /* TopEdge */ &TxtAt_Plain, /* ITextFont */ (UBYTE *) "NOW", /* IText */ NULL /* NextText */ }; static struct Gadget nowgad = { &dategad, /* NextGadget pointer */ 220, 50, /* LeftEdge, TopEdge */ 24, 8, /* Width, Height */ GADGHCOMP, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ NULL, /* GadgetRender */ NULL, /* SelectRender */ &nowtext, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ NOWGAD, /* GadgetID */ NULL /* UserData Pointer */ }; static struct IntuiText oktext = { 1, 0, /* FrontPen / BackPen */ JAM2, /* DrawMode */ 0, /* LeftEdge */ 0, /* TopEdge */ &TxtAt_Plain, /* ITextFont */ (UBYTE *) "OK", /* IText */ NULL /* NextText */ }; static struct Gadget okgad = { &nowgad, /* NextGadget pointer */ 30, 50, /* LeftEdge, TopEdge */ 16, 8, /* Width, Height */ GADGHNONE, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ NULL, /* GadgetRender */ NULL, /* SelectRender */ &oktext, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ OKGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /* These coordinate pairs define the border of the up-arrow gadgets. */ static SHORT upborder_pairs[] = { 7, 0, 14, 7, 0, 7, 7, 0 }; /* The up-arrow border definition. */ static struct Border upborder = { -1, -1, /* LeftEdge, TopEdge */ 1, 2, /* FrontPen, BackPen */ JAM1, /* DrawMode */ 4, /* number of pairs */ (SHORT *) &upborder_pairs, NULL /* NextBorder */ }; /* These coordinate pairs define the border of the down-arrow gadgets. */ static SHORT downborder_pairs[] = { 0, 0, 14, 0, 7, 7, 0, 0 }; /* The down-arrow border definition. */ static struct Border downborder = { -1, -1, /* LeftEdge, TopEdge */ 1, 2, /* FrontPen, BackPen */ JAM1, /* DrawMode */ 4, /* number of pairs */ (SHORT *) &downborder_pairs, NULL /* NextBorder */ }; /********************************************************************** * Gadget Structure definition for the upsec gadget. **********************************************************************/ /* Each component of the date and time can be incremented/decremented * by clicking on the appropriate up or down arrow gadgets. */ static struct Gadget downsecgad = { &okgad, /* NextGadget pointer */ 184, 60, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &downborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ DOWNSECGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upmin gadget. **********************************************************************/ static struct Gadget downmingad = { &downsecgad, /* NextGadget pointer */ 160, 60, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &downborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ DOWNMINGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the uphour gadget. **********************************************************************/ static struct Gadget downhourgad = { &downmingad, /* NextGadget pointer */ 136, 60, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &downborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ DOWNHOURGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upyear gadget. **********************************************************************/ static struct Gadget downyeargad = { &downhourgad, /* NextGadget pointer */ 112, 60, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &downborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ DOWNYEARGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upday gadget. **********************************************************************/ static struct Gadget downdaygad = { &downyeargad, /* NextGadget pointer */ 88, 60, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &downborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ DOWNDAYGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upmonth gadget. **********************************************************************/ static struct Gadget downmonthgad = { &downdaygad, /* NextGadget pointer */ 64, 60, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ /* Gadget Flags */ NULL, RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &downborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ DOWNMONTHGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upsec gadget. **********************************************************************/ static struct Gadget upsecgad = { &downmonthgad, /* NextGadget pointer */ 184, 40, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &upborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ UPSECGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upmin gadget. **********************************************************************/ static struct Gadget upmingad = { &upsecgad, /* NextGadget pointer */ 160, 40, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &upborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ UPMINGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the uphour gadget. **********************************************************************/ static struct Gadget uphourgad = { &upmingad, /* NextGadget pointer */ 136, 40, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &upborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ UPHOURGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upyear gadget. **********************************************************************/ static struct Gadget upyeargad = { &uphourgad, /* NextGadget pointer */ 112, 40, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &upborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ UPYEARGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upday gadget. **********************************************************************/ static struct Gadget updaygad = { &upyeargad, /* NextGadget pointer */ 88, 40, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ NULL, /* Gadget Flags */ RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &upborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ UPDAYGAD, /* GadgetID */ NULL /* UserData Pointer */ }; /********************************************************************** * Gadget Structure definition for the upmonth gadget. **********************************************************************/ static struct Gadget upmonthgad = { &updaygad, /* NextGadget pointer */ 64, 40, /* LeftEdge, TopEdge */ 15, 8, /* Width, Height */ /* Gadget Flags */ NULL, RELVERIFY , /* Activation Flags */ REQGADGET | BOOLGADGET, /* GadgetType */ (APTR) &upborder, /* GadgetRender */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ NULL, /* SpecialInfo */ UPMONTHGAD, /* GadgetID */ NULL /* UserData Pointer */ }; static struct Requester daterequest; /* requester for the date */ /* Date requester border 2 coordinate pairs. */ static SHORT datereq_pairs2[] = { 8, 4, DATEREQWIDTH - 8, 4, DATEREQWIDTH - 8, DATEREQHEIGHT - 4, 8, DATEREQHEIGHT - 4, 8, 4 }; /* Date requester border 2 definition */ static struct Border datereq_bord2 = { -1, -1, /* LeftEdge, TopEdge */ 0, 2, JAM2, /* FrontPen, BackPen, DrawMode*/ 5, /* Count of XY pairs */ (SHORT *)&datereq_pairs2, /* XY pairs */ NULL /* Next Border */ }; /* Date requester border 1 coordinate pairs. */ static SHORT datereq_pairs1[] = { 4, 2, DATEREQWIDTH - 4, 2, DATEREQWIDTH - 4, DATEREQHEIGHT - 2, 4, DATEREQHEIGHT - 2, 4, 2 }; /* Date requester border 1 definition. */ static struct Border datereq_bord1 = { -1, -1, /* LeftEdge, TopEdge */ 0, 2, JAM2, /* FrontPen, BackPen, DrawMode*/ 5, /* Count of XY pairs */ (SHORT *)&datereq_pairs1, /* XY pairs */ &datereq_bord2 /* Next Border */ }; /* This is the definition for the prompt string (user-supplied) which * appears in the requester. */ static struct IntuiText datereqtext = { 1, 0, /* FrontPen / BackPen */ JAM2, /* DrawMode */ 20, /* LeftEdge */ 15, /* TopEdge */ &TxtAt_Plain, /* ITextFont */ NULL, /* IText */ NULL /* NextText */ }; static initialized = 0; /* set to 1 after initialization */ static InitDateRequest() { InitRequester(&daterequest); daterequest.LeftEdge = 60; daterequest.TopEdge = 10; daterequest.Width = DATEREQWIDTH; daterequest.Height = DATEREQHEIGHT; daterequest.ReqGadget = &upmonthgad; daterequest.ReqText = &datereqtext; daterequest.ReqBorder = &datereq_bord1; daterequest.BackFill = 2; ++initialized; } /* Request a date from the user. * Called with: * window: pointer to window structure * prompt: string to be used as the prompt text * default_date: pointer to default date or NULL * date: pointer to date result (returned) * Returns: * status code: 0 => success, 1 => failure * (actually, always returns 0 - can't leave without good date) */ DateRequest(window,prompt,default_date,date) struct Window *window; char *prompt; struct DateStamp *default_date,*date; { ULONG class; /* message class */ USHORT code; /* message code */ struct Gadget *gadget; /* pointer to gadget affected */ USHORT gadgid; /* gadget ID */ struct IntuiMessage *msg; /* Intuition message pointer */ UnpackedDS upd; /* unpacked version of date */ SHORT x,y; /* mouse x and y position */ if (!initialized) InitDateRequest(); datereqtext.IText = (UBYTE *) prompt; if (default_date) /* write default date in requester? */ DS2Str(dategad_sbuf_1,"%02m/%02d/%02y %02h:%02n:%02s", default_date); else *dategad_sbuf_1 = '\0'; Request(&daterequest, window); for (;;) { Wait(1L << window->UserPort->mp_SigBit); while (msg = (struct IntuiMessage *) GetMsg(window->UserPort)) { class = msg->Class; code = msg->Code; gadget = (struct Gadget *) msg->IAddress; x = msg->MouseX; y = msg->MouseY; ReplyMsg(msg); /* acknowledge the message */ switch (class) { case REQSET: ActivateGadget(&dategad,window,&daterequest); break; case GADGETUP: gadgid = gadget->GadgetID; if (gadgid == NOWGAD) DateStamp(date); else if (gadgid == OKGAD) gadgid = DATEGAD; UnpackDS(date, &upd); switch (gadgid) { case DATEGAD: if ( ! Str2DS(dategad_sbuf_1, date) ) { EndRequest(&daterequest, window); return 0; } else DisplayBeep(window->WScreen); /* bad conversion */ break; case UPYEARGAD: ++upd.year; break; case DOWNYEARGAD: if (upd.year > 1978) --upd.year; break; case UPMONTHGAD: if (++upd.month > 12) upd.month = 1; break; case DOWNMONTHGAD: if (--upd.month < 1) upd.month = 12; break; case UPDAYGAD: if (upd.day < 31) ++upd.day; break; case DOWNDAYGAD: if (upd.day > 1) --upd.day; break; case UPHOURGAD: if (++upd.hour > 23) upd.hour = 0; break; case DOWNHOURGAD: if (--upd.hour < 0) upd.hour = 23; break; case UPMINGAD: if (++upd.minute > 59) upd.minute = 0; break; case DOWNMINGAD: if (--upd.minute < 0) upd.minute = 59; break; case UPSECGAD: if (++upd.second > 59) upd.second = 0; break; case DOWNSECGAD: if (--upd.second < 0) upd.second = 59; break; default: break; } /* end switch(gadgid) */ /* Reformat the new date value. */ PackDS(date, &upd); if (upd.year) DS2Str(dategad_sbuf_1,"%02m/%02d/%02y %02h:%02n:%02s", date); else strcpy(dategad_sbuf_1,"00/00/00 00:00:00"); RefreshGadgets(&dategad, window, &daterequest); break; default: break; /* ignore the rest */ } /* end switch(class) */ } } } /*#define DEBUG */ #ifdef DEBUG /* --- Only compiled in the debug version --- */ #include /* New window structure */ struct NewWindow newwindow = { 0,0,640,200,0,1, /* IDCMP Flags */ MOUSEMOVE | MENUPICK | MOUSEBUTTONS | CLOSEWINDOW | GADGETDOWN | GADGETUP | REQSET, /* Flags */ WINDOWCLOSE | WINDOWDEPTH | ACTIVATE | RMBTRAP | REPORTMOUSE, NULL, /* First gadget */ NULL, /* Checkmark */ (UBYTE *)"Date Requester Test Program", /* Window title */ NULL, /* No custom streen */ NULL, /* Not a super bitmap window */ 0,0,640,200, /* Not used, but set up anyway */ WBENCHSCREEN }; struct IntuitionBase *IntuitionBase; struct Window *mywindow; struct DateStamp *ds; static struct IntuiText MoreText = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ JAM2, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ AUTOITEXTFONT, /* ITextFont */ (UBYTE *) "Want to play some more?", /* IText */ NULL /* NextText */ }; static struct IntuiText YesText = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ AUTODRAWMODE, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ AUTOITEXTFONT, /* ITextFont */ (UBYTE *) "Sure!", /* IText */ NULL /* NextText */ }; static struct IntuiText NoText = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ JAM2, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ AUTOITEXTFONT, /* ITextFont */ (UBYTE *) "Nope!", /* IText */ NULL /* NextText */ }; main() { short keep_going; if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",33L))) { puts("Failed to open Intuition library!"); exit(1); } ds = (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC); DateStamp(ds); /* get current date/time */ mywindow = OpenWindow(&newwindow); do { DateRequest(mywindow, "Enter date and time", ds, ds); keep_going = AutoRequest(mywindow, &MoreText, &YesText, &NoText, NULL, NULL, 220L, 50L); } while (keep_going); if (mywindow) CloseWindow(mywindow); if (IntuitionBase) CloseLibrary(IntuitionBase); } #endif SHAR_EOF if test 21886 -ne "`wc -c DateRequest.c`" then echo shar: error transmitting DateRequest.c '(should have been 21886 characters)' fi echo shar: extracting DiskMisc.c '(8658 characters)' cat << \SHAR_EOF > DiskMisc.c /* DiskMisc.c - miscellaneous disk support routines. * Mark Rinfret (et al), 1987 * * History: (most recent change first) * * 12/15/87 -MRR- Added two new routines, FindDevice and GetVolumeName. * These are based largely on the "Info" program by * Chuck McManis. * * 11/24/87 -MRR- The routine "DiskBlocks" was changed to "DiskBlocksLeft". * A new routine, "TotalDiskBlocks", returns the capacity, * in disk blocks, of the drive associated with a pathname. * A new routine, "GetDiskInfo", returns InfoData on a given * pathname. */ #include #include #include #include #include #include #include #include #include #include #include #include ":src/lib/DiskMisc.h" extern LONG sendpkt(); static int errCode; extern struct DosLibrary *DOSBase; /* These are some macros that help in dealing with BCPL pointers and strings * the first is macro converts a BPTR to a C pointer of type struct DeviceList * * The second two provide the length of a BSTR * and a pointer to it's text. */ /* Convert BCPL DeviceList pointer to C pointer. */ #define DLPTR(x) ((struct DeviceList *)BADDR(x)) /* Get the length of a BCPL string. */ #define LENGTH(x) (unsigned) (*(UBYTE *)BADDR(x)) /* Get address of BCPL string, adjusted for leading length byte. */ #define STRING(x) (((char *)BADDR(x))+1) ^L /* * Find the first device node for a specified device type. * Called with: * dList: device list * dType: device type mnemonic * Returns: * pointer to device node or NULL * * Note: by passing the dl_Next field on successive calls, you may scan * the entire device list. */ struct DeviceList * FindDevice(dList, dType) struct DeviceList *dList; /* Pointer to a device list structure */ long dType; /* A device type as defined in dos.h */ { struct DeviceList *t; /* A temporary pointer */ for (t = dList; ((t != NULL) && (t->dl_Type != dType)); t = DLPTR(t->dl_Next)); return(t); } char * GetVolumeName(deviceName, volumeName) char *deviceName, *volumeName; { struct RootNode *rootNode; struct DeviceList *devList, *t, *t2; struct DeviceNode *devNode; struct DosInfo *dosInfo; char dName[31]; int i, nameLength; struct InfoData *info; struct Process *myProcess; APTR savedWindow; struct Lock *l; char *vName = NULL; /* set non-null on success */ *volumeName = '\0'; /* initialize name to null */ /* Make a copy of the device name string. */ strncpy(dName, deviceName, sizeof(dName)-1); /* Make sure that the device name is not colon-terminated. Also * insure that the device name is all upper case. */ nameLength = strlen(dName); for (i = 0; i < nameLength; ++i) { if (dName[i] == ':') { dName[i] = '\0'; break; } else dName[i] = toupper(dName[i]); } nameLength = strlen(dName); /* Get device name length. */ if (! (info = (struct InfoData *) AllocMem((long) sizeof(struct InfoData), MEMF_PUBLIC|MEMF_CLEAR))) { return vName; /* Will be NULL if unsuccessful. */ } /* Get the DOS root node. */ rootNode = (struct RootNode *)DOSBase->dl_Root; /* Get the DOS info node. */ dosInfo = (struct DosInfo *)BADDR(rootNode->rn_Info); /* devList becomes the anchor point that we always start from */ devList = (struct DeviceList *)BADDR(dosInfo->di_DevInfo); /* Disable requesters if no disk present */ myProcess = (struct Process *) FindTask(NULL); savedWindow = myProcess->pr_WindowPtr; myProcess->pr_WindowPtr = (APTR) -1L; for (t = FindDevice(DLPTR(dosInfo->di_DevInfo), DLT_DEVICE); t != NULL; t = FindDevice(DLPTR(t->dl_Next), DLT_DEVICE)) { devNode = (struct DeviceNode *) t; /* A non-null task pointer indicates a disk device. */ if (devNode->dn_Task) { #ifdef DEBUG char tempString[31]; strncpy(tempString, STRING(devNode->dn_Name), LENGTH(devNode->dn_Name) ); printf("Testing %s\n", tempString); #endif if (!strncmp(dName, STRING(devNode->dn_Name), MAX(LENGTH(devNode->dn_Name),nameLength) ) ) { /* We've found a match! Now, add a terminating colon to the * device name so we can pass it to Lock. */ dName[nameLength++] = ':'; dName[nameLength] = '\0'; #ifdef DEBUG printf("Matched %s\n", deviceName); #endif l = (struct Lock *) Lock(dName, ACCESS_READ); if (l) { /* disk inserted? */ Info(l, info); t2 = DLPTR(info->id_VolumeNode); if (t2 != NULL) { strncpy(volumeName, STRING(t2->dl_Name), LENGTH(t2->dl_Name) ); volumeName[LENGTH(t2->dl_Name)] = '\0'; } #ifdef DEBUG else DebugWrite("Null volume name!\n"); #endif UnLock(l); } #ifdef DEBUG else printf("Unable to lock %s!\n", dName); #endif vName = volumeName; /* set 'success' */ break; } } /* end of disk device test */ } /* end for */ myProcess->pr_WindowPtr = savedWindow; /* restore window pointer */ cleanup: if (info) FreeMem(info, (long) sizeof(struct InfoData)); return vName; } /* This routine returns the number of disk blocks remaining on the * drive specified by 'name'. Though 'name' would typically be the * drive name or volume name, it can also be the name of any file * on the disk drive. * Called with: * name: disk device or volume name * Returns: * > 0 => number of blocks available * < 0 => error status */ LONG DiskBlocksLeft(name) char *name; { LONG blocks = -1L; struct InfoData *info = NULL; if ( !( info = GetDiskInfo(name) ) ) return -errCode; blocks = info->id_NumBlocks - info->id_NumBlocksUsed; FreeMem(info, (long) sizeof(struct InfoData)); return blocks; /* bad status indicator */ } /* Get disk info, given a pathname. * Called with: * name: file pathname * Returns: * a pointer to an InfoData structure * Note: * It is the user application's responsibility to free the memory * allocated for the InfoData structure. */ struct InfoData * GetDiskInfo( name ) char *name; { struct InfoData *info = NULL; struct FileLock *lock = NULL; errCode = 0; if (lock = (struct FileLock *) Lock(name, ACCESS_READ)) { if (info = AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC)) { if ( ! Info(lock,info)) errCode = IoErr(); } else errCode = ERROR_NO_FREE_STORE; UnLock(lock); } else errCode = IoErr(); if (errCode) { if (info) FreeMem( info, (long) sizeof( struct InfoData ) ); info = NULL; } return info; } /* Disk ACTION_INHIBIT support routine. * Author: Mark R. Rinfret * Date: 06/29/87 * * This routine provides support for user-written disk formatting, copy * operations which benefit from suppressing/restoring disk validation. */ int Inhibit(drivename, code) char *drivename; int code; { struct MsgPort *task; LONG arg[2]; LONG rc; if (!(task=(struct MsgPort *) DeviceProc(drivename))) return 1; /* fail, darn it! */ arg[0] = code; /* Now, cross all your fingers and toes... */ return ( !sendpkt(task,ACTION_INHIBIT,arg,1)); } /* This routine returns the total number of disk blocks on the * drive specified by 'name'. Though 'name' would typically be the * drive name or volume name, it can also be the name of any file * on the disk drive. * Called with: * name: disk device, volume or path name * Returns: * > 0 => total number of blocks on drive * < 0 => error status */ LONG TotalDiskBlocks(name) char *name; { struct InfoData *info = NULL; long int blocks = -1L; if ( ! ( info = GetDiskInfo(name) ) ) return -errCode; blocks = info->id_NumBlocks; FreeMem(info, (long) sizeof(struct InfoData)); return blocks; /* bad status indicator */ } #ifdef DEBUG main() { long blocks; char deviceName[81], volumeName[81]; if ((blocks = TotalDiskBlocks("df0:")) < 0) { printf("Bad status from TotalDiskBlocks() => %ld\n", -blocks); exit(); } else printf("Total disk blocks on DF0: => %ld\n", blocks); if ( (blocks = DiskBlocksLeft("df0:") ) < 0) printf("Bad status from DiskBlocks() => %ld\n", -blocks); else printf("Disk blocks left on df0: => %ld\n",blocks); for (;;) { puts("Enter a disk DEVICE name (dh0, df0, etc.)."); puts("Just hit RETURN to quit."); gets(deviceName); if (*deviceName == '\0') break; if (!GetVolumeName(deviceName, volumeName)) puts("Sorry - I couldn't find that device in my system."); else printf("The volume name is %s\n",volumeName); } } #endif SHAR_EOF if test 8658 -ne "`wc -c DiskMisc.c`" then echo shar: error transmitting DiskMisc.c '(should have been 8658 characters)' fi echo shar: extracting Error.c '(2495 characters)' cat << \SHAR_EOF > Error.c /* MRBackup Error handling routines. * Filename: Error.c * Date: 11/20/87 * * History: (most recent change first) * * 11/20/87 -MRR- V1.4 This package was created, along with ErrorRequest.c, * to provide extended error handling features. */ #include "MRBackup.h" #include "Gadget.h" struct Requester RequesterStructure2; /* Get an error handling option. This is done by putting up a requester * and waiting for the user to select one of the option gadgets. * Called with: * flags: error recovery flags * The flags are various ERR_ codes, OR'ed together. For example, * ERR_ABORT | ERR_RETRY_FILE | ERR_IGNORE * would give the option of allowing the user to abort the * operation, retry the current file or simply ignore the error. * Returns: * error recovery code (ERR_ABORT, ERR_RETRY_FILE, etc.) */ GetErrOpt(flags) unsigned flags; { ULONG class; unsigned enable; struct Gadget *gadget; struct IntuiMessage *msg; int status = ERR_ABORT; if (!flags) flags = ERR_ABORT; for (gadget = RequesterStructure2.ReqGadget; gadget; gadget = gadget->NextGadget) { switch (gadget->GadgetID) { case ABORT: enable = flags & ERR_ABORT; break; case FILERETRY: enable = flags & ERR_RETRY_FILE; break; case DISKRESTART: enable = flags & ERR_RESTART_VOLUME; break; case FILESKIP: enable = flags & ERR_IGNORE; break; default: /* Some other gadgetry; default to enabled. */ enable = 1; } if (enable) gadget->Flags &= ~GADGDISABLED; else gadget->Flags |= GADGDISABLED; } RequesterStructure2.LeftEdge = 5; RequesterStructure2.TopEdge = 15; if (!Request(&RequesterStructure2, mainWindow)) { TypeAndSpeak("I could not put up my error requester.\n"); TypeAndSpeak("I will have to abort this operation.\n"); status = ERR_ABORT; } else { WindowToFront(mainWindow); for (class = 0; class != GADGETDOWN; ) { Wait(1L << mainWindow->UserPort->mp_SigBit); msg = (struct IntuiMessage *) GetMsg(mainWindow->UserPort); if (msg) { class = msg->Class; gadget = (struct Gadget *) msg->IAddress; ReplyMsg(msg); } } switch (gadget->GadgetID) { case ABORT: status = ERR_ABORT; break; case FILERETRY: status = ERR_RETRY_FILE; break; case DISKRESTART: status = ERR_RESTART_VOLUME; break; case FILESKIP: status = ERR_IGNORE; break; default: TypeAndSpeak("I have a bug in my error requester!\n"); } } WindowToBack(mainWindow); return status; } SHAR_EOF if test 2495 -ne "`wc -c Error.c`" then echo shar: error transmitting Error.c '(should have been 2495 characters)' fi echo shar: extracting FileMisc.c '(4940 characters)' cat << \SHAR_EOF > FileMisc.c /* File date routines. * Filename: FileDates.c * History: (most recent change first) * * 01/01/88 -MRR- Happy new year! Added a new function, CompareFileDates. * 09/24/87 -MRR- SetFileDate was allocating a BSTR of 68 bytes, rather * than using the length of the file name string. I don't * have the foggiest notion why (that was DUMB!). */ #include "exec/types.h" #include "exec/ports.h" #include "exec/io.h" #include "exec/memory.h" #include "libraries/dosextens.h" #include #define AZTEC 1 #ifdef AZTEC #include "functions.h" /* aztec C include */ #endif #define ACTION_SETDATE_MODE 34L /* Set creation date on file */ #define DOSTRUE -1L /* AmigaDos TRUE */ #define MAXARGS 7L /* limit in packet structure (dosextens.h) */ #define NARGS 4L /* Number of args for setdate */ long sendpkt(); /* Function: * CompareFileDates * * Called with: * name1, name2: filenames for which dates are to be compared * * Returns: * 0 => dates are equal or both files don't exist * -1 => date of < date of or doesn't exist * 1 => date of > date of or doesn't exist * * Description: * CompareFileDates attempts to compare the file creation/modification * dates of two files. */ int CompareFileDates(name1, name2) char *name1, *name2; { struct DateStamp d1, d2; GetFileDate(name1, &d1); GetFileDate(name2, &d2); return CompareDS(&d1, &d2); } ^L /* Function: * GetFileDate * * Called with: * name: file name * date: pointer to DateStamp structure * * Returns: * result: 1 => got a date, 0 => didn't * * Description: * GetFileDate attempts to get the creation/modification date * of a file (unfortunately, they're one and the same) and stores * it into the location pointed to by . If the file doesn't * exist or for some reason the date can't be obtained, * is set to zeros and a zero is returned. Otherwise, is set * to the file date and a 1 is returned. */ BOOL GetFileDate(name, date) char *name; struct DateStamp *date; { struct FileInfoBlock *Fib; ULONG FLock; int result = FALSE; register struct DateStamp *d; if ((FLock = (ULONG) Lock(name,(long)(ACCESS_READ)))== NULL) goto exit1; Fib = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock), (long)(MEMF_CHIP|MEMF_PUBLIC)); if (Fib == NULL ) result = FALSE; else{ if (!Examine(FLock, Fib )) { result = FALSE; } else if (Fib->fib_DirEntryType > 0 ) result = FALSE; /* It's a directory */ else{ d = &Fib->fib_Date; date->ds_Days = d->ds_Days; date->ds_Minute = d->ds_Minute; date->ds_Tick = d->ds_Tick; result = TRUE; } FreeMem((void *)Fib,(long)sizeof(struct FileInfoBlock)); } UnLock(FLock); exit1: if (! result ) { date->ds_Days = 0; date->ds_Minute = 0; date->ds_Tick = 0; } return result; } ^L /* Function: * IsDir * * Called with: * name: pathname specification * * Returns: * 0 => no * 1 => yes * <0 => - * * Description: * * Examine a pathname to determine if it is a device or directory name. */ int IsDir(name) char *name; { struct FileInfoBlock *FIB = NULL; struct Lock *lock = NULL; int status; if (!(FIB = AllocMem((long)sizeof(struct FileInfoBlock), MEMF_CHIP|MEMF_CLEAR))) { return -ERROR_NO_FREE_STORE; } if (!(lock = (struct Lock *) Lock(name,SHARED_LOCK))) { status = -IoErr(); goto done; } if ((Examine(lock,FIB))==0){ status = -IoErr(); goto done; } status = (FIB->fib_DirEntryType > 0); done: if (FIB) FreeMem(FIB, (long) sizeof(struct FileInfoBlock)); UnLock(lock); return status; } ^L /*---------------------------------------------------------------------*/ /* SetFileDate: datestamp the given file with the given date. */ /*---------------------------------------------------------------------*/ BOOL SetFileDate(name,date ) char *name; struct DateStamp *date; { struct MsgPort *task; /* for process id handler */ ULONG arg[4]; /* array of arguments */ int nameleng; char *bstr, *strcpy(); /* of file to be set */ long rc; char *strchr(); int strlen(); rc = 0; nameleng = strlen(name); if (!(bstr = (char *)AllocMem((long) (nameleng + 2),MEMF_PUBLIC))) goto exit2; if (!(task = (struct MsgPort *)DeviceProc(name ))) goto exit1; /* Dos Packet needs the filename in Bstring format */ (void) strcpy(bstr+1, name ); *bstr = nameleng; arg[0]= (ULONG)NULL; arg[1]= (ULONG)IoErr(); /* lock on parent director set by DeviceProc() */ arg[2]= (ULONG)bstr >> 2; arg[3]= (ULONG)date; rc = sendpkt(task,ACTION_SETDATE_MODE,arg,4L ); exit1: if (bstr ) FreeMem((void *)bstr, (long) (nameleng + 2)); exit2: if (rc == DOSTRUE ) return TRUE; else return FALSE; } SHAR_EOF if test 4940 -ne "`wc -c FileMisc.c`" then echo shar: error transmitting FileMisc.c '(should have been 4940 characters)' fi echo shar: extracting FormatDisk.c '(9938 characters)' cat << \SHAR_EOF > FormatDisk.c /* Format a floppy disk (880k drive). * Author: Mark R. Rinfret * Date: 06/28/87 * Description: * This set of routines may be incorporated into a program which * has need of formatting a floppy disk. I wrote it to support my * hard disk backup utility. * * History: (most recent change first) * * 12/08/87 -MRR- My floppy drive (at least) will occaisionally "hang" * during formatting. I don't know what the source of * the problem is, but for now I've added a timer and * switched to a SendIO/Wait combo to handle this. * * 08/26/87 -MRR- Modified FormatDisk to delay 5 seconds after * uninhibiting the drive. This should give enough time * for the validator to do its thing and prevent the * "Insert disk..." requester from rearing its ugly head * if the application attempts to access the disk as * soon as we return. */ #include #include #include #include #include #include #include ":src/lib/AmigaFunctions.h" #include ":src/lib/Timer.h" extern struct IOExtTD *CreateExtIO(); static int CkIOErr(); #define MAX_NAME 30L #define TD_WRITE CMD_WRITE #define TRACKSIZE NUMSECS * TD_SECTOR /* Format a floppy disk - hardwired for the 3.5" 880k floppy drives. * Called with: * drivename: device name (DF0, etc.) * name: new volume name * Returns: * Zero on success, 1 on failure * Note: * This routine does not currently perform a verification, as * recommended by the RKM. Perhaps later... * I also discovered that there's some erroneous crap in * "The Amiga Programmer's Workbook, Vol. II", by * Eugene P. Mortimore. On page 339, he states that only 512 * bytes of track data are required for formatting. The RKM * correctly states that a "track's worth of data" is required. * It took some playing with DiskEd to discover this error. */ int FormatDisk(drivename,name) char *drivename; char *name; { long checkSum; char *dosID = "DOS"; long dosWord = 0; short error; long diskBit, timerBit; struct MsgPort *diskPort = NULL; struct IOExtTD *diskRequest = NULL; ULONG diskChangeCount; USHORT retries, status = 0, i, timeout, track; long signals; /* signal bits from Wait() */ struct timerequest *timeRequest; /* timeout timer request */ int unit; char *volname; char *diskBuffer; ULONG *diskBlock; /* alias for diskBuffer, ULONG type */ if (strlen(name) >= MAX_NAME) { #ifdef DEBUG printf("Disk name is too long!\n"); #endif status = ERROR_INVALID_COMPONENT_NAME; goto cleanup; } if ((unit = (drivename[2]-'0')) < 0 || unit >= NUMUNITS) { #ifdef DEBUG printf("FormatDisk: invalid drive specification!\n"); #endif status = ERROR_INVALID_COMPONENT_NAME; goto cleanup; } if (!(diskBuffer = AllocMem((long) TRACKSIZE, MEMF_PUBLIC | MEMF_CHIP))) { status = ERROR_NO_FREE_STORE; goto cleanup; } timeRequest = CreateTimer(0); /* create uHERZ timer */ if (timeRequest == NULL) { status = ERROR_NO_FREE_STORE; /* would IoError be valid? */ goto cleanup; } /* Store DOS "magic word" in disk block to be written during * formatting. */ diskBlock = (ULONG *) diskBuffer;/* we'll need this later */ for (i = 0; i < 3; ++i) dosWord = (dosWord << 8) | dosID[i]; dosWord = dosWord << 8; #ifdef DEBUG printf("dosWord is %lx\n",dosWord); #endif for (i = 0; i < TRACKSIZE / 4; ++i) diskBlock[i] = (dosWord | (long) (i & 0xff)); if ((diskPort = CreatePort(0L, 0L)) == NULL) { #ifdef DEBUG printf("FormatDisk can't create port!\n"); #endif status = 1; /* is there a better error code? */ goto cleanup; } if (!(diskRequest = (struct IOExtTD *) CreateExtIO(diskPort, (long) sizeof(struct IOExtTD)))) { status = 1; goto cleanup; } if (status = OpenDevice(TD_NAME, (long) unit, diskRequest, 0L)) { #ifdef DEBUG printf("FormatDisk: OpenDevice error: %d\n",error); #endif goto cleanup; } if (status = Inhibit(drivename, 1)) { #ifdef DEBUG printf("FormatDisk: unable to inhibit drive!\n"); #endif goto cleanup; } /* Get the current disk change count. This allows the trackdisk * driver to detect unwanted disk changes later on. */ diskRequest->iotd_Req.io_Command = TD_CHANGENUM; DoIO(diskRequest); /* Save a copy of the disk change count. */ diskChangeCount = diskRequest->iotd_Req.io_Actual; #ifdef DEBUG printf("Current disk change count is %ld\n", diskChangeCount); #endif /* Format the disk, one track at a time. This operation seems * susceptible to timing out (infrequently) on my system, so we'll * use a combination of SendIO and Wait, rather than DoIO. */ diskBit = 1L << diskRequest->iotd_Req.io_Message.mn_ReplyPort->mp_SigBit; timerBit = 1L << timeRequest->tr_node.io_Message.mn_ReplyPort->mp_SigBit; #ifdef DEBUG printf("diskBit => %08lx, timerBit => %08lx\n", diskBit, timerBit); #endif for (track = 0; track < NUMTRACKS; ++track) { retries = 0; retry: diskRequest->iotd_Req.io_Command = TD_FORMAT; diskRequest->iotd_Req.io_Flags = 0; diskRequest->iotd_Req.io_Data = (APTR) diskBuffer; diskRequest->iotd_Count = diskChangeCount; diskRequest->iotd_Req.io_Length = NUMSECS * TD_SECTOR; diskRequest->iotd_Req.io_Offset = track * NUMSECS * TD_SECTOR; SendIO(diskRequest); StartTimer(timeRequest, 5L, 0L); /* Start 5 second disk timer. */ #ifdef DEBUG if (timeRequest->tr_node.io_Error) { printf("Error on StartTimer: %d\n", timeRequest->tr_node.io_Error); } #endif while (TRUE) { timeout = 0; signals = Wait(diskBit | timerBit); if (signals & timerBit) { if (CheckIO(timeRequest)) { /* timer I/O complete? */ WaitIO(timeRequest); /* complete timer processing */ AbortIO(diskRequest); /* kill disk I/O */ timeout = 1; #ifdef DEBUG puts("--TIMEOUT--"); #endif break; } } if (signals & diskBit) { /* Did disk complete? */ if (CheckIO(diskRequest)) { WaitIO(diskRequest); /* complete disk processing */ StopTimer(timeRequest); break; } } } /* end while(TRUE) */ /* Retry a timeout 3 times before giving up. */ if (timeout && (++retries < 4) ) goto retry; if (status = CkIOErr(diskRequest,"Formatting error")) { #ifdef DEBUG printf(" Track: %d\n",track); #endif goto cleanup; } } /* Now comes some real KLUDGING. Fill in the root block and the * first hash block. The information for this was gathered from * the "AmigaDos Technical Reference Manual" and some sleuthing * with DiskEd. */ for (i = 0; i < 128; ++i) diskBlock[i] = 0; diskBlock[0] = 2; /* T.SHORT (type) */ diskBlock[3] = 128 - 56; /* hashtable size */ diskBlock[78] = 0xffffffff; /* BMFLAG */ diskBlock[79] = 881; /* first bitmap block */ DateStamp(&diskBlock[105]); /* volume last altered date/time */ DateStamp(&diskBlock[121]); /* volume creation date/time */ volname = (char *) &diskBlock[108]; /* convert input name to BSTR */ *volname = strlen(name); for (i = 0; i < *volname; ++i) *(volname + 1 + i) = *(name + i); diskBlock[127] = 1; /* ST.ROOT (secondary type) */ checkSum = 0; for (i = 0; i < 128; ++i) checkSum += diskBlock[i]; diskBlock[5] = - checkSum; /* Write the root block out to the disk. */ diskRequest->iotd_Req.io_Command = TD_WRITE; diskRequest->iotd_Req.io_Length = TD_SECTOR; diskRequest->iotd_Req.io_Offset = TD_SECTOR * 880L; DoIO(diskRequest); if (status = CkIOErr(diskRequest, "Error writing root block")) { goto cleanup; } /* Write the first bitmap block. */ for (i = 0; i < 56; ++i) diskBlock[i] = 0xffffffff; for (i = 56; i < 128; ++i) diskBlock[i] = 0; diskBlock[0] = 0xc000c037; /* hint: x37 = 55 (last word of map?) */ diskBlock[28] = 0xffff3fff; /* blocks 880, 881 used */ diskBlock[55] = 0x3fffffff; /* blocks 1760, 1761 used? */ diskRequest->iotd_Req.io_Length = TD_SECTOR; diskRequest->iotd_Req.io_Offset = 881L * TD_SECTOR; DoIO(diskRequest); /* write out the bitmap */ if (status = CkIOErr(diskRequest, "Error writing bitmap")) { goto cleanup; } diskRequest->iotd_Req.io_Command = ETD_UPDATE; diskRequest->iotd_Req.io_Flags = 0; DoIO(diskRequest); /* Turn the disk motor off. */ diskRequest->iotd_Req.io_Command = TD_MOTOR; diskRequest->iotd_Req.io_Length = 0; DoIO(diskRequest); Inhibit(drivename, 0); /* enable disk validator */ Delay(3L * TICKS_PER_SECOND); /* Give it a chance */ cleanup: CloseDevice(diskRequest); if (diskBuffer) FreeMem(diskBuffer, (long) TRACKSIZE); if (diskRequest) DeleteExtIO(diskRequest, (long) sizeof(*diskRequest)); if (diskPort) DeletePort(diskPort); if (timeRequest) DeleteTimer(timeRequest); return status; } /* Check the disk request block for an error code. If an error * occurred, print the argument string. * Called with: * req: pointer to I/O request structure * msg: error message string * Returns: * error code from request structure */ static int CkIOErr(req, msg) struct IOStdReq *req; char *msg; { register int code; if (code = req->io_Error) { #ifdef DEBUG printf("%s, code: %d\n",msg,code); #endif } return code; } #ifdef DEBUG main(argc, argv) int argc; char *argv[]; { char *diskname; char *volname; int unit; if (argc < 3) volname = "GoodJob!"; else volname = argv[2]; if (argc < 2) diskname = "DF1:"; else { diskname = argv[1]; if (strlen(diskname) != 4 || (strncmp(diskname,"df",2) && strncmp(diskname,"DF",2))) { bad_drive: printf("Drive name may only be df0: through df3:!\n"); exit(1); } if ((unit = (diskname[2] - '0')) < 0 || unit > 3) goto bad_drive; } printf("Insert disk in %s, then hit return\n",diskname); while (getchar() != '\n'); if (FormatDisk(diskname,volname)) printf("FormatDisk failed\n"); else { printf("FormatDisk succeeded\n"); } } #endif SHAR_EOF if test 9938 -ne "`wc -c FormatDisk.c`" then echo shar: error transmitting FormatDisk.c '(should have been 9938 characters)' fi # End of shell archive exit 0