home *** CD-ROM | disk | FTP | other *** search
/ ANews 1 / AnewsCD01.iso / Indispensables / Compression / xad / Developer / Sources / tools / xadUnFile.c < prev   
C/C++ Source or Header  |  1999-08-09  |  19KB  |  616 lines

  1. #ifdef MULTIFILE
  2.   #define NAME         "xadUnFileM"
  3. #else
  4.   #define NAME         "xadUnFile"
  5. #endif
  6. #define DISTRIBUTION "(Freeware) "
  7. #define REVISION     "7"
  8.  
  9. /* Programmheader
  10.  
  11.     Name:        xadUnFile
  12.     Author:        SDI
  13.     Distribution:    Freeware
  14.     Description:    dearchives file archives
  15.     Compileropts:    -
  16.     Linkeropts:    -gsi -l amiga
  17.  
  18.  1.0   13.09.98 : first version
  19.  1.1   18.11.98 : added FILE parameter and directory creation
  20.  1.2   03.02.99 : added corrupt message
  21.  1.3   07.02.99 : added missing "group crunched" handling
  22.  1.4   16.03.99 : errors no longer abort decrunching
  23.  1.5   21.06.99 : added support for multiple input files and renaming
  24.  1.6   04.07.99 : bug fix
  25.  1.7   18.07.99 : added SHOWPROT, reduced status prints, added QUIT,
  26.     splitted in xadUnFile and xadUnFileM
  27. */
  28.  
  29. #include <proto/xadmaster.h>
  30. #include <proto/exec.h>
  31. #include <proto/dos.h>
  32. #include <exec/memory.h>
  33. #include <dos/dosasl.h>
  34. #include <utility/hooks.h>
  35. #include "SDI_defines.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 MINPRINTSIZE    51200    /* 50KB */
  45.  
  46. #ifdef MULTIFILE
  47. #define PARAM    "FROM/A/M,DEST=DESTDIR/K,PASSWORD/K,FILE/K,NE=NOEXTERN/S,"\
  48.         "INFO=LIST/S,OW=OVERWRITE/S,NOTREE/S,ASKMAKEDIR/S,"    \
  49.         "NOCOMMENT/S,NOPROT/S,NODATE/S,NOABS/S,SHOWPROT/S,QUIET/S"
  50. #else
  51. #define PARAM    "FROM/A,DEST=DESTDIR,PASSWORD/K,FILE/M,NE=NOEXTERN/S,"\
  52.         "INFO=LIST/S,OW=OVERWRITE/S,NOTREE/S,ASKMAKEDIR/S,"    \
  53.         "NOCOMMENT/S,NOPROT/S,NODATE/S,NOABS/S,SHOWPROT/S,QUIET/S"
  54. #endif
  55.  
  56. #ifdef MULTIFILE
  57. #define OPTIONS \
  58.   "FROM       The input archive file(s) (no patterns allowed)\n"    \
  59.   "DESTDIR    The destination directory, not needed with INFO\n"    \
  60.   "PASSWORD   A password for encrypted archives\n"            \
  61.   "FILE       Filename (with patterns) to be extracted\n"        \
  62.   "NOEXTERN   Turns off usage of external clients\n"            \
  63.   "INFO       Shows archive information without extracting\n"        \
  64.   "OVERWRITE  Files are overwritten without asking\n"            \
  65.   "NOTREE     Files are extracted without subdirectories\n"        \
  66.   "ASKMAKEDIR You get asked before a directory is created\n"        \
  67.   "NOCOMMENT  No filenote comments are extracted or displayed\n"    \
  68.   "NOPROT     Protection information gets not extracted\n"        \
  69.   "NODATE     Creation date information gets not extracted\n"        \
  70.   "NOABS      Do not extract absolute path name parts\n"        \
  71.   "SHOWPROT   Show protection information with LIST\n"            \
  72.   "QUIET      Turns of progress report and user interaction!\n"
  73. #else
  74. #define OPTIONS \
  75.   "FROM       The input archive file (no patterns allowed)\n"        \
  76.   "DESTDIR    The destination directory, not needed with INFO\n"    \
  77.   "PASSWORD   A password for encrypted archives\n"            \
  78.   "FILE       Filename(s) (with patterns) to be extracted\n"        \
  79.   "NOEXTERN   Turns off usage of external clients\n"            \
  80.   "INFO       Shows archive information without extracting\n"        \
  81.   "OVERWRITE  Files are overwritten without asking\n"            \
  82.   "NOTREE     Files are extracted without subdirectories\n"        \
  83.   "ASKMAKEDIR You get asked before a directory is created\n"        \
  84.   "NOCOMMENT  No filenote comments are extracted or displayed\n"    \
  85.   "NOPROT     Protection information gets not extracted\n"        \
  86.   "NODATE     Creation date information gets not extracted\n"        \
  87.   "NOABS      Do not extract absolute path name parts\n"        \
  88.   "SHOWPROT   Show protection information with LIST\n"            \
  89.   "QUIET      Turns of progress report and user interaction!\n"
  90. #endif
  91.  
  92. struct xHookArgs {
  93.   STRPTR name;
  94.   ULONG flags;
  95.   ULONG finish;
  96.   ULONG lastprint;
  97. };
  98.  
  99. #ifdef MULTIFILE
  100. struct Args {
  101.   STRPTR * from;
  102.   STRPTR   destdir;
  103.   STRPTR   password;
  104.   STRPTR   file;
  105.   ULONG    noextern;
  106.   ULONG    info;
  107.   ULONG    overwrite;
  108.   ULONG    notree;
  109.   ULONG    askmakedir;
  110.   ULONG    nocomment;
  111.   ULONG    noprot;
  112.   ULONG    nodate;
  113.   ULONG    noabs;
  114.   ULONG       showprot;
  115.   ULONG    quiet;
  116. };
  117. #else
  118. struct Args {
  119.   STRPTR   from;
  120.   STRPTR   destdir;
  121.   STRPTR   password;
  122.   STRPTR * file;
  123.   ULONG    noextern;
  124.   ULONG    info;
  125.   ULONG    overwrite;
  126.   ULONG    notree;
  127.   ULONG    askmakedir;
  128.   ULONG    nocomment;
  129.   ULONG    noprot;
  130.   ULONG    nodate;
  131.   ULONG    noabs;
  132.   ULONG       showprot;
  133.   ULONG    quiet;
  134. };
  135.  
  136. LONG CheckName(STRPTR *pat, STRPTR name);
  137. #endif
  138.  
  139. ASM(ULONG) progrhook(REG(a0, struct Hook *),
  140.   REG(a1, struct xadProgressInfo *));
  141.  
  142. void ShowProt(ULONG i);
  143.  
  144. ULONG start(void)
  145. {
  146.   ULONG ret = RETURN_FAIL;
  147.   struct DosLibrary *dosbase;
  148.  
  149.   SysBase = (*((struct ExecBase **) 4));
  150.   { /* test for WB and reply startup-message */
  151.     struct Process *task;
  152.     if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  153.     {
  154.       WaitPort(&task->pr_MsgPort);
  155.       Forbid();
  156.       ReplyMsg(GetMsg(&task->pr_MsgPort));
  157.       return RETURN_FAIL;
  158.     }
  159.   }
  160.  
  161.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  162.   {
  163.     LONG err = 0;
  164.     struct xadMasterBase *xadmasterbase;
  165.  
  166.     DOSBase = dosbase;
  167.     if((xadmasterbase = (struct xadMasterBase *)
  168.     OpenLibrary("xadmaster.library", 1)))
  169.     {
  170.       struct Args args;
  171.       struct RDArgs *rda;
  172.       
  173.       memset(&args, 0, sizeof(struct Args));
  174.       xadMasterBase = xadmasterbase;
  175.  
  176.       if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  177.       {
  178.         rda->RDA_ExtHelp = OPTIONS;
  179.  
  180.         if(ReadArgs(PARAM, (LONG *) &args, rda))
  181.         {
  182.       if(args.destdir || args.info)
  183.       {
  184.         struct xadArchiveInfo *ai;
  185.     
  186.         if((ai = (struct xadArchiveInfo *)
  187.         xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
  188.         {
  189. #ifdef MULTIFILE
  190.           if(*(args.from+1))
  191.           {
  192.             struct xadSplitFile *sf = 0, *sf2, *sf0 = 0;
  193.         while(*args.from && !err)
  194.         {
  195.           if((sf2 = xadAllocObjectA(XADOBJ_SPLITFILE, 0)))
  196.           {
  197.             if(sf)
  198.             {
  199.               sf->xsf_Next = sf2; sf = sf2;
  200.             }
  201.             else
  202.               sf0 = sf = sf2;
  203.             sf->xsf_Type = XAD_INFILENAME;
  204.             sf->xsf_Data = (ULONG) *(args.from++);
  205.           }
  206.           else
  207.             err = XADERR_NOMEMORY;
  208.         }
  209.             if(!err)
  210.               err = xadGetInfo(ai, XAD_INSPLITTED, sf0, XAD_NOEXTERN,
  211.               args.noextern, args.password ? XAD_PASSWORD : TAG_IGNORE,
  212.               args.password, TAG_DONE);
  213.             while(sf0)
  214.             {
  215.               sf2 = sf0; sf0 = sf0->xsf_Next;
  216.               xadFreeObjectA(sf2, 0);
  217.             }
  218.           }
  219.           else
  220.             err = xadGetInfo(ai, XAD_INFILENAME, *args.from,
  221.             XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
  222.             TAG_IGNORE, args.password, TAG_DONE);
  223. #else
  224.           err = xadGetInfo(ai, XAD_INFILENAME, args.from,
  225.           XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
  226.           TAG_IGNORE, args.password, TAG_DONE);
  227. #endif
  228.  
  229.           if(!err)
  230.           {
  231.             if(ai->xai_Flags & XADAIF_FILECORRUPT)
  232.               Printf("!!! The archive file has some corrupt data. !!!\n");
  233.             if(args.info)
  234.             {
  235.               struct xadFileInfo *xfi;
  236.               ULONG grsize = 0;
  237.               Printf("ArchiverName:   %s\n"
  238.           "Size     CrndSize Ratio Date       Time     %sName\n",
  239.           ai->xai_Client->xc_ArchiverName, args.showprot ? "Protection       " : "");
  240.  
  241.               xfi = ai->xai_FileInfo;
  242.               while(xfi && !CTRL_C)
  243.               {
  244.                 if(!(xfi->xfi_Flags & XADFIF_GROUPED))
  245.                   grsize = 0;
  246.             if(xfi->xfi_Flags & XADFIF_DIRECTORY)
  247.             {
  248.                   Printf("   <dir>    <dir>       %02ld.%02ld.%04ld %02ld:%02ld:%02ld ",
  249.                   xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
  250.                   xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
  251.                   xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second);
  252.                   if(args.showprot)
  253.                     ShowProt(xfi->xfi_Protection);
  254.                   Printf("%s\n", args.notree ? FilePart(xfi->xfi_FileName) :
  255.                   xfi->xfi_FileName);
  256.                 }
  257.             else if(xfi->xfi_Flags & XADFIF_GROUPED)
  258.             {
  259.                   Printf("%8ld   merged  n/a  %02ld.%02ld.%04ld %02ld:%02ld:%02ld ",
  260.                   xfi->xfi_Size, xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
  261.                   xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
  262.                   xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second);
  263.                   if(args.showprot)
  264.                     ShowProt(xfi->xfi_Protection);
  265.                   Printf("%s\n", args.notree ? FilePart(xfi->xfi_FileName) :
  266.                   xfi->xfi_FileName);
  267.                   grsize += xfi->xfi_Size;
  268.                   if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
  269.                   {
  270.                 ULONG i = 0, j = 0;
  271.               
  272.                 if(xfi->xfi_GroupCrSize < grsize)
  273.                 {
  274.                   i = ((grsize - xfi->xfi_GroupCrSize)*1000)/grsize;
  275.                   j = i % 10;
  276.                   i /= 10;
  277.                 }
  278.                     Printf("%8ld %8ld %2ld.%1ld%%\n", grsize, xfi->xfi_GroupCrSize,
  279.                     i, j);
  280.                     grsize = 0;
  281.                   }
  282.             }
  283.             else
  284.             {
  285.               ULONG i = 0, j = 0;
  286.               
  287.               if(xfi->xfi_CrunchSize < xfi->xfi_Size)
  288.               {
  289.                 i = ((xfi->xfi_Size - xfi->xfi_CrunchSize)*1000)/xfi->xfi_Size;
  290.                 j = i % 10;
  291.                 i /= 10;
  292.               }
  293.                  
  294.                   Printf("%8ld %8ld %2ld.%1ld%% %02ld.%02ld.%04ld %02ld:%02ld:%02ld ",
  295.                   xfi->xfi_Size, xfi->xfi_CrunchSize, i, j,
  296.                   xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
  297.                   xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
  298.                   xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second);
  299.                   if(args.showprot)
  300.                     ShowProt(xfi->xfi_Protection);
  301.                   Printf("%s\n", args.notree ? FilePart(xfi->xfi_FileName) :
  302.                   xfi->xfi_FileName);
  303.                 }
  304.                 if(xfi->xfi_Comment && !args.nocomment)
  305.                   Printf(": %s\n", xfi->xfi_Comment);
  306. #ifdef DEBUG
  307.             if(xfi->xfi_Flags)
  308.             {
  309.                   Printf("Flags:          ");
  310.                   if(xfi->xfi_Flags & XADFIF_CRYPTED)
  311.                     Printf("XADFIF_CRYPTED ");
  312.                   if(xfi->xfi_Flags & XADFIF_DIRECTORY)
  313.                     Printf("XADFIF_DIRECTORY ");
  314.                   if(xfi->xfi_Flags & XADFIF_LINK)
  315.                     Printf("XADFIF_LINK ");
  316.                   if(xfi->xfi_Flags & XADFIF_INFOTEXT)
  317.                     Printf("XADFIF_INFOTEXT ");
  318.                   if(xfi->xfi_Flags & XADFIF_GROUPED)
  319.                     Printf("XADFIF_GROUPED ");
  320.                   if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
  321.                     Printf("XADFIF_ENDOFGROUP ");
  322.                   if(xfi->xfi_Flags & XADFIF_NODATE)
  323.                     Printf("XADFIF_NODATE ");
  324.                   Printf("\n");
  325.                 }
  326. #endif
  327.                 if(xfi->xfi_Flags & XADFIF_CRYPTED)
  328.                   Printf("The entry is encrypted\n");
  329.                 xfi = xfi->xfi_Next;
  330.               }
  331.               ret = 0;
  332.             }
  333.             else
  334.             {
  335.           struct Hook prhook;
  336.           struct xadFileInfo *fi;
  337.           UBYTE filename[256];
  338. #ifdef MULTIFILE
  339.             UBYTE parsebuf[1024];
  340. #endif
  341.           struct xHookArgs xh;
  342.         
  343.           ret = 0;
  344.           xh.name = filename;
  345.           xh.flags = xh.finish = xh.lastprint = 0;
  346.  
  347.           /* Note! The hook may change the filename!!! */
  348.  
  349.               memset(&prhook, 0, sizeof(struct Hook));
  350.               prhook.h_Entry = (ULONG (*)()) progrhook;
  351.               prhook.h_Data = &xh;
  352.           fi = ai->xai_FileInfo;
  353.  
  354. #ifdef MULTIFILE
  355.             if(!args.file || ParsePatternNoCase(args.file, parsebuf, 1024) >= 0)
  356. #endif
  357.             {
  358.             while(fi && !CTRL_C && !xh.finish)
  359.             {
  360. #ifdef MULTIFILE
  361.               if(!args.file || MatchPatternNoCase(parsebuf, args.notree ?
  362.               FilePart(fi->xfi_FileName) : fi->xfi_FileName))
  363. #else
  364.               if(!args.file || CheckName(args.file, args.notree ?
  365.               FilePart(fi->xfi_FileName) : fi->xfi_FileName))
  366. #endif
  367.               {
  368.                 CopyMem(args.destdir, filename, strlen(args.destdir)+1);
  369.                 if(args.notree)
  370.                   AddPart(filename, FilePart(fi->xfi_FileName), 256);
  371.                 else if(!args.noabs)
  372.                   AddPart(filename, fi->xfi_FileName, 256);
  373.                 else
  374.                 {
  375.                   STRPTR fname = filename, f;
  376.  
  377.               if(*args.destdir)
  378.               {
  379.                     fname += strlen(args.destdir)-1;
  380.                     if(*fname != ':' && *fname != '/')
  381.                       *(++fname) = '/';
  382.                     ++fname;
  383.                   }
  384.                   for(f = fi->xfi_FileName; *f; ++f)
  385.                     *(fname++) = *f == ':' ? '/' : *f;
  386.                   *fname = 0;
  387.                 }
  388.                 if(fi->xfi_Flags & XADFIF_DIRECTORY)
  389.                 {
  390.                   if(!args.notree)
  391.                   {
  392.                     BPTR a;
  393.                     LONG err = 0, i = 0;
  394.                     UBYTE r;
  395.                     while(filename[i] && !err)
  396.                     {
  397.                         for(;filename[i] && filename[i] != '/'; ++i)
  398.                         ;
  399.                         r = filename[i];
  400.                         filename[i] = 0;
  401.                   if((a = Lock(filename, SHARED_LOCK)))
  402.                           UnLock(a);
  403.                       else if((a = CreateDir(filename)))
  404.                             UnLock(a);
  405.                         else
  406.                             err = 1;
  407.                           filename[i++] = r;
  408.                     }
  409.                     if(!args.quiet)
  410.                     {
  411.                       if(err)
  412.                         Printf("failed to create directory '%s'\n",
  413.                         fi->xfi_FileName);
  414.                       else
  415.                         Printf("Created directory   : %s\n", filename);
  416.                     }
  417.                   }
  418.                 } 
  419.                 else if(fi->xfi_Flags & XADFIF_LINK)
  420.                 {
  421.                   if(!args.quiet)
  422.                     Printf("Skipped Link\n");
  423.                 }
  424.                 else
  425.                 {
  426.                   struct DateStamp d;
  427.  
  428.                   if(!xadFileUnArc(ai, XAD_OUTFILENAME, filename,
  429.                       XAD_ENTRYNUMBER, fi->xfi_EntryNumber, XAD_MAKEDIRECTORY,
  430.                       !args.askmakedir, XAD_OVERWRITE, args.overwrite,
  431.                       args.quiet ? TAG_IGNORE : XAD_PROGRESSHOOK, &prhook, TAG_DONE))
  432.                       {
  433.                         if(!args.nodate && !(fi->xfi_Flags & XADFIF_NODATE)
  434.                         && !xadConvertDates(XAD_DATEXADDATE, &fi->xfi_Date,
  435.                         XAD_GETDATEDATESTAMP, &d, TAG_DONE))
  436.                           SetFileDate(filename, &d);
  437.                         if(!args.noprot)
  438.                           SetProtection(filename, fi->xfi_Protection);
  439.                         if(fi->xfi_Comment && !args.nocomment)
  440.                           SetComment(filename, fi->xfi_Comment);
  441.                         /* SetOwner ??? */
  442.                       }
  443.                     }
  444.                   }
  445.                   fi = fi->xfi_Next;
  446.                 }
  447.               }
  448.             }
  449.             xadFreeInfo(ai);
  450.           } /* xadGetInfo */
  451.  
  452.           xadFreeObjectA(ai, 0);
  453.             } /* xadAllocObject */
  454.           }
  455.           else
  456.             SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  457.  
  458.           FreeArgs(rda);
  459.         } /* ReadArgs */
  460.         FreeDosObject(DOS_RDARGS, rda);
  461.       } /* AllocDosObject */
  462.  
  463.       if(CTRL_C)
  464.         SetIoErr(ERROR_BREAK);
  465.  
  466.       if(!args.quiet)
  467.       {
  468.         if(err)
  469.       Printf("An error occured: %s\n", xadGetErrorText(err));
  470.         else if(ret)
  471.           PrintFault(IoErr(), 0);
  472.       }
  473.  
  474.       CloseLibrary((struct Library *) xadmasterbase);
  475.     } /* OpenLibrary xadmaster */
  476.     else
  477.       Printf("Could not open xadmaster.library\n");
  478.     CloseLibrary((struct Library *) dosbase);
  479.   } /* OpenLibrary dos */
  480.   return ret;
  481. }
  482.  
  483. /* Because of SAS-err, this cannot be SAVEDS */
  484. ASM(ULONG) progrhook(REG(a0, struct Hook *hook),
  485. REG(a1, struct xadProgressInfo *pi))
  486. {
  487.   ULONG ret = 0;
  488.   STRPTR name = ((struct xHookArgs *) (hook->h_Data))->name;
  489.  
  490.   switch(pi->xpi_Mode)
  491.   {
  492.   case XADPMODE_ASK:
  493.     ret |= ((struct xHookArgs *) (hook->h_Data))->flags;
  494.     if((pi->xpi_Status & XADPIF_OVERWRITE) && !(ret & XADPIF_OVERWRITE))
  495.     {
  496.       LONG r;
  497.  
  498.       Printf("File '%s' already exists, overwrite? (Y|A|S|\033[1mN\033[0m|Q|R): ",
  499.       pi->xpi_FileName);
  500.       Flush(Output());
  501.       SetMode(Input(), TRUE);
  502.       r = FGetC(Input());
  503.       SetMode(Input(), FALSE);
  504.       switch(r)
  505.       {
  506.       case 'a': case 'A':
  507.     ((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_OVERWRITE;
  508.       case 'y': case 'Y': ret |= XADPIF_OVERWRITE; break;
  509.       case 's': case 'S': ret |= XADPIF_SKIP; break;
  510.       case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1; break;
  511.       case 'r': case 'R':
  512.         Printf("\r\033[KEnter new (full) name for '%s':", pi->xpi_FileName);
  513.         Flush(Output());
  514.         FGets(Input(), name, 255); /* 1 byte less to correct bug before V39 */
  515.         r = strlen(name);
  516.         if(name[r-1] == '\n') /* skip return character */
  517.           name[--r] = 0;
  518.         Printf("\033[1F\033[K"); /* go up one line and clear it */
  519.         if(pi->xpi_NewName = xadAllocVec(++r, MEMF_PUBLIC))
  520.         {
  521.           while(r--)
  522.             pi->xpi_NewName[r] = name[r];
  523.           ret |= XADPIF_RENAME;
  524.         }
  525.         else
  526.           Printf("No memory to store new name\n");
  527.       }
  528.     }
  529.     if((pi->xpi_Status & XADPIF_MAKEDIRECTORY) &&
  530.     !(ret & XADPIF_MAKEDIRECTORY))
  531.     {
  532.       Printf("Directory of file '%s' does not exist, create? (Y|A|S|\033[1mN\033[0m|Q): ",
  533.       name);
  534.       Flush(Output());
  535.       SetMode(Input(), TRUE);
  536.       switch(FGetC(Input()))
  537.       {
  538.       case 'a': case 'A':
  539.     ((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_MAKEDIRECTORY;
  540.       case 'y': case 'Y': ret |= XADPIF_MAKEDIRECTORY; break;
  541.       case 's': case 'S': ret |= XADPIF_SKIP; break;
  542.       case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1;
  543.       }
  544.       SetMode(Input(), FALSE);
  545.     }
  546.     break;
  547.   case XADPMODE_PROGRESS:
  548.     if(pi->xpi_CurrentSize - ((struct xHookArgs *) (hook->h_Data))->lastprint >= MINPRINTSIZE)
  549.     {
  550.       Printf("\r\033[KWrote %8ld of %8ld bytes: %s",
  551.       pi->xpi_CurrentSize, pi->xpi_FileInfo->xfi_Size, name);
  552.       Flush(Output());
  553.       ((struct xHookArgs *) (hook->h_Data))->lastprint = pi->xpi_CurrentSize;
  554.     }
  555.     break;
  556.   case XADPMODE_END: Printf("\r\033[KWrote %8ld bytes: %s\n",
  557.     pi->xpi_CurrentSize, name);
  558.     break;
  559.   case XADPMODE_ERROR: Printf("\r\033[K%s: %s\n", name,
  560.     xadGetErrorText(pi->xpi_Error));
  561.     break;
  562.   }
  563.  
  564.   if(!CTRL_C) /* clear ok flag */
  565.     ret |= XADPIF_OK;
  566.  
  567.   return ret;
  568. }
  569.  
  570. void ShowProt(ULONG i)
  571. {
  572.   LONG j;
  573.   UBYTE buf[18];
  574.   
  575.   for(j = 0; j < 16; ++j)
  576.     buf[j] = '-';
  577.   buf[j++] = ' ';
  578.   buf[j] = 0;
  579.  
  580.   if(i & FIBF_OTR_READ)        buf[0] = 'r';
  581.   if(i & FIBF_OTR_WRITE)    buf[1] = 'w';
  582.   if(i & FIBF_OTR_EXECUTE)    buf[2] = 'e';
  583.   if(i & FIBF_OTR_DELETE)    buf[3] = 'd';
  584.   if(i & FIBF_GRP_READ)        buf[4] = 'r';
  585.   if(i & FIBF_GRP_WRITE)    buf[5] = 'w';
  586.   if(i & FIBF_GRP_EXECUTE)    buf[6] = 'e';
  587.   if(i & FIBF_GRP_DELETE)    buf[7] = 'd';
  588.   if(i & (1<<7))        buf[8] = 'h';
  589.   if(i & FIBF_SCRIPT)        buf[9] = 's';
  590.   if(i & FIBF_PURE)        buf[10] = 'p';
  591.   if(i & FIBF_ARCHIVE)        buf[11] = 'a';
  592.   if(!(i & FIBF_READ))        buf[12] = 'r';
  593.   if(!(i & FIBF_WRITE))        buf[13] = 'w';
  594.   if(!(i & FIBF_EXECUTE))    buf[14] = 'e';
  595.   if(!(i & FIBF_DELETE))    buf[15] = 'd';
  596.   Printf(buf);
  597. }
  598.  
  599. #ifndef MULTIFILE
  600. /* would be better to store the pattern parse stuff and do it only once,
  601. but so it is a lot easier */
  602. LONG CheckName(STRPTR *pat, STRPTR name)
  603. {
  604.   UBYTE buf[500];
  605.   while(*pat)
  606.   {
  607.     if(ParsePatternNoCase(*(pat++), buf, 500) >= 0)
  608.     {
  609.       if(MatchPatternNoCase(buf, name))
  610.         return 1;
  611.     } /* A scan failure means no recognition, should be an error print here */
  612.   }
  613.   return 0;
  614. }
  615. #endif
  616.