home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / varie / xad / developer / sources / tools / xadundisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-25  |  17.6 KB  |  626 lines

  1. #define NAME         "xadUnDisk"
  2. #define DISTRIBUTION "(Freeware) "
  3. #define REVISION     "8"
  4. #define DATE         "12.04.2000"
  5.  
  6. /* Programmheader
  7.  
  8.     Name:        xadUnDisk
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    dearchives disk archives
  12.     Compileropts:    -
  13.     Linkeropts:    -gsi -l amiga
  14.  
  15.  1.0   18.11.98 : first version
  16.  1.1   23.12.98 : added support for FILEDESCRIPT
  17.  1.2   04.02.99 : added file corrupt message, new InfoText system and SAVETEXTS
  18.  1.3   16.02.99 : bug fix in report hook
  19.  1.4   28.02.99 : little bug fix in chunk hook
  20.  1.5   15.09.99 : added insert disk question
  21.  1.6   20.02.00 : added FORMAT keyword and ADF to disk
  22.  1.7   19.03.00 : bug fix
  23.  1.8   12.04.00 : image question only, if XADERR_FILETYPE
  24. */
  25.  
  26. #include <proto/xadmaster.h>
  27. #include <proto/exec.h>
  28. #include <proto/dos.h>
  29. #include <proto/utility.h>
  30. #include <exec/memory.h>
  31. #include <devices/trackdisk.h>
  32. #include <dos/dosasl.h>
  33. #include <dos/filehandler.h>
  34. #include <utility/hooks.h>
  35. #include "SDI_version.h"
  36. #include "SDI_compiler.h"
  37. #define SDI_TO_ANSI
  38. #include "SDI_ASM_STD_protos.h"
  39.  
  40. struct xadMasterBase *   xadMasterBase = 0;
  41. struct DosLibrary *     DOSBase = 0;
  42. struct ExecBase *     SysBase  = 0;
  43.  
  44. #define PARAM    "FROM/A,TO,LOWCYL/N,HIGHCYL/N,ENTRY/N,PASSWORD,SAVETEXTS/K," \
  45.         "NE=NOEXTERN/S,INFO=LIST/S,SHOWTEXTS/S,OW=OVERWRITE/S,"    \
  46.         "IG=IGNOREGEOMETRY/S,FORMAT/S,DIMG=DISKIMAGE/S"
  47.  
  48. struct Args {
  49.   STRPTR from;
  50.   STRPTR to;
  51.   LONG * lowcyl;
  52.   LONG * highcyl;
  53.   LONG * entry;
  54.   STRPTR password;
  55.   STRPTR savetexts;
  56.   ULONG  noextern;
  57.   ULONG  info;
  58.   ULONG  showtexts;
  59.   ULONG  overwrite;
  60.   ULONG  ignoregeometry;
  61.   ULONG  format;
  62.   ULONG  diskimage;
  63. };
  64.  
  65. ASM(ULONG) SAVEDS progrhook(REG(a0, struct Hook *),
  66.   REG(a1, struct xadProgressInfo *));
  67. struct Hook prhook = {{0,0},(ULONG (*)()) progrhook, 0, 0};
  68. void ShowTexts(struct xadTextInfo *ti);
  69. void SaveTexts(struct xadTextInfo *ti, STRPTR name);
  70. LONG WriteDisk(struct Args *);
  71.  
  72. ULONG start(void)
  73. {
  74.   ULONG ret = RETURN_FAIL;
  75.   struct DosLibrary *dosbase;
  76.  
  77.   SysBase = (*((struct ExecBase **) 4));
  78.   { /* test for WB and reply startup-message */
  79.     struct Process *task;
  80.     if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  81.     {
  82.       WaitPort(&task->pr_MsgPort);
  83.       Forbid();
  84.       ReplyMsg(GetMsg(&task->pr_MsgPort));
  85.       return RETURN_FAIL;
  86.     }
  87.   }
  88.  
  89.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  90.   {
  91.     LONG err = 0;
  92.     struct xadMasterBase *xadmasterbase;
  93.  
  94.     DOSBase = dosbase;
  95.     if((xadmasterbase = (struct xadMasterBase *)
  96.     OpenLibrary("xadmaster.library", 5)))
  97.     {
  98.       LONG def = 1;
  99.       struct Args args;
  100.       struct RDArgs *rda;
  101.       
  102.       memset(&args, 0 , sizeof(struct Args));
  103.       args.entry = &def;
  104.  
  105.       xadMasterBase = xadmasterbase;
  106.       if((rda = ReadArgs(PARAM, (LONG *) &args, 0)))
  107.       {
  108.     if(args.to || args.info)
  109.     {
  110.       struct xadArchiveInfo *ai;
  111.     
  112.       if(args.diskimage)
  113.       {
  114.         ret = 0;
  115.         if(args.to[strlen(args.to)-1] == ':' && stricmp(args.to, "NIL:"))
  116.           err = WriteDisk(&args);
  117.         else
  118.           Printf("Use copy command to copy disk images.\n");
  119.       }
  120.       else if((ai = (struct xadArchiveInfo *)
  121.       xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
  122.       {
  123.         if(!(err = xadGetInfo(ai, XAD_INFILENAME, args.from,
  124.         XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
  125.         TAG_IGNORE, args.password, TAG_DONE)))
  126.         {
  127.           if(ai->xai_Flags & XADAIF_FILECORRUPT)
  128.             Printf("!!! The archive file has some corrupt data. !!!\n");
  129.           if(args.info)
  130.           {
  131.             struct xadDiskInfo *xdi;
  132.             Printf("ArchiverName:   %s\n", ai->xai_Client->xc_ArchiverName);
  133. #ifdef DEBUG
  134.             Printf("Password:       %s\n", ai->xai_Password ? ai->xai_Password : "<none>");
  135.             Printf("InSize:         %ld\n", ai->xai_InSize);
  136.             Printf("InPos:          %ld\n", ai->xai_InPos);
  137. #endif
  138.  
  139.             xdi = ai->xai_DiskInfo;
  140.             while(xdi)
  141.             {
  142.           if(xdi->xdi_EntryNumber != 1 || xdi->xdi_Next)
  143.                 Printf("\nEntry:          %ld\n", xdi->xdi_EntryNumber);
  144.               Printf("EntryInfo:      %s\n", xdi->xdi_EntryInfo ? xdi->xdi_EntryInfo : "<none>");
  145. #ifdef DEBUG
  146.               Printf("Flags:          ");
  147.               if(xdi->xdi_Flags & XADDIF_CRYPTED)
  148.                 Printf("XADDIF_CRYPTED ");
  149.               Printf(xdi->xdi_Flags ? "\n" : "<none>\n");
  150. #endif
  151.               Printf("SectorSize:     %ld\n", xdi->xdi_SectorSize);
  152.               Printf("Sectors:        %ld\n", xdi->xdi_TotalSectors);
  153.               Printf("Cylinders:      %ld\n", xdi->xdi_Cylinders);
  154.               Printf("CylSectors:     %ld\n", xdi->xdi_CylSectors);
  155.               Printf("Heads:          %ld\n", xdi->xdi_Heads);
  156.               Printf("TrackSectors:   %ld\n", xdi->xdi_TrackSectors);
  157.               Printf("LowCyl:         %ld\n", xdi->xdi_LowCyl);
  158.               Printf("HighCyl:        %ld\n", xdi->xdi_HighCyl);
  159.               if(xdi->xdi_Flags & XADDIF_CRYPTED)
  160.                 Printf("The entry is encrypted\n");
  161.               if(xdi->xdi_TextInfo)
  162.               {
  163.                 STRPTR a;
  164.                 struct xadTextInfo *ti;
  165.  
  166.                 for(ti = xdi->xdi_TextInfo; ti; ti = ti->xti_Next)
  167.                 {
  168.               a = "TextInfo";
  169.               if(ti->xti_Flags & XADTIF_BANNER)
  170.                 a = "Banner";
  171.               else if(ti->xti_Flags & XADTIF_FILEDIZ)
  172.                 a = "DIZ-Text";
  173.  
  174.               if(ti->xti_Size && ti->xti_Text)
  175.                     Printf("There is a %s with size %ld.\n", a, ti->xti_Size);
  176.                   else if(ti->xti_Flags & XADTIF_CRYPTED)
  177.                     Printf("There is a crypted %s.\n", a);
  178.                   else
  179.                     Printf("There is an empty %s.\n", a);
  180.                 }
  181.                 if(args.showtexts)
  182.                   ShowTexts(xdi->xdi_TextInfo);
  183.                 if(args.savetexts)
  184.                   SaveTexts(xdi->xdi_TextInfo, args.savetexts);
  185.               }
  186.               xdi = xdi->xdi_Next;
  187.             }
  188.             ret = 0;
  189.           }
  190.           else
  191.           {
  192.         struct xadDeviceInfo *dvi = 0;
  193.  
  194.             if(args.to[strlen(args.to)-1] == ':' && stricmp(args.to, "NIL:"))
  195.             {
  196.               if((dvi = (struct xadDeviceInfo *)
  197.               xadAllocObjectA(XADOBJ_DEVICEINFO, 0)))
  198.               {
  199.                 args.to[strlen(args.to)-1] = 0; /* strip ':' */
  200.                 dvi->xdi_DOSName = args.to;
  201.               }
  202.               else
  203.                 err = XADERR_NOMEMORY;
  204.             }
  205.             if(args.showtexts || args.savetexts)
  206.             {
  207.               struct xadDiskInfo *xdi = ai->xai_DiskInfo;
  208.  
  209.               while(xdi && xdi->xdi_EntryNumber < *args.entry)
  210.                 xdi = xdi->xdi_Next;
  211.               if(xdi && xdi->xdi_TextInfo)
  212.               {
  213.                 if(args.showtexts)
  214.                   ShowTexts(xdi->xdi_TextInfo);
  215.                 if(args.savetexts)
  216.                   SaveTexts(xdi->xdi_TextInfo, args.savetexts);
  217.               }
  218.             }
  219.         if(dvi)
  220.         {
  221.           UBYTE r;
  222.           STRPTR b;
  223.           
  224.           for(b = args.to; *b; ++b)
  225.             *b = toupper(*b);
  226.  
  227.                   Printf("Insert disk into %s: and press <ENTER> (any other key to abort): ", dvi->xdi_DOSName);
  228.                   Flush(Output());
  229.                   SetMode(Input(), TRUE);
  230.                   r = FGetC(Input());
  231.                   SetMode(Input(), FALSE);
  232.                   if(r != '\r' && r != '\n')
  233.                   {
  234.                     Printf("\n");
  235.                     err = XADERR_BREAK;
  236.                   }
  237.         }
  238.             if(!err && !(err = xadDiskUnArc(ai, dvi ? XAD_OUTDEVICE :
  239.             XAD_OUTFILENAME, dvi ? (ULONG) dvi : (ULONG) args.to,
  240.             XAD_ENTRYNUMBER, *args.entry, args.lowcyl ?
  241.             XAD_LOWCYLINDER : TAG_IGNORE, args.lowcyl ? *args.lowcyl :
  242.             0, args.highcyl ? XAD_HIGHCYLINDER : TAG_IGNORE,
  243.             args.highcyl ? *args.highcyl : 0, XAD_OVERWRITE,
  244.             args.overwrite, XAD_IGNOREGEOMETRY, args.ignoregeometry,
  245.             XAD_FORMAT, args.format, XAD_VERIFY, TRUE, XAD_PROGRESSHOOK,
  246.             &prhook, TAG_DONE)))
  247.               ret = 0;
  248.             if(dvi)
  249.               xadFreeObjectA(dvi, 0);
  250.           }
  251.           xadFreeInfo(ai);
  252.         } /* xadGetInfo */
  253.         else if(err == XADERR_FILETYPE && args.to[strlen(args.to)-1] == ':' && stricmp(args.to, "NIL:"))
  254.         {
  255.           UBYTE r;
  256.  
  257.           ret = 0;
  258.               Printf("Unknown type. Press <I> to write it to disks as image: ");
  259.               Flush(Output());
  260.               SetMode(Input(), TRUE);
  261.               r = FGetC(Input());
  262.               SetMode(Input(), FALSE);
  263.               if(r == 'i' || r == 'I')
  264.             err = WriteDisk(&args);
  265.           else
  266.                 Printf("\n");
  267.         }
  268.  
  269.         xadFreeObjectA(ai, 0);
  270.           } /* xadAllocObject */
  271.         }
  272.         else
  273.           SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  274.  
  275.         FreeArgs(rda);
  276.       } /* ReadArgs */
  277.  
  278.       if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  279.         SetIoErr(ERROR_BREAK);
  280.  
  281.       if(err)
  282.     Printf("An error occured: %s\n", xadGetErrorText(err));
  283.       else if(ret)
  284.         PrintFault(IoErr(), 0);
  285.  
  286.       CloseLibrary((struct Library *) xadmasterbase);
  287.     } /* OpenLibrary xadmaster */
  288.     else
  289.       Printf("Could not open xadmaster.library\n");
  290.     CloseLibrary((struct Library *) dosbase);
  291.   } /* OpenLibrary dos */
  292.   return ret;
  293. }
  294.  
  295. ASM(ULONG) SAVEDS progrhook(REG(a0, struct Hook *hook),
  296. REG(a1, struct xadProgressInfo *pi))
  297. {
  298.   ULONG ret = 0;
  299.  
  300.   switch(pi->xpi_Mode)
  301.   {
  302.   case XADPMODE_ASK:
  303.     {
  304.       UBYTE r;
  305.       if(pi->xpi_Status & XADPIF_OVERWRITE)
  306.       {
  307.         Printf("File already exists, overwrite? (Y|S|\033[1mN\033[0m): ");
  308.         Flush(Output());
  309.         SetMode(Input(), TRUE);
  310.         r = FGetC(Input());
  311.         if(r == 'Y' || r == 'y')
  312.           ret |= XADPIF_OVERWRITE;
  313.         else if(r == 'S' || r == 's')
  314.           ret |= XADPIF_SKIP;
  315.         SetMode(Input(), FALSE);
  316.       }
  317.       if(pi->xpi_Status & XADPIF_IGNOREGEOMETRY)
  318.       {
  319.         Printf("\r\033[KDrive geometry not correct, ignore? (Y|S|\033[1mN\033[0m): ");
  320.         Flush(Output());
  321.         SetMode(Input(), TRUE);
  322.         r = FGetC(Input());
  323.         if(r == 'Y' || r == 'y')
  324.           ret |= XADPIF_IGNOREGEOMETRY;
  325.         else if(r == 'S' || r == 's')
  326.           ret |= XADPIF_SKIP;
  327.         SetMode(Input(), FALSE);
  328.       }
  329.     }
  330.     break;
  331.   case XADPMODE_PROGRESS:
  332.     {
  333.       if(pi->xpi_DiskInfo->xdi_Flags & (XADDIF_NOCYLINDERS|XADDIF_NOCYLSECTORS))
  334.       {
  335.         Printf("\r\033[KWrote %ld of %ld bytes (%ld/%ld sectors)",
  336.         pi->xpi_CurrentSize, pi->xpi_DiskInfo->xdi_TotalSectors*
  337.         pi->xpi_DiskInfo->xdi_SectorSize, pi->xpi_CurrentSize/
  338.         pi->xpi_DiskInfo->xdi_SectorSize, pi->xpi_DiskInfo->xdi_TotalSectors);
  339.       }
  340.       else
  341.       {
  342.         ULONG numcyl, fullsize, curcyl, i;
  343.  
  344.         i = pi->xpi_DiskInfo->xdi_CylSectors *
  345.             pi->xpi_DiskInfo->xdi_SectorSize;
  346.         numcyl = pi->xpi_HighCyl+1-pi->xpi_LowCyl;
  347.         fullsize = numcyl * i;
  348.         curcyl = pi->xpi_CurrentSize/i;
  349.  
  350.         Printf("\r\033[KWrote %ld of %ld bytes (%ld/%ld cylinders)",
  351.         pi->xpi_CurrentSize, fullsize, curcyl, numcyl);
  352.       }
  353.       Flush(Output());
  354.     }
  355.     break;
  356.   case XADPMODE_END: 
  357.     if(pi->xpi_DiskInfo->xdi_Flags & (XADDIF_NOCYLINDERS|XADDIF_NOCYLSECTORS))
  358.       Printf("\r\033[KWrote %ld bytes (%ld sectors)\n",
  359.       pi->xpi_CurrentSize, pi->xpi_DiskInfo->xdi_TotalSectors);
  360.     else
  361.       Printf("\r\033[KWrote %ld bytes (%ld cylinders)\n",
  362.       pi->xpi_CurrentSize, pi->xpi_HighCyl+1-pi->xpi_LowCyl);
  363.     break;
  364.   case XADPMODE_ERROR: Printf("\r\033[K");
  365.     break;
  366.   }
  367.  
  368.   if(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)) /* clear ok flag */
  369.     ret |= XADPIF_OK;
  370.  
  371.   return ret;
  372. }
  373.  
  374. void ShowTexts(struct xadTextInfo *ti)
  375. {
  376.   ULONG i = 1, j;
  377.   BPTR fh;
  378.   STRPTR a;
  379.  
  380.   fh = Output();
  381.  
  382.   while(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && ti)
  383.   {
  384.     if(ti->xti_Size && ti->xti_Text)
  385.     {
  386.       Printf("»»»» TEXTINFO %ld ««««\n", i);
  387.       a = ti->xti_Text;
  388.       for(j = 0; !(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && j < ti->xti_Size; ++j)
  389.       {
  390.         if(isprint(*a) || *a == '\n' || *a == '\t' || *a == '\033')
  391.           FPutC(fh, *a);
  392.         else
  393.           FPutC(fh, '.');
  394.         ++a;
  395.       }
  396.       if(*(--a) != '\n')
  397.         FPutC(fh, '\n');
  398.     }
  399.     ti = ti->xti_Next;
  400.     ++i;
  401.   }
  402. }
  403.  
  404. void SaveTexts(struct xadTextInfo *ti, STRPTR name)
  405. {
  406.   UBYTE namebuf[256];
  407.   ULONG i = 1;
  408.   BPTR fh;
  409.   LONG err = 0;
  410.  
  411.   while(!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && ti && !err)
  412.   {
  413.     if(ti->xti_Size && ti->xti_Text)
  414.     {
  415.       sprintf(namebuf, "%s.%ld", name, i);
  416.       if((fh = Open(namebuf, MODE_NEWFILE)))
  417.       {
  418.         if(Write(fh, ti->xti_Text, ti->xti_Size) != ti->xti_Size)
  419.           ++err;
  420.         Close(fh);
  421.       }
  422.       else
  423.         ++err;
  424.     }
  425.     ti = ti->xti_Next;
  426.     ++i;
  427.   }
  428.   if(err)
  429.     Printf("Failed to save information texts.\n");
  430. }
  431.  
  432. LONG WriteDisk(struct Args *args)
  433. {
  434.   LONG err = XADERR_RESOURCE;
  435.   struct DosList *dol;
  436.  
  437.   if((dol = LockDosList(LDF_READ|LDF_DEVICES)))
  438.   {
  439.     ULONG i;
  440.  
  441.     i = strlen(args->to)-1;
  442.     args->to[i] = 0; /* remove ':' */
  443.  
  444.     if((dol = FindDosEntry(dol, args->to, LDF_DEVICES)))
  445.     {
  446.       struct MsgPort *port;
  447.       
  448.       args->to[i] = ':';
  449.       if((port = CreateMsgPort()))
  450.       {
  451.     struct IOStdReq *ioreq;
  452.     
  453.     if((ioreq = (struct IOStdReq *) CreateIORequest(port, sizeof(struct IOStdReq))))
  454.     {
  455.       struct FileSysStartupMsg *fsm;
  456.  
  457.       fsm = (struct FileSysStartupMsg *) (dol->dol_misc.dol_handler.dol_Startup<<2);
  458.  
  459.       if(!OpenDevice((STRPTR)((fsm->fssm_Device<<2)+1), fsm->fssm_Unit, (struct IORequest *) ioreq, 0))
  460.       {
  461.         struct DosEnvec *de;
  462.         STRPTR buf;
  463.         ULONG size;
  464.  
  465.         de = (struct DosEnvec *) (fsm->fssm_Environ<<2);
  466.          size = (de->de_SizeBlock<<2)*(de->de_BlocksPerTrack*de->de_Surfaces);
  467.         if((buf = (STRPTR) AllocVec(size*2, MEMF_ANY)))
  468.         {
  469.           BPTR fh;
  470.  
  471.           if((fh = Open(args->from, MODE_OLDFILE)))
  472.           {
  473.         struct FileInfoBlock *fib;
  474.           ULONG low, num;
  475.  
  476.         low = de->de_LowCyl*size;
  477.         num = (de->de_HighCyl-de->de_LowCyl+1) * size;
  478.         if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
  479.         {
  480.           if(ExamineFH(fh, fib))
  481.           {
  482.             struct UtilityBase *UtilityBase;
  483.  
  484.             if((UtilityBase = (struct UtilityBase *) OpenLibrary("utility.library", 37)))
  485.             {
  486.               struct xadProgressInfo *pi;
  487.  
  488.               if((pi = (struct xadProgressInfo *) xadAllocObjectA(XADOBJ_PROGRESSINFO, 0)))
  489.               {
  490.                 struct xadDiskInfo *xdi;
  491.                 err = 0;
  492.                 if(num != fib->fib_Size && !args->ignoregeometry)
  493.                 {
  494.                   pi->xpi_Mode = XADPMODE_ASK;
  495.                   pi->xpi_Status = XADPIF_IGNOREGEOMETRY;
  496.                           if(!((i = CallHookPkt(&prhook, 0, pi)) & XADPIF_OK))
  497.                     err = XADERR_BREAK;
  498.                   else if(i & XADPIF_SKIP)
  499.                     err = XADERR_SKIP;
  500.                   else if(!(i & XADPIF_IGNOREGEOMETRY))
  501.                     err = XADERR_GEOMETRY;
  502.             }
  503.             if(!err)
  504.             {
  505.               UBYTE r;
  506.               STRPTR b;
  507.           
  508.               for(b = args->to; *b; ++b)
  509.                 *b = toupper(*b);
  510.  
  511.                       Printf("\r\033[KInsert disk into %s and press <ENTER> (any other key to abort): ", args->to);
  512.                       Flush(Output());
  513.                       SetMode(Input(), TRUE);
  514.                       r = FGetC(Input());
  515.                       SetMode(Input(), FALSE);
  516.                       if(r != '\r' && r != '\n')
  517.                       {
  518.                         Printf("\n");
  519.                         err = XADERR_BREAK;
  520.                       }
  521.             }
  522.                 if(!err && (xdi = (struct xadDiskInfo *) xadAllocObjectA(XADOBJ_DISKINFO, 0)))
  523.                 {
  524.                   ULONG siz, p;
  525.                   STRPTR b;
  526.                   siz = fib->fib_Size;
  527.  
  528.                   ioreq->io_Flags = 0;
  529.                   b = buf+size;
  530.                   p = 0;
  531.                   pi->xpi_DiskInfo = xdi;
  532.                   xdi->xdi_Flags = XADDIF_NOCYLINDERS|XADDIF_NOCYLSECTORS;
  533.                   xdi->xdi_TotalSectors = (siz+511)>>9; /* divide by 512 */
  534.                   xdi->xdi_SectorSize = 512;
  535.                   Inhibit(args->to, DOSTRUE);
  536.               while(siz && !err)
  537.               {
  538.                 i = size > siz ? siz : size;
  539.                 if(p+i > num)
  540.                 {
  541.                   if(!(i = num-p)) /* do not exceed borders */
  542.                   {
  543.                     err = XADERR_OUTPUT; break;
  544.                   }
  545.                 }
  546.                 siz -= i;
  547.  
  548.                 if(Read(fh, buf, i) != i)
  549.                   err = XADERR_INPUT;
  550.                 else
  551.                 {
  552.                       ioreq->io_Length  = i;
  553.                       ioreq->io_Offset  = low+p;
  554.                       ioreq->io_Command = args->format ? TD_FORMAT : CMD_WRITE;
  555.                       ioreq->io_Data    = buf;
  556.                       p += i;
  557.                       if(DoIO(((struct IORequest *) ioreq)))
  558.                         err = XADERR_OUTPUT;
  559.                       else
  560.                       {
  561.                         ioreq->io_Command = CMD_READ;
  562.                         ioreq->io_Data    = b;
  563.                         if(DoIO(((struct IORequest *) ioreq)))
  564.                           err = XADERR_OUTPUT;
  565.                         else
  566.                         {
  567.                           pi->xpi_Mode = XADPMODE_PROGRESS;
  568.                           pi->xpi_CurrentSize = p;
  569.                                 if(!(CallHookPkt(&prhook, 0, pi)) & XADPIF_OK)
  570.                             err = XADERR_BREAK;
  571.                           else
  572.                           {
  573.                             while(i--)
  574.                             {
  575.                               if(buf[i] != b[i])
  576.                               {
  577.                                 err = XADERR_OUTPUT;
  578.                                 break;
  579.                               }
  580.                             }
  581.                           }
  582.                         }
  583.                       }
  584.                     }
  585.                   } /* while */
  586.                   Inhibit(args->to, DOSFALSE);
  587.               pi->xpi_Mode = err ? XADPMODE_ERROR : XADPMODE_END;
  588.                   pi->xpi_CurrentSize = fib->fib_Size;
  589.                   pi->xpi_Status = err;
  590.                           CallHookPkt(&prhook, 0, pi);
  591.                   xadFreeObjectA(xdi, 0);
  592.                 }
  593.                 xadFreeObjectA(pi, 0);
  594.               }
  595.               else
  596.                 err = XADERR_NOMEMORY;
  597.               CloseLibrary((struct Library *) UtilityBase);
  598.             }
  599.           }
  600.           else
  601.             err = XADERR_INPUT;
  602.           FreeDosObject(DOS_FIB, fib);
  603.         }
  604.         else
  605.           err = XADERR_NOMEMORY;
  606.         Close(fh);
  607.           }
  608.           else
  609.             err = XADERR_INPUT;
  610.           FreeVec(buf);
  611.         }
  612.         else
  613.           err = XADERR_NOMEMORY;
  614.         CloseDevice((struct IORequest *) (ioreq));
  615.       } /* OpenDevice */
  616.       DeleteIORequest(ioreq);
  617.     } /* CreatIORequest */
  618.     DeleteMsgPort(port);
  619.       } /* CreateMsgPort */
  620.     } /* FindDosEntry */
  621.     UnLockDosList(LDF_READ|LDF_DEVICES);
  622.   } /* LockDosList */
  623.  
  624.   return err;
  625. }
  626.