/*
 *	showlocks.c
 *
 * Written 13-Mar-88 by Chuck McManis
 * Copyright 1988 Charles McManis, All rights reserved. 
 * This file may be freely redistributed and used as long as this notice remains
 * with it.
 *
 * This program will list out all of the locks that are being held on the 
 * specified volume. You can enter either a volume name or disk device.
 *
 * The output of this program is :
 *	Lock #0 : 'Path'
 *	Lock #1 : 'Path'
 *	...
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

extern struct DosLibrary *DOSBase;
char	*GetPath();

void
main(argc,argv)

int	argc;
char	*argv[];

{
  int			j,NumVols;
  struct DeviceList	*dl,*vols[20];
  struct RootNode	*rn;
  struct DosInfo	*di;
  char			*t,tmpname[40];


  if (argc != 2) {
    printf("Usage is : ShowLocks Volumename:\n");
    exit(0);
  }

  NumVols=0;
  if (strcmp(argv[1],"all") == 0) {
    /* Find the device list */
    rn = (struct RootNode *)DOSBase->dl_Root;
    di = (struct DosInfo  *)BADDR(rn->rn_Info);
    /* While searching the list we lock out Multitasking */
    Forbid();
    for (dl = (struct DeviceList *)BADDR(di->di_DevInfo); dl;
	 dl = (struct DeviceList *)BADDR(dl->dl_Next)) 
      if (dl->dl_Type == DLT_VOLUME) vols[NumVols++] = dl;
    Permit(); /* Back to multitasking mode */
  }

  printf("Lock Monitor, prints out outstanding locks on a given volume.\n");
  if (NumVols) {
    for (j=0; j<NumVols; j++) {
      t = (char *)BADDR(vols[j]->dl_Name);
      t++; /* point past the length */
      strcpy(tmpname,t);   /* Put the name in here... */
      strcat(tmpname,":"); /* and append a colon ... */
      /*BUG*BUG*BUG*BUG*BUG*BUG*BUG*BUG*BUG*/
      /* Delete this line when you get 1.3 */
      if (strcmp(t,"RAM Disk") == 0) continue;
      if (vols[j]->dl_Task) {
        printf("Locks held on Volume %s\n",tmpname);
	PrintLocks(tmpname);
      } else printf("Volume %s is not mounted.\n",tmpname);
    } 
  } else {
    printf("Locks held on Volume %s\n",argv[1]);
    PrintLocks(argv[1]);
  }
}

PrintLocks(str)

char *str;
{
  ULONG			thislock;
  struct FileLock 	*fl;
  int			i;

  thislock = Lock(str,ACCESS_READ);
  i = 0;
  for (fl = (struct FileLock *)(BADDR(thislock)); fl;
       fl = (struct FileLock *)(BADDR(fl->fl_Link))) 
      printf("    Lock #%d : '%s'\n",i++,GetPath((ULONG)(fl) >> 2));
  if (thislock) UnLock(thislock);
  return(0);
}

/*
 * Function GetPath()
 *
 * This function will return a pointer to a string with the path of
 * the passed lock.
 */
char *
GetPath(Lck)

ULONG	Lck;

{

  static char	LockPath[256];
  UWORD		FDATA[sizeof(struct FileInfoBlock)/2+1];
  ULONG		CurLock,NewLock;
  char		*s;
  struct FileInfoBlock	*fi;


  /* Initialize LockPath to the NULL string */
  LockPath[0]  = '\0';
  if ((Lck == 0) || (Lck == ~0L))
    return(LockPath); /* If Lock is on root (0) return */

  /* Initialize fi so that it is on a long word boundary */
  if ((long)(FDATA) & 2) fi = (struct FileInfoBlock *)(&FDATA[1]);
  else fi = (struct FileInfoBlock *)FDATA;

  CurLock = DupLock(Lck); /* Make a copy of the Lock passed */
  while (CurLock != NULL) {
    Examine(CurLock,fi);
    if ((CurLock != 0) && (fi->fib_DiskKey != 0)) {
      if (strlen(LockPath)) strins(LockPath,"/");
      strins(LockPath,fi->fib_FileName);
    }
    NewLock = ParentDir(CurLock);
    UnLock(CurLock);
    CurLock = NewLock;
  }
  /* Fix up the volume name to include a colon */
  for (s = LockPath; *s; s++) if (*s == '/') {*s = ':'; break;}
  if (!(*s)) strcat(LockPath,":"); 
  return(LockPath);
}
