#include <proto/exec.h>
#include <proto/dos.h>

/***********************************************/

struct DosLibrary *DOSBase;

struct
   {
      char *From;
      char *To;
      long Soft;
      long Force;
   } Arguments;

struct FileInfoBlock __aligned FileInfoBlock;
struct RDArgs *RDArgs;
BPTR Dest;

char VersionString[]="$VER: MakeLink 1.0 (30.01.93)";

/***********************************************/

BOOL CheckLoop(void);

/***********************************************/

int __saveds main(void)

{
   int RetVal;

   RetVal=0;
   if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37))
      {
         if (RDArgs=ReadArgs("FROM/A,TO/A,SOFT/S,FORCE/S",(long *)&Arguments,NULL))
            {
               if (Dest=Lock(Arguments.To,ACCESS_READ))
                  {
                     if (Examine(Dest,&FileInfoBlock))
                        {
                           if (FileInfoBlock.fib_DirEntryType>0)
                              {
                                 if (!Arguments.Force)
                                    {
                                       VPrintf("Links to directories require use of the FORCE keyword\n",NULL);
                                       RetVal=10;
                                    }
                                 else if (!CheckLoop())
                                    {
                                       RetVal=10;
                                    }
                              }
                           if (!RetVal)
                              {
                                 if (!MakeLink(Arguments.From,(long)(Arguments.Soft ? Arguments.To : Dest),Arguments.Soft))
                                    {
                                       PrintFault(IoErr(),NULL);
                                       RetVal=10;
                                    }
                              }
                        }
                     else
                        {
                           PrintFault(IoErr(),Arguments.To);
                           RetVal=10;
                        }
                     UnLock(Dest);
                  }
               else
                  {
                     PrintFault(IoErr(),Arguments.To);
                     RetVal=10;
                  }
               FreeArgs(RDArgs);
            }
         CloseLibrary(DOSBase);
      }
   else
      {
         RetVal=100;
      }
   return(RetVal);
}

/***********************************************/

BOOL CheckLoop(void)

{
   char *Position;
   BPTR Parent, Source;
   char Saved;
   long Result;

   Position=PathPart(Arguments.From);
   Saved=*Position;
   *Position='\0';
   if (Source=Lock(Arguments.From,ACCESS_READ))
      {
         do
            {
               Parent=ParentDir(Source);
               Result=SameLock(Source,Dest);
               UnLock(Source);
               if (Result==LOCK_SAME)
                  {
                     UnLock(Parent);
                     *Position=Saved;
                     VPrintf("Link loop from %s to %s not allowed\n",(long *)&Arguments.From);
                     return(FALSE);
                  }
               Source=Parent;
            }
         while (Source);
      }
   else
      {
         PrintFault(IoErr(),Arguments.From);
         *Position=Saved;
         return(FALSE);
      }
   *Position=Saved;
   return(TRUE);
}
