home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------------*/
- /* Command: SetSize */
- /* Author: James E. Cooper Jr. */
- /* Change History: */
- /* Date Person Action */
- /* ------- ------------- ----------------- */
- /* 14AUG91 Jim Cooper Initial Creation */
- /* */
- /* Notes: */
- /* 2.0 specific program to set the size of a file. Calls DOS SetFileSize */
- /* routine. Useful for hacking the ends off of XModem'd files, when you */
- /* forgot to turn Auto-Chop on. */
- /*---------------------------------------------------------------------------*/
-
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <dos/dosextens.h>
- #include <dos/rdargs.h>
-
- #include <string.h>
-
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- #include "setsize_rev.h"
-
- #define DOSLIB "dos.library"
- #define DOSVER 36L /* We require AT LEAST V36 of OS */
-
- #define EXECBASE (*(struct ExecBase **)4)
- #define THISPROC ((struct Process *)(EXECBASE->ThisTask))
- #define Result2(x) THISPROC->pr_Result2 = x
-
-
- #define MSG_SETSIZE_FAILED "SetSize failed"
-
- #define TEMPLATE "FILE/A/M,SIZE/K/N,ALL/S" VERSTAG
- #define OPT_FILE 0
- #define OPT_SIZE 1
- #define OPT_CTRLZ 2
- #define OPT_ALL 3
- #define OPT_COUNT 4
-
- #define CTRL_Z '\x1A'
-
- int cmd_setsize(void)
- {
- struct Library *SysBase = (*((struct Library **) 4));
- struct DosLibrary *DOSBase;
- long temprc, rc, i, size;
- á long opts[OPT_COUNT];
- struct RDargs *rdargs;
- struct AnchorPath __aligned ua;
- BPTR oldlock, curlock, fh;
- char fname[32];
- char *curarg, **argptr, buf;
-
- /*------------------------------------------------------------------------*/
- /* Set up the default return code. */
- /*------------------------------------------------------------------------*/
- rc = RETURN_FAIL;
-
- /*------------------------------------------------------------------------*/
- /* And open the dos library for our use. */
- /*------------------------------------------------------------------------*/
- á if ((DOSBase = (struct DosLibrary *)OpenLibrary(DOSLIB, DOSVER)))
- {
- /*---------------------------------------------------------------------*/
- /* Clear the options array, just to be on the safe side... */
- /*---------------------------------------------------------------------*/
- memset((char *)opts, 0, sizeof(opts));
-
- /*---------------------------------------------------------------------*/
- /* Parse the command line. */
- /*---------------------------------------------------------------------*/
- rdargs = ReadArgs(TEMPLATE, opts, NULL);
-
- /*---------------------------------------------------------------------*/
- /* If there was an error parsing, print an error message and get out! */
- /*---------------------------------------------------------------------*/
- if (rdargs == NULL)
- {
- PrintFault(IoErr(), NULL);
- }
- else
- {
- /*------------------------------------------------------------------*/
- /* Now we have to set up the pattern match structure. */
- /*------------------------------------------------------------------*/
- /* Set the flag which tells the pattern matcher to decode wild */
- /* cards. */
- /*------------------------------------------------------------------*/
- ua.ap_Flags = APF_DOWILD;
-
- /*------------------------------------------------------------------*/
- /* Tell the matcher to stop if the user presses Ctrl-C. */
- /*------------------------------------------------------------------*/
- ua.ap_BreakBits = SIGBREAKF_CTRL_C;
-
- /*------------------------------------------------------------------*/
- /* Initialize for MultiArgs handling... */
- /*------------------------------------------------------------------*/
- argptr = (char **)opts[OPT_FILE];
-
- /*------------------------------------------------------------------*/
- /* The following while loop handles the MultiArgs spec. */
- /*------------------------------------------------------------------*/
- while (curarg = *argptr++)
- {
- /*---------------------------------------------------------------*/
- /* Clear our UserAnchor structure to all zeros before going to */
- /* the next step. */
- /*---------------------------------------------------------------*/
- memset(&ua, 0, sizeof(struct AnchorPath));
-
- /*---------------------------------------------------------------*/
- /* Set up a default message leader. */
- /*---------------------------------------------------------------*/
- strcpy(fname, MSG_SETSIZE_FAILED);
-
- /*---------------------------------------------------------------*/
- /* Finally, call the matcher. */
- /*---------------------------------------------------------------*/
- MatchFirst(curarg, &ua);
- temprc = IoErr();
-
- /*---------------------------------------------------------------*/
- /* Process all matches returned. If 'MatchFirst()' returned an */
- /* error, the 'while()' let's us skip all this and fall through */
- /* the exit code. */
- /*---------------------------------------------------------------*/
- while (temprc == 0)
- {
- strcpy(fname, ua.ap_Info.fib_FileName);
-
- if (ua.ap_Info.fib_DirEntryType > 0 && opts[OPT_ALL])
- {
- /*---------------------------------------------------------*/
- /* The flag APF_DIDDIR tells us that we are 'backing out' */
- /* of a subdirectory... in other words, we have processed */
- /* all sub-files of that directory and we are moving back */
- /* to its parent. If this flag is set, we need to clear */
- /* it. */
- /*---------------------------------------------------------*/
- if (!(ua.ap_Flags & APF_DIDDIR))
- {
- /*------------------------------------------------------*/
- /* If we are resizing ALL files, tell the matcher to */
- /* enter this directory. */
- /*------------------------------------------------------*/
- ua.ap_Flags |= APF_DODIR;
- }
- ua.ap_Flags &= ~APF_DIDDIR;
- }
-
- /*------------------------------------------------------------*/
- /* If we have an error OTHER than that we are out of matches, */
- /* we need to exit IMMEDIATELY! */
- /*------------------------------------------------------------*/
- if (temprc && (temprc != ERROR_NO_MORE_ENTRIES))
- {
- break;
- }
-
- /*------------------------------------------------------------*/
- /* Set us to the directory this file lives in. */
- /*------------------------------------------------------------*/
- curlock = DupLock(ua.ap_Current->an_Lock);
- oldlock = CurrentDir(curlock);
-
- /*------------------------------------------------------------*/
- /* We must open the file for SetFileSize() to work. */
- /*------------------------------------------------------------*/
- if ((fh = Open(fname, MODE_OLDFILE)) == NULL)
- {
- temprc = IoErr();
- CurrentDir(oldlock);
- UnLock(curlock);
- break;
- }
-
- /*------------------------------------------------------------*/
- /* Now, we're ready to set the new size. If the user didn't */
- /* give us a SIZE, we will assume he simply wants us to strip */
- /* ^Z's from the end of the file. */
- /*------------------------------------------------------------*/
- if (opts[OPT_SIZE] == NULL)
- {
- /*---------------------------------------------------------*/
- /* Find the beginning of the ^Z padding at the end of the */
- /* file. */
- /*---------------------------------------------------------*/
- Seek(fh, 0, OFFSET_END);
- Seek(fh, -1, OFFSET_CURRENT);
- while (Read(fh, &buf, 1))
- {
- if (buf != CTRL_Z)
- {
- break;
- }
- Seek(fh, -2, OFFSET_CURRENT);
- }
- size = Seek(fh, 0, OFFSET_CURRENT);
- }
- else
- {
- /*---------------------------------------------------------*/
- /* O.K., so they gave us a size, let's use it! */
- /*---------------------------------------------------------*/
- size = *((long *)(opts[OPT_SIZE]));
- }
-
- /*------------------------------------------------------------*/
- /* Tell DOS to set the size. */
- /*------------------------------------------------------------*/
- if ((i = SetFileSize(fh, size, OFFSET_BEGINNING)) == -1)
- {
- temprc = IoErr();
- }
-
- /*------------------------------------------------------------*/
- /* Close the file (whether it worked or not!). */
- /*------------------------------------------------------------*/
- Close(fh);
-
- /*------------------------------------------------------------*/
- /* Now change the directory back to where it was when we got */
- /* started. */
- /*------------------------------------------------------------*/
- CurrentDir(oldlock);
- UnLock(curlock);
-
- if (i == -1)
- {
- /*---------------------------------------------------------*/
- /* If 'SetFileSize()' returned an error, we have to get */
- /* out and tell the user about it! */
- /*---------------------------------------------------------*/
- break;
- }
-
- /*------------------------------------------------------------*/
- /* Now get the next file which matches the given pattern. */
- /*------------------------------------------------------------*/
- MatchNext(&ua);
- temprc = IoErr();
- }
-
- /*---------------------------------------------------------------*/
- /* If the only error we had was that we ran out of files to */
- /* resize, we are doing fine! Set the return code so the user */
- /* knows everything went well. */
- /*---------------------------------------------------------------*/
- if (temprc == ERROR_NO_MORE_ENTRIES)
- {
- rc = RETURN_OK;
- }
- else
- {
- PrintFault(temprc,fname);
-
- /*------------------------------------------------------------*/
- /* If the user hit Ctrl-C, we have to warn him that he is */
- /* being rude! */
- /*------------------------------------------------------------*/
- if (temprc == ERROR_BREAK)
- {
- rc = RETURN_WARN;
- }
- else
- {
- /*---------------------------------------------------------*/
- /* If there was any other error, FAIL!!! */
- /*---------------------------------------------------------*/
- rc = RETURN_FAIL;
- }
- }
- /*---------------------------------------------------------------*/
- /* We have to clean up after ourselves. */
- /*---------------------------------------------------------------*/
- MatchEnd(&ua);
- }
- FreeArgs(rdargs);
- }
- CloseLibrary((struct Library *)DOSBase);
- }
- else
- {
- /*---------------------------------------------------------------------*/
- /* They tried to run us under the wrong version of the OS. We need to */
- /* exit gracefully, yet still let them know what went wrong... */
- /*---------------------------------------------------------------------*/
- Result2(ERROR_INVALID_RESIDENT_LIBRARY);
- }
- return(rc);
- }
-