home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol2 / ii-49 / dircomp.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  14KB  |  444 lines

  1. ;/* DirComp.c - AmigaMail Directory Compare example using MatchFirst()/Next().
  2. sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 DirComp.c
  3. slink from DirComp.o to DirComp lib lib:amiga.lib ; if you don't have pragmas
  4. quit
  5.  *
  6.  * Pure code if pragmas are used.
  7.  * Monday, 15-Jul-91 16:07:31, Ewout
  8.  *
  9.  * Compiled with SAS/C 6.56
  10.  */
  11. /*
  12. Copyright (c) 1991 Commodore-Amiga, Inc.
  13.  
  14. This example is provided in electronic form by Commodore-Amiga,
  15. Inc. for use with the Amiga Mail Volume II technical publication.
  16. Amiga Mail Volume II contains additional information on the correct
  17. usage of the techniques and operating system functions presented in
  18. these examples.  The source and executable code of these examples may
  19. only be distributed in free electronic form, via bulletin board or
  20. as part of a fully non-commercial and freely redistributable
  21. diskette.  Both the source and executable code (including comments)
  22. must be included, without modification, in any copy.  This example
  23. may not be published in printed form or distributed with any
  24. commercial product. However, the programming techniques and support
  25. routines set forth in these examples may be used in the development
  26. of original executable software products for Commodore Amiga
  27. computers.
  28.  
  29. All other rights reserved.
  30.  
  31. This example is provided "as-is" and is subject to change; no
  32. warranties are made.  All use is at your own risk. No liability or
  33. responsibility is assumed.
  34. */
  35.  
  36. #include <exec/memory.h>
  37. #include <dos/dosextens.h>
  38. #include <dos/rdargs.h>
  39.  
  40. #include <clib/exec_protos.h>
  41. #include <clib/dos_protos.h>
  42.  
  43. /* undef PRAGMAS if you don't have them */
  44. #undef PRAGMAS
  45. #ifdef PRAGMAS
  46. #include <pragmas/exec_pragmas.h>
  47. #include <pragmas/dos_pragmas.h>
  48. #else
  49. struct ExecBase *SysBase;
  50. struct DosLibrary *DOSBase;
  51.  
  52. #endif
  53.  
  54. /* Default size of buffer to build full targetpaths in */
  55. #define BUFFERSIZE 256
  56.  
  57. static UBYTE   *VersTag = "\0$VER: DirComp 37.1 (15.07.91)";
  58.  
  59. LONG            main(VOID);
  60. LONG            GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize);
  61. UBYTE          *ItsWild(UBYTE * string);
  62. UWORD           StrLen(UBYTE *);
  63.  
  64. LONG
  65. main(VOID)
  66. {
  67. #ifdef PRAGMAS
  68.   struct DosLibrary *DOSBase;
  69.  
  70. #endif
  71.   struct RDArgs  *readargs;
  72.   LONG            rargs[5], vargs[5];
  73.   UBYTE          *source, *target;
  74.   ULONG           buffersize = 0;
  75.   UBYTE          *sourcedir, *targetdir;
  76.   UBYTE          *textbuffer, *tmp, *tmp1, *tmp2;
  77.   struct AnchorPath *anchorpath;
  78.   struct FileInfoBlock *fib, *targetfib;
  79.   struct Process *process;
  80.   APTR            wptr;
  81.   BPTR            dirlock, filelock;
  82.   BOOL            checkdatestamp, all;
  83.   LONG            date, error, rc = 0;
  84.  
  85. #ifndef PRAGMAS
  86.   /* set up SysBase */
  87.   SysBase = (*((struct Library **) 4));
  88. #endif
  89.  
  90.   /* Fail silently if < 37 */
  91.   if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
  92.   {
  93.     rargs[0] = 0L;
  94.     rargs[1] = 0L;
  95.     rargs[2] = 0L;
  96.     rargs[3] = 0L;
  97.     rargs[4] = 0L;
  98.  
  99.     if (readargs = ReadArgs("SOURCE/A,TARGET/A,DATE/S,ALL/S,BUFFER/K/N", rargs, NULL))
  100.     {
  101.  
  102.       source = (UBYTE *) rargs[0];
  103.       target = (UBYTE *) rargs[1];
  104.       checkdatestamp = (BOOL) rargs[2];
  105.       all = (BOOL) rargs[3];
  106.  
  107.       if (!(sourcedir = AllocMem(StrLen(source) + 129, MEMF_CLEAR)))
  108.         error = ERROR_NO_FREE_STORE;
  109.       else
  110.       {
  111.         /* 128 bytes to print informative text */
  112.         textbuffer = sourcedir + StrLen(source) + 1;
  113.  
  114.         /* use user specified buffersize if indicated */
  115.         if (rargs[4])
  116.           buffersize = *((LONG *) rargs[4]);
  117.         if (buffersize < BUFFERSIZE || buffersize > 4096)
  118.           buffersize = BUFFERSIZE;
  119.  
  120.         if (!(targetdir = AllocMem(buffersize, MEMF_CLEAR)))
  121.           error = ERROR_NO_FREE_STORE;
  122.         else
  123.         {
  124.           if (!(targetfib = AllocDosObject(DOS_FIB, NULL)))
  125.             error = ERROR_NO_FREE_STORE;
  126.           else
  127.           {
  128.  
  129.             /*
  130.              * Check if source and target are valid.
  131.              *
  132.              * Separate source path from pattern (if any). Use the source path figure
  133.              * out what to append to the target.
  134.              */
  135.  
  136.             /* No requesters */
  137.             process = (struct Process *) FindTask(NULL);
  138.             wptr = process->pr_WindowPtr;
  139.             process->pr_WindowPtr = (APTR) - 1L;
  140.  
  141.             if ((error = GetPath(source, sourcedir, StrLen(source) + 1) == 0))
  142.             {
  143.               if (!(dirlock = Lock(sourcedir, SHARED_LOCK)))
  144.                 error = IoErr();
  145.               else
  146.               {
  147.                 UnLock(dirlock);
  148.                 if (!(dirlock = Lock(target, SHARED_LOCK)))
  149.                   error = IoErr();
  150.                 else
  151.                 {
  152.                   UnLock(dirlock);
  153.  
  154.                   if (anchorpath = AllocMem(sizeof(struct AnchorPath) + buffersize,
  155.                                             MEMF_CLEAR))
  156.                   {
  157.                     anchorpath->ap_Strlen = buffersize;
  158.  
  159.                     /* Allow to break on CTRL-C */
  160.                     anchorpath->ap_BreakBits = SIGBREAKF_CTRL_C;
  161.  
  162.                     if ((error = MatchFirst(source, anchorpath)) == 0)
  163.                     {
  164.  
  165.                       do
  166.                       {
  167.                         fib = &(anchorpath->ap_Info);
  168.  
  169.                         /*
  170.                          * APF_DIDDIR indicates that we used returned from a
  171.                          * directory. In that case we clear both APF_DIDDIR and
  172.                          * APF_DODIR, so we can start afresh with the next one.
  173.                          */
  174.  
  175.  
  176.                         if (anchorpath->ap_Flags & APF_DIDDIR)
  177.                           anchorpath->ap_Flags &= ~(APF_DODIR | APF_DIDDIR);
  178.                         else
  179.                         {
  180.  
  181.                           /*
  182.                            * Make a filename for the target directory. First copy
  183.                            * targetname into buffer.
  184.                            */
  185.                           targetdir[0] = '\0';
  186.                           tmp = targetdir;
  187.                           tmp1 = target;
  188.                           while (*tmp++ = *tmp1++);
  189.  
  190.                           /* Skip sourcename in ap_Buf */
  191.                           tmp1 = sourcedir;
  192.                           tmp2 = anchorpath->ap_Buf;
  193.                           while (*tmp1++ == *tmp2++);
  194.                           /* Skip back 1 if not after a separator */
  195.                           if (*(tmp2 - 1) != '/')
  196.                             tmp2--;
  197.  
  198.                           /*
  199.                            * We hit the source itself, don't compare it, but enter
  200.                            * it.
  201.                            */
  202.                           if (*tmp2 == 0)
  203.                           {
  204.                             anchorpath->ap_Flags |= APF_DODIR;
  205.                             continue;
  206.                           }
  207.  
  208.                           /* Build it */
  209.                           if (AddPart(targetdir, tmp2, buffersize - 1))
  210.                             vargs[0] = (LONG) targetdir;
  211.                           else
  212.                           {
  213.                             PrintFault(ERROR_NO_FREE_STORE, NULL);
  214.                             break;
  215.                           }
  216.  
  217.                           /* Lock it and check it out */
  218.                           if (filelock = Lock(targetdir, SHARED_LOCK))
  219.                           {
  220.                             if ((Examine(filelock, targetfib)) == DOSTRUE)
  221.                             {
  222.                               textbuffer[0] = '\0';
  223.  
  224.                               /*
  225.                                * To get nice output without work I use AddPart() to
  226.                                * add differences to the textbuffer.
  227.                                */
  228.                               if (targetfib->fib_DirEntryType
  229.                                   != fib->fib_DirEntryType)
  230.                                 AddPart(textbuffer, "of different type", 128);
  231.                               else
  232.                               {
  233.                                 if (targetfib->fib_Size < fib->fib_Size)
  234.                                   AddPart(textbuffer, "smaller", 128);
  235.                                 else if (targetfib->fib_Size > fib->fib_Size)
  236.                                   AddPart(textbuffer, "larger", 128);
  237.  
  238.                                 if (checkdatestamp)
  239.                                 {
  240.                                   date = CompareDates((struct DateStamp *)
  241.                                         & (fib->fib_Date),
  242.                                       (struct DateStamp *) & (targetfib->fib_Date));
  243.                                   if (date < 0)
  244.                                     AddPart(textbuffer, "older", 128);
  245.                                   else if (date > 0)
  246.                                     AddPart(textbuffer, "newer", 128);
  247.                                 }
  248.                               }
  249.  
  250.  
  251.                               if (*textbuffer != NULL)
  252.                               {
  253.                                 vargs[1] = (LONG) textbuffer;
  254.                                 VFPrintf(Output(), "%s: object %s\n", vargs);
  255.                               }
  256.                             }
  257.                             else
  258.                               PrintFault(IoErr(), targetdir);
  259.                             UnLock(filelock);
  260.                           }
  261.                           else
  262.                           {
  263.                             PrintFault(IoErr(), targetdir);
  264.  
  265.                             /*
  266.                              * If and error occured on a directory name, don't enter
  267.                              * it.
  268.                              */
  269.                             if (fib->fib_DirEntryType > 0)
  270.                               continue;
  271.  
  272.                           }
  273.  
  274.                           /*
  275.                            * If the ALL keyword has been used and this is a directory
  276.                            * enter it by setting the APF_DODIR flag.
  277.                            */
  278.  
  279.                           if (fib->fib_DirEntryType > 0 && all != FALSE)
  280.                             anchorpath->ap_Flags |= APF_DODIR;
  281.  
  282.                         }
  283.  
  284.                       } while ((error = MatchNext(anchorpath)) == 0);
  285.                     }
  286.  
  287.                     MatchEnd(anchorpath);
  288.  
  289.                     if (error == ERROR_NO_MORE_ENTRIES)
  290.                       error = 0;
  291.  
  292.                     FreeMem(anchorpath, sizeof(struct AnchorPath) + buffersize);
  293.                   }
  294.                 }
  295.               }
  296.               /* Reset windowpointer */
  297.               process->pr_WindowPtr = wptr;
  298.             }
  299.             else
  300.               PrintFault(error, NULL);
  301.             FreeDosObject(DOS_FIB, targetfib);
  302.           }
  303.           FreeMem(targetdir, buffersize);
  304.         }
  305.         FreeMem(sourcedir, StrLen(sourcedir) + 129);
  306.       }
  307.       FreeArgs(readargs);
  308.     }
  309.     else
  310.       error = IoErr();
  311.  
  312.     SetIoErr(error);
  313.     if (error)
  314.     {
  315.       PrintFault(error, NULL);
  316.       if (error = ERROR_BREAK)
  317.         rc = RETURN_WARN;
  318.       else
  319.         error = RETURN_FAIL;
  320.     }
  321.     CloseLibrary((struct Library *) DOSBase);
  322.   }
  323.   return (rc);
  324. }
  325.  
  326. LONG
  327. GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize)
  328. {
  329.   UBYTE          *pathpart, *filepart;
  330.   UBYTE          *tmp1, *tmp2;
  331.   BPTR            lock;
  332.   struct FileInfoBlock *fib;
  333.   LONG            error = 0;
  334.  
  335.   /* Open own copy of dos.library if pragmas are used so it's standalone */
  336. #ifdef PRAGMAS
  337.   struct Library *DOSBase;
  338.  
  339.   if (!(DOSBase = OpenLibrary("dos.library", 36)))
  340.     return (1);
  341. #endif
  342.  
  343.   /*
  344.    * If there seems to be no path, the pathpart will point to the filepart too, so we
  345.    * need to check for that.
  346.    */
  347.   filepart = FilePart(path);
  348.   pathpart = PathPart(path);
  349.  
  350.   /*
  351.    * This also handles cases where there is only a volume/device name, only a
  352.    * directory name or a combo of those.
  353.    */
  354.   if (pathpart == path)
  355.   {
  356.  
  357.     /*
  358.      * There seems to be only one component. Copy it if it is not wild. Caller will
  359.      * have to check whether if it exists and if it is a file or directory.
  360.      */
  361.     if (!(ItsWild(pathpart)))
  362.       pathpart = NULL;
  363.   }
  364.  
  365.   if (pathpart != path)
  366.   {
  367.  
  368.     /*
  369.      * If pathpart equals filepart (pointer wise) then there is only one component
  370.      * (possible preceeded by a volume name).
  371.      */
  372.     if (pathpart == filepart)
  373.     {
  374.       if (!(ItsWild(pathpart)))
  375.         pathpart = NULL;
  376.     }
  377.     else
  378.     {
  379.       /* Try to lock it to determine if the last component is a directory. */
  380.       if (lock = Lock(path, SHARED_LOCK))
  381.       {
  382.         if (fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR))
  383.         {
  384.           if ((Examine(lock, fib)) == DOSTRUE)
  385.           {
  386.             /* Hey it's a directory after all */
  387.             if (fib->fib_DirEntryType > 0)
  388.               pathpart = NULL;
  389.           }
  390.           FreeMem(fib, sizeof(struct FileInfoBlock));
  391.         }
  392.         UnLock(lock);
  393.       }                                          /* else treat it as a filename */
  394.     }
  395.  
  396.     /* Copy the pathpart in the buffer */
  397.     tmp1 = buffer;
  398.     tmp2 = path;
  399.     while ((*tmp1++ = *tmp2++) && (tmp2 != pathpart))
  400.     {
  401.       if (tmp1 == (buffer + buffersize))
  402.       {
  403.         error = ERROR_NO_FREE_STORE;
  404.         break;
  405.       }
  406.     }
  407.     *tmp1 = '\0';                                /* NULL terminate. */
  408.   }
  409.  
  410. #ifdef PRAGMAS
  411.   CloseLibrary(DOSBase);
  412. #endif
  413.   return (error);
  414. }
  415.  
  416. UBYTE          *
  417. ItsWild(UBYTE * string)
  418. {
  419.   static UBYTE   *special = "#?*%([|";
  420.   UBYTE          *tmp = string;
  421.   COUNT           i;
  422.  
  423.   do
  424.   {
  425.     for (i = 0; special[i] != '\0'; i++)
  426.     {
  427.       if (*tmp == special[i])
  428.         return (tmp);
  429.     }
  430.     tmp++;
  431.   } while (*tmp);
  432.  
  433.   return (NULL);
  434. }
  435.  
  436. UWORD
  437. StrLen(UBYTE * string)
  438. {
  439.   UBYTE          *length = string + 1;
  440.  
  441.   while (*string++ != '\0');
  442.   return ((UWORD) (string - length));
  443. }
  444.