home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
001-099
/
ff019.lzh
/
LockMon
/
LockMon.c
next >
Wrap
C/C++ Source or Header
|
1986-04-08
|
7KB
|
189 lines
/*
* LockMon: determine the number of locks associated with a filesystem
* task. I haven't figured out how to do this directly, so I
* cheat -- if a volume is offlined, then a linked list of locks
* is transferred to the volume's DeviceList entry. Note that
* this isn't a permanent solution -- it won't work with hard
* disks or RAM:, for instance.
*
* Warnings: Uses Aztec C library internal DOSBase, which holds the
* DOS library base pointer. Lattice does the same.
* And ... this implementation is guesswork. Caveat emptor!
*
* Request: Anybody know a better way?
*
* Perpetrator: Dewi Williams ..!ihnp4!druca!dewi.
* Extremely public domain.
*
* Version: 1.0
*/
#include <stdio.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <exec/memory.h>
/* Defines */
/* Change typeless BCPL BPTR to typed C (for struct pointers). Don't
* use this define on an APTR, that's only a badly disguised void *.
*/
#define BPTR_TO_C(strtag, var) ((struct strtag *)(BADDR( (ULONG) var)))
/* And do the reverse */
#define C_TO_BPTR(var) (((ULONG)var)>>2)
/* Externs */
extern struct DosLibrary *DOSBase; /* dos library base pointer */
extern short Enable_Abort; /* controls ^C processing */
/* ARGSUSED */
main(argc, argv)
int argc;
char **argv;
{
struct RootNode *rn;
struct DosInfo *di;
struct DeviceList *dl;
struct FileLock *myFileLock;
struct Process *myprocess;
char buf[80];
struct FileInfoBlock *fi;
char *name;
char *btocstr();
void *malloc();
void CountLocks();
struct Task *FindTask();
Enable_Abort = 0; /* Disable ^C processing */
printf("Eject any volumes you wish to profile.\n");
printf("You will be requested to re-insert them as needed.\n");
printf("When ready, press RETURN to continue or 'q' to abort.\n");
(void)gets(buf); /* Well, q and RETURN really... */
if (buf[0] == 'q') { /* Last chance to change your mind! */
printf("Aborted...\n");
exit(0);
}
/* Wait for things to settle down (just in case) */
(void)Delay(5 * TICKS_PER_SECOND);
/* The FileInfoBlock with guaranteed alignment. */
if ((fi = (struct FileInfoBlock *)malloc(sizeof(*fi) )) == NULL) {
printf("Memory allocation failure");
exit(1);
}
/* Note that since lockmon itself has a lock on the current
* directory, this has to be filtered out as an artefact.
* We can get its value out of the CLI stuff. Our task control
* block is the first element of the process control block,
* hence the following casting. This code fragment courtesy of
* the kind person at C-A who answered my query about finding
* the current directory on RAM:
*/
myprocess = (struct Process *)FindTask(NULL);
myFileLock = BPTR_TO_C(FileLock, myprocess->pr_CurrentDir);
/* Any system manipulation of AmigaDOS linked lists while we're
* traversing could quite easily crash us, and the system. So
* we righteously forbid it.
*/
Forbid(); /* but is this really necessary? */
/* Take the DOS library base pointer, deduce the DOS Root Node
* address from that. Follow this to the Info substructure, which
* gives us the start address of the DeviceList chain. Volumes are
* DeviceList entries with a type of DLT_VOLUME. Note that these are
* AmigaDOS linked lists *NOT* Exec ones, so all the stuff about List,
* Node etc. doesn't apply. One box, 2 operating systems!
*/
rn = (struct RootNode *)DOSBase->dl_Root;
di = BPTR_TO_C(DosInfo, rn->rn_Info);
dl = BPTR_TO_C(DeviceList, di->di_DevInfo);
while (dl != NULL) {
if (dl->dl_Type == DLT_VOLUME) {
if ((name = btocstr(dl->dl_Name)) == NULL) {
printf("Memory allocation failure\n");
break;
}
printf("Volume '%s': ", name);
if (dl->dl_LockList != NULL) {
CountLocks(BPTR_TO_C(FileLock,dl->dl_LockList),
fi, myFileLock);
} else {
/* Either mounted or no locks... */
if (dl->dl_Task == NULL)
printf(": no locks\n");
else
printf(": mounted\n");
}
free(name);
}
dl = BPTR_TO_C(DeviceList, dl->dl_Next);
}
Permit(); /* Multi-tasking now back on */
free(fi);
exit(0);
}
/*
* Traverse the linked lists of locks, counting them and printing out their
* corresponding filesystem names.
*/
void
CountLocks(list, fi, mylock)
struct FileLock *list; /* the linked list to run through */
struct FileInfoBlock *fi; /* area for Examine */
struct FileLock *mylock; /* this one's ours */
{
register struct FileLock *lptr;
register int count = 0;
short Examine();
for(lptr=list;lptr != NULL; lptr= BPTR_TO_C(FileLock,lptr->fl_Link)){
if (lptr == mylock) continue;
if (Examine(C_TO_BPTR(lptr), fi) == FALSE) {
/* Clicked Cancel on system requester ? */
printf("\n\tCannot deduce filename for lock");
} else {
printf("\n\t%s", fi->fib_FileName);
}
count++;
}
if (count > 0)
printf("\nTotal: %d lock(s)\n", count);
else
printf(": no locks\n");
}
/*
* Convert a BCPL string to a C string. To avoid scrogging in-memory
* stuff, it malloc's off a copy first.
*/
char *
btocstr(b)
ULONG b;
{
register char *p, *s;
void *malloc();
s = (char *)BADDR(b); /* Shift & get length-prefixed str */
if ((p = malloc(s[0])) != NULL) {
(void)movmem(s +1, p, s[0]); /* Aztec memcpy */
p[s[0]] = '\0';
}
return p;
}