home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / utility / misc / setsize.lha / setsize / SetSize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-17  |  11.3 KB  |  298 lines

  1. /*---------------------------------------------------------------------------*/
  2. /* Command: SetSize                                 */
  3. /* Author: James E. Cooper Jr.                             */
  4. /* Change History:                                 */
  5. /*  Date    Person      Action                         */
  6. /* -------  ------------- -----------------                     */
  7. /* 14AUG91  Jim Cooper      Initial Creation                     */
  8. /*                                         */
  9. /* Notes:                                     */
  10. /*   2.0 specific program to set the size of a file.  Calls DOS SetFileSize  */
  11. /*   routine.  Useful for hacking the ends off of XModem'd files, when you   */
  12. /*   forgot to turn Auto-Chop on.                         */
  13. /*---------------------------------------------------------------------------*/
  14.  
  15. #include <exec/types.h>
  16. #include <exec/execbase.h>
  17. #include <exec/memory.h>
  18. #include <dos/dosextens.h>
  19. #include <dos/rdargs.h>
  20.  
  21. #include <string.h>
  22.  
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25.  
  26. #include "setsize_rev.h"
  27.  
  28. #define DOSLIB    "dos.library"
  29. #define DOSVER    36L                /* We require AT LEAST V36 of OS */
  30.  
  31. #define EXECBASE (*(struct ExecBase **)4)
  32. #define THISPROC   ((struct Process *)(EXECBASE->ThisTask))
  33. #define Result2(x) THISPROC->pr_Result2 = x
  34.  
  35.  
  36. #define MSG_SETSIZE_FAILED "SetSize failed"
  37.  
  38. #define TEMPLATE  "FILE/A/M,SIZE/K/N,ALL/S" VERSTAG
  39. #define OPT_FILE  0
  40. #define OPT_SIZE  1
  41. #define OPT_CTRLZ 2
  42. #define OPT_ALL   3
  43. #define OPT_COUNT 4
  44.  
  45. #define CTRL_Z '\x1A'
  46.  
  47. int cmd_setsize(void)
  48. {
  49.    struct Library *SysBase = (*((struct Library **) 4));
  50.    struct DosLibrary *DOSBase;
  51.    long temprc, rc, i, size;
  52. á  long opts[OPT_COUNT];
  53.    struct RDargs *rdargs;
  54.    struct AnchorPath __aligned ua;
  55.    BPTR oldlock, curlock, fh;
  56.    char fname[32];
  57.    char *curarg, **argptr, buf;
  58.  
  59.    /*------------------------------------------------------------------------*/
  60.    /* Set up the default return code.                         */
  61.    /*------------------------------------------------------------------------*/
  62.    rc = RETURN_FAIL;
  63.  
  64.    /*------------------------------------------------------------------------*/
  65.    /* And open the dos library for our use.                     */
  66.    /*------------------------------------------------------------------------*/
  67.  á if ((DOSBase = (struct DosLibrary *)OpenLibrary(DOSLIB, DOSVER)))
  68.    {
  69.       /*---------------------------------------------------------------------*/
  70.       /* Clear the options array, just to be on the safe side...         */
  71.       /*---------------------------------------------------------------------*/
  72.       memset((char *)opts, 0, sizeof(opts));
  73.  
  74.       /*---------------------------------------------------------------------*/
  75.       /* Parse the command line.                         */
  76.       /*---------------------------------------------------------------------*/
  77.       rdargs = ReadArgs(TEMPLATE, opts, NULL);
  78.  
  79.       /*---------------------------------------------------------------------*/
  80.       /* If there was an error parsing, print an error message and get out!  */
  81.       /*---------------------------------------------------------------------*/
  82.       if (rdargs == NULL)
  83.       {
  84.      PrintFault(IoErr(), NULL);
  85.       }
  86.       else
  87.       {
  88.      /*------------------------------------------------------------------*/
  89.      /* Now we have to set up the pattern match structure.             */
  90.      /*------------------------------------------------------------------*/
  91.      /* Set the flag which tells the pattern matcher to decode wild      */
  92.      /* cards.                                 */
  93.      /*------------------------------------------------------------------*/
  94.      ua.ap_Flags = APF_DOWILD;
  95.  
  96.      /*------------------------------------------------------------------*/
  97.      /* Tell the matcher to stop if the user presses Ctrl-C.         */
  98.      /*------------------------------------------------------------------*/
  99.      ua.ap_BreakBits = SIGBREAKF_CTRL_C;
  100.  
  101.      /*------------------------------------------------------------------*/
  102.      /* Initialize for MultiArgs handling...                 */
  103.      /*------------------------------------------------------------------*/
  104.      argptr = (char **)opts[OPT_FILE];
  105.  
  106.      /*------------------------------------------------------------------*/
  107.      /* The following while loop handles the MultiArgs spec.         */
  108.      /*------------------------------------------------------------------*/
  109.      while (curarg = *argptr++)
  110.      {
  111.         /*---------------------------------------------------------------*/
  112.         /* Clear our UserAnchor structure to all zeros before going to   */
  113.         /* the next step.                             */
  114.         /*---------------------------------------------------------------*/
  115.         memset(&ua, 0, sizeof(struct AnchorPath));
  116.  
  117.         /*---------------------------------------------------------------*/
  118.         /* Set up a default message leader.                  */
  119.         /*---------------------------------------------------------------*/
  120.         strcpy(fname, MSG_SETSIZE_FAILED);
  121.  
  122.         /*---------------------------------------------------------------*/
  123.         /* Finally, call the matcher.                     */
  124.         /*---------------------------------------------------------------*/
  125.         MatchFirst(curarg, &ua);
  126.         temprc = IoErr();
  127.  
  128.         /*---------------------------------------------------------------*/
  129.         /* Process all matches returned.  If 'MatchFirst()' returned an  */
  130.         /* error, the 'while()' let's us skip all this and fall through  */
  131.         /* the exit code.                             */
  132.         /*---------------------------------------------------------------*/
  133.         while (temprc == 0)
  134.         {
  135.            strcpy(fname, ua.ap_Info.fib_FileName);
  136.  
  137.            if (ua.ap_Info.fib_DirEntryType > 0 && opts[OPT_ALL])
  138.            {
  139.           /*---------------------------------------------------------*/
  140.           /* The flag APF_DIDDIR tells us that we are 'backing out'  */
  141.           /* of a subdirectory... in other words, we have processed  */
  142.           /* all sub-files of that directory and we are moving back  */
  143.           /* to its parent.  If this flag is set, we need to clear   */
  144.           /* it.                             */
  145.           /*---------------------------------------------------------*/
  146.           if (!(ua.ap_Flags & APF_DIDDIR))
  147.           {
  148.              /*------------------------------------------------------*/
  149.              /* If we are resizing ALL files, tell the matcher to    */
  150.              /* enter this directory.                     */
  151.              /*------------------------------------------------------*/
  152.              ua.ap_Flags |= APF_DODIR;
  153.           }
  154.           ua.ap_Flags &= ~APF_DIDDIR;
  155.            }
  156.  
  157.            /*------------------------------------------------------------*/
  158.            /* If we have an error OTHER than that we are out of matches, */
  159.            /* we need to exit IMMEDIATELY!                     */
  160.            /*------------------------------------------------------------*/
  161.            if (temprc && (temprc != ERROR_NO_MORE_ENTRIES))
  162.            {
  163.           break;
  164.            }
  165.  
  166.            /*------------------------------------------------------------*/
  167.            /* Set us to the directory this file lives in.             */
  168.            /*------------------------------------------------------------*/
  169.            curlock = DupLock(ua.ap_Current->an_Lock);
  170.            oldlock = CurrentDir(curlock);
  171.  
  172.            /*------------------------------------------------------------*/
  173.            /* We must open the file for SetFileSize() to work.           */
  174.            /*------------------------------------------------------------*/
  175.            if ((fh = Open(fname, MODE_OLDFILE)) == NULL)
  176.            {
  177.           temprc = IoErr();
  178.           CurrentDir(oldlock);
  179.           UnLock(curlock);
  180.           break;
  181.            }
  182.  
  183.            /*------------------------------------------------------------*/
  184.            /* Now, we're ready to set the new size.  If the user didn't  */
  185.            /* give us a SIZE, we will assume he simply wants us to strip */
  186.            /* ^Z's from the end of the file.                             */
  187.            /*------------------------------------------------------------*/
  188.            if (opts[OPT_SIZE] == NULL)
  189.            {
  190.           /*---------------------------------------------------------*/
  191.           /* Find the beginning of the ^Z padding at the end of the  */
  192.           /* file.                             */
  193.           /*---------------------------------------------------------*/
  194.           Seek(fh, 0, OFFSET_END);
  195.           Seek(fh, -1, OFFSET_CURRENT);
  196.           while (Read(fh, &buf, 1))
  197.           {
  198.              if (buf != CTRL_Z)
  199.              {
  200.             break;
  201.              }
  202.              Seek(fh, -2, OFFSET_CURRENT);
  203.           }
  204.           size = Seek(fh, 0, OFFSET_CURRENT);
  205.            }
  206.            else
  207.            {
  208.           /*---------------------------------------------------------*/
  209.           /* O.K., so they gave us a size, let's use it!             */
  210.           /*---------------------------------------------------------*/
  211.           size = *((long *)(opts[OPT_SIZE]));
  212.            }
  213.  
  214.            /*------------------------------------------------------------*/
  215.            /* Tell DOS to set the size.                     */
  216.            /*------------------------------------------------------------*/
  217.            if ((i = SetFileSize(fh, size, OFFSET_BEGINNING)) == -1)
  218.            {
  219.           temprc = IoErr();
  220.            }
  221.  
  222.            /*------------------------------------------------------------*/
  223.            /* Close the file (whether it worked or not!).                */
  224.            /*------------------------------------------------------------*/
  225.            Close(fh);
  226.  
  227.            /*------------------------------------------------------------*/
  228.            /* Now change the directory back to where it was when we got  */
  229.            /* started.                             */
  230.            /*------------------------------------------------------------*/
  231.            CurrentDir(oldlock);
  232.            UnLock(curlock);
  233.  
  234.            if (i == -1)
  235.            {
  236.           /*---------------------------------------------------------*/
  237.           /* If 'SetFileSize()' returned an error, we have to get    */
  238.           /* out and tell the user about it!                 */
  239.           /*---------------------------------------------------------*/
  240.           break;
  241.            }
  242.  
  243.            /*------------------------------------------------------------*/
  244.            /* Now get the next file which matches the given pattern.     */
  245.            /*------------------------------------------------------------*/
  246.            MatchNext(&ua);
  247.            temprc = IoErr();
  248.         }
  249.  
  250.         /*---------------------------------------------------------------*/
  251.         /* If the only error we had was that we ran out of files to      */
  252.         /* resize, we are doing fine!  Set the return code so the user   */
  253.         /* knows everything went well.                     */
  254.         /*---------------------------------------------------------------*/
  255.         if (temprc == ERROR_NO_MORE_ENTRIES)
  256.         {
  257.            rc = RETURN_OK;
  258.         }
  259.         else
  260.         {
  261.            PrintFault(temprc,fname);
  262.  
  263.            /*------------------------------------------------------------*/
  264.            /* If the user hit Ctrl-C, we have to warn him that he is     */
  265.            /* being rude!                             */
  266.            /*------------------------------------------------------------*/
  267.            if (temprc == ERROR_BREAK)
  268.            {
  269.           rc = RETURN_WARN;
  270.            }
  271.            else
  272.            {
  273.           /*---------------------------------------------------------*/
  274.           /* If there was any other error, FAIL!!!             */
  275.           /*---------------------------------------------------------*/
  276.           rc = RETURN_FAIL;
  277.            }
  278.         }
  279.         /*---------------------------------------------------------------*/
  280.         /* We have to clean up after ourselves.                 */
  281.         /*---------------------------------------------------------------*/
  282.         MatchEnd(&ua);
  283.      }
  284.      FreeArgs(rdargs);
  285.       }
  286.       CloseLibrary((struct Library *)DOSBase);
  287.    }
  288.    else
  289.    {
  290.       /*---------------------------------------------------------------------*/
  291.       /* They tried to run us under the wrong version of the OS.  We need to */
  292.       /* exit gracefully, yet still let them know what went wrong...         */
  293.       /*---------------------------------------------------------------------*/
  294.       Result2(ERROR_INVALID_RESIDENT_LIBRARY);
  295.    }
  296.    return(rc);
  297. }
  298.