🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.amiga.tech
Article #2713

Re: Anybody know how to do this stuff?

#2713
From: Doug Merritt
Date: Wed, 13 Dec 1989 05:06
594 lines
15047 bytes
In article <4730@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes:
>In article <13920027@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes:
>> I want to find out, for any given device name, whether that is a currently
>> mounted file system device.
>
>There are two parts to this question. First, whether it's a file-system device.
>Second, whether it's currently mounted. The second is easy... you can just
>set your pr_windowptr to -1 and try to access it. To see if it's a file
>system device is a bit harder. You can try doing a getdiskinfo on it.
>
>Or you can traverse the device list and kill two birds with one stone. Let
>me dig up the code...
>
>Bummer. That disk has an error. I'll run disksalv on it while I read news and
>let you know what comes out. (let's see you do *that* on a Mac!)

Since I haven't seen Peter's code yet (DOA? Give my regards to Lazarus),
here's mine ("fs.c").

Hmmm. I just saw Peter's code after all, but since I spent an
hour creating "fs.c" out of the relevent piece of my "filetype" program,
I'll post it anyway. It does lots more than Peter's code (weak justification
for posting :-).

In fact, it does more than you asked for...given a device/volume/assign
name, it tells you everything known about it (see examples below).

If you want to follow Peter's suggestion about having SKsh wildcard
device names, I'm very much in favor...I'm always wishing the CLI
supported that. Anyway, as I said in another posting today, my filetype
program does exactly that, and I can give you complete working code
to support that feature if you want it.

As for this "fs.c", it works quite well, although I see Chuck McManis
just posted something (Subject: "Re: Problem with handler) that suggests
that in addition to checking for a handler task, I should perhaps also
check DSKENV and even send an ACTION_DISKINFO packet. I'll have to look
into that; but meanwhile the simple check has never produced any problem
reports.

Examples of 'fs' in action:

For instance, "fs Workbench1.3:" produces
	Workbench1.3: -- volume (mounted on DF0)

Conversely, "fs df0:" produces
	df0: -- device (file system; contains Workbench1.3)

After ejecting the diskette, the same commands produces
	df0: -- device (file system; ejected)

Or for ASSIGN'ed directories, "fs src:" produces
	src: -- directory (SupraDrive0:SOURCE)

The code works on ram:, rad:, etc. Hope it helps.
	Doug
--
Doug Merritt		{pyramid,apple}!xdos!doug
Member, Crusaders for a Better Tomorrow		Professional Wildeyed Visionary
---------------------- CUT HERE ----------------------------------
/*
 * fs -- check filesystem devices (extracted from my 'filetype' source)
 *
 * copyright 1987 Douglas R. Merritt
 * License to use is hereby granted on the condition that this
 * notice be retained unchanged, and that any commercial
 * use must conspicuously credit the copyright holder.
 *
 */
#define	NONE_SUCH	0
#define	DEVICE		1
#define	DIRECTORY	2
#define	VOLUME		3

char	*ExtraInfo;

#define	TextCountDirEntries(N)	""

char	*strdup(), *Name2Path(), *concat3();

#include	"ctype.h"
#include	"exec/types.h"
#include	"libraries/dos.h"

#ifdef BADDR
#undef BADDR
#endif
#define BADDR(N)	((char *) ( ((ULONG)(N)) << 2) )

#define BCAST(TYPE, VAL)	((TYPE) BADDR((ULONG)VAL))

/*
 * RoundUp0 -- ceiling (yields 0 if n % TO == 0)
 * BufRound -- given buffer address, rounds up to word boundary
 */
#define RoundUp0(N,TO)      ( (TO - (((ULONG)N) & (TO-1)) ) & (TO-1))
#define BufRound(BUF)       &BUF[ RoundUp0(BUF,4) ]

extern  char *calloc();
extern  struct FileHandle *Output(), *Open(), *output;
extern  ULONG Read();

#include	"exec/nodes.h"
#include	"exec/memory.h"
#include	"exec/resident.h"
#include	"libraries/dosextens.h"
#include	"libraries/dos.h"
#include	"libraries/diskfont.h"
#include	"libraries/filehandler.h"
#include	"exec/libraries.h"
#include	"workbench/startup.h"

ULONG   Examine(), ExNext();	/* move to def.h? */
struct  FileLock *Lock(), *ParentDir();
struct	Process *FindTask();

struct	FileInfoBlock *GetInfo();
char	*FileName(), *Name2Path(), *concat3();

extern  struct DosLibrary *DOSBase;
typedef struct DeviceList *DevPtr;

/************************* misc. functions ************************/
/*
 * is this a device name? (e.g. "ser:")
 */
int
IsDevName(name)
	char	*name;
{
	char	*s;

	for (s=name; *s; ++s)
		if (*s == ':') break;
	if (!s[0] || s[1]) return(0);
	return(1);
} /* IsDevName() */

/*
 * compare a string and a BSTR, case-insensitive
 */
StrBstrCmp(s, b)
	unsigned char *s;
	BPTR  b;
{
	int	total, rdone, sdone, c1, c2;
	unsigned char *r, *rstart;

	if (!s || !b) return(-1);
	r = (unsigned char *) BADDR(b);
	total = *r++;
	rstart = r;
	rdone = sdone = 0;
	while (1) {
		if (!*s) sdone = 1;
		if ((r - rstart) >= total) rdone = 1;
		if (sdone || rdone)
			return(sdone - rdone);
		c1 = isupper(*s) ? tolower(*s) : *s;
		c2 = isupper(*r) ? tolower(*r) : *r;
		if (c1 != c2) return(c1 - c2);
		++s; ++r;
	}
	/*NOTREACHED*/
} /* StrBstrCmp() */

/*
 * convert a BSTR to a string
 *      We count on exit() freeing the allocated memory.
 */
char *
Bstr2Str(s)
	unsigned char    *s;
{
	char    *ret;
	int	len;

	if (!s)	s = (unsigned char *) "\0";
	else	s = (unsigned char *) BADDR(s);
	len = s[0] & 0xff;
	ret = calloc(1, len+2);
	strncpy(ret, &s[1], len);
	ret[ len ] = '\0';
	return(ret);
} /* Bstr2Str() */

/*
 * given a pointer to the MsgPort part of a task structure, return
 *      the name found in the Node portion.
 */
char *
taskname(p)
	struct  MsgPort *p;
{
	struct  Node *t;
		char    *s;

	if (!p) return(0);
	t = (struct Node *) p->mp_SigTask;
	if (t->ln_Name) {
		s = t->ln_Name;
		if (*s)
			return(strdup(s));
	}
	return((char *) 0);
} /* taskname() */

/*
 * case-insensitive string compare
 */
stricmp(a, b)
	/*register*/ char    *a, *b;
{
	int	     c1, c2;

	if (!a || !b) return(-1);
	while (*a && *b) {
		c1 = isupper(*a) ? tolower(*a) : *a;
		c2 = isupper(*b) ? tolower(*b) : *b;
		if (c1 != c2) return(c1 - c2);
		++a; ++b;
	}
	return(((int) *a) - ((int) *b));
} /* stricmp() */

#define GetLock(cur)    BCAST(struct FileLock *, cur->dl_Lock)
#define GetVol(cur)     BCAST(struct DeviceList *, cur->fl_Volume)
#define DevNode(cur)    ((struct DeviceNode *) cur)
#define IsVolMounted(cur)   (cur->dl_Task != NULL)

/*
 * Find device list entry of specified type and handler values.
 *	Used to match volumes with devices & vice versa.
 */
struct	DeviceList *
FindDevType(task, type)
	struct	MsgPort	*task;
	ULONG		type;
{
	struct  DosInfo		*dos;
	struct  RootNode	*root;
	struct	DeviceList 	*dev, *cur;

	if (!task) return(0);
	/*
	 * find device list, starting from Dosbase; see AmyDos Tech. Ref Man
	 *      and libraries/dosextens.h
	 */
	root = (struct RootNode *) DOSBase->dl_Root;
	dos = BCAST(struct DosInfo *,    root->rn_Info);
	dev = BCAST(struct DeviceList *, dos->di_DevInfo);

	/* device is *supposed* to be treated differently, so we do: */
	if (type == DLT_DEVICE) {
		Forbid();
		for (cur=dev; cur!=NULL; cur=BCAST(DevPtr, cur->dl_Next)) {
			if (cur->dl_Type != DLT_DEVICE)
				continue;
			if (DevNode(cur)->dn_Task == task) {
				Permit();
				return(cur);
			}
		}
		Permit();
	} else {
		Forbid();
		for (cur=dev; cur!=NULL; cur=BCAST(DevPtr, cur->dl_Next)) {
			if (cur->dl_Type != type)
				continue;
			if (cur->dl_Task == task) {
				Permit();
				return(cur);
			}
		}
		Permit();
	}
	return(0);
} /* FindDevType() */

/*
 * check device list to see if this name is on it
 */
int
IsDevice(buf)
	char    *buf;
{
	struct  DosInfo		*dos;
	struct  RootNode	*root;
	struct	MsgPort		*task;
	DevPtr  dev, cur;
	char    *s, name[128], *strchr();
	char	*str, *on, *devname;
	enum	FILETYPE ret;
	int	mtd, isfs;
	struct	Process *tp;
	APTR	tmp;


	strcpy(name, buf);
	if (s=strchr(name, ':')) *s = '\0';	/* erase ':' */
	else return(NONE_SUCH);	/* fail safe...shouldn't happen */
	/*
	 * find device list, starting from Dosbase; see AmyDos Tech. Ref Man
	 *      and libraries/dosextens.h
	 */

	Forbid(); /* vvvvvv */

	root = (struct RootNode *) DOSBase->dl_Root;
	dos = BCAST(struct DosInfo *,    root->rn_Info);
	dev = BCAST(struct DeviceList *, dos->di_DevInfo);
	for (cur=dev; cur!=NULL; cur=BCAST(DevPtr, cur->dl_Next)) {
		s = BCAST(char *, cur->dl_Name);
		if (StrBstrCmp(name, cur->dl_Name)) continue;
		switch(cur->dl_Type) {
		case DLT_DEVICE:
#if 0
/*
 * this older code is interesting, but it turns out nobody puts
 * anything very useful in those fields.
 */
			if (DevNode(cur)->dn_Handler) {	
				ExtraInfo =
					Bstr2Str(DevNode(cur)->dn_Handler);
			} else if (DevNode(cur)->dn_Task) {
				ExtraInfo = taskname(DevNode(cur)->dn_Task);
			}
			if (!ExtraInfo || !*ExtraInfo ||
			    !isprint(*ExtraInfo) || !isprint(ExtraInfo[1]))
				ExtraInfo = "no id";
#endif
			task = DevNode(cur)->dn_Task;

			Permit();  /* ^^^^^^ */

#if 0
			tp = FindTask((char *) 0 );
			tmp = tp->pr_WindowPtr;
			tp->pr_WindowPtr = (APTR) -1L;
			isfs = IsDir(GetInfo(buf));
			tp->pr_WindowPtr = tmp;
			if (isfs) {
#endif
			if (task) {
				char	buf[256], *str;

				strcpy(buf, "file system; ");
				if (cur=FindDevType(task, DLT_VOLUME)) {
					str = Bstr2Str(cur->dl_Name);
					strcat(buf, "contains ");
					strcat(buf, str);
					free(str);
				} else {
					strcat(buf, "ejected");
				}
				ExtraInfo = strdup(buf);
			} else {
				ExtraInfo = "non-file system";
			}
			return(DEVICE);
		case DLT_DIRECTORY:
			cur = GetVol(GetLock(cur));
			mtd = IsVolMounted(cur);

			Permit();	/* ^^^^^^ */

			if (mtd) {
				ExtraInfo = Name2Path(buf);
			} else {
				char	*tmp, *dup;

				dup = Bstr2Str(cur->dl_Name);
				tmp = "unmounted volume ";
				ExtraInfo = concat3(tmp, dup, "");
				free(dup);
			}
			return(DIRECTORY);
		case DLT_VOLUME:
			mtd = IsVolMounted(cur);

			Permit();	/* ^^^^^^ */

			if (!mtd) {
				ExtraInfo = "unmounted";
				return(VOLUME);
			}
			/*
			 * avoid bug in ram disk; try
			 *	dir "RAM Disk:"
			 * (task hangs, don't say I didn't warn you)
			 */
			if (!stricmp(buf, "RAM Disk:")) {
				str = TextCountDirEntries("ram:");
			} else {
				str = TextCountDirEntries(buf);
			}
			task = DevNode(cur)->dn_Task;

			/* "impossible" error: */
			if (!(cur=FindDevType(task, DLT_DEVICE))) {
				devname = strdup("???");
			} else {
				devname = Bstr2Str(cur->dl_Name);
			}
			on = "mounted on ",
			ExtraInfo = concat3(str, on, devname);
			free(str);
			free(devname);
			return(VOLUME);
		default:
			Permit();	/* ^^^^^^ */

			ret = NONE_SUCH;
			return(ret);
		}
		break;
	}
	Permit();	/* ^^^^^^ */
	return(NONE_SUCH);	/* unknown volume name */
} /* IsDevice() */

/*
 * copy a string into newly allocated space
 */
char *
strdup(s)
	char	*s;
{
	char	*ret;

	if (!s) return(0);
	ret = calloc(1, strlen(s)+1);
	strcpy(ret, s);
	return(ret);
} /* strdup() */

/*
 * concatenate 3 strings into newly allocated storage
 */
char *
concat3(a, b, c)
	char	*a, *b, *c;
{
	int	total;
	char	*ret;
	register char *tmp;

	total = strlen(a) + strlen(b) + strlen(c);
	tmp = ret = calloc(1, total+1);
	while (*a)
		*tmp++ = *a++;
	while (*b)
		*tmp++ = *b++;
	while (*c)
		*tmp++ = *c++;
	*tmp = '\0';
	return(ret);
} /* concat3() */

/*
 * convert any name (e.g. relative to current directory) to its
 *	true full path name (in newly allocated space)
 */
char *
Name2Path(name)
	char	*name;
{
	struct  FileLock *Ilock;
	char	buf[256];

	Ilock = Lock(name, (ULONG) ACCESS_READ);
	if (!Ilock) return(strdup(name));
	Lock2Path(Ilock, buf);
	UnLock(Ilock);
	return(strdup(buf));
} /* Name2Path() */

/*
 * Get full path corresponding to lock (locked file should exist!)
 *	Since we have to go upward one directory at a time,
 *	we have to go all the way to the top before we can build
 *	the path left to right. A data stack is used for this.
 */
Lock2Path(curlock, pathbuf)
	struct	FileLock	*curlock;
	char	*pathbuf;
{
#define	LOCKSTACKSIZE	128
	struct	FileLock *locklist[LOCKSTACKSIZE];
	UBYTE    Ibuf [ sizeof(struct FileInfoBlock) + 4];
	struct  FileInfoBlock *Ifib;
	int	i;
	char	*s, *path;

	Ifib  = (struct FileInfoBlock *) BufRound(Ibuf);
	if (!Examine(curlock, Ifib)) return(0);
	/* if (!IsDir(Ifib)) return(0); */
	/*
	 * find full path name; build LIFO stack of
	 * pushed locks; when full use popped locks with
	 * Examine() to get each name in path.
	 */
	for (i=0; i<LOCKSTACKSIZE; i++) {
		locklist[i] = curlock;
		if (!(curlock = ParentDir(curlock)) )
			break; 	/* normal loop exit */
	}
	path = &pathbuf[0];
	if (i >= LOCKSTACKSIZE) {
		err("Too many subdirectories");
		*path++ = '?';
		*path++ = '/';
		--i;
	}
	/*
	 * concatenate each component of path
	 */
	if (!Examine(locklist[i--], Ifib))
		goto wierd;
	for (s=Ifib->fib_FileName; *s; )
		*path++ = *s++;
	*path++ = ':';
	while (i >= 0) {
		if (!Examine(locklist[i], Ifib))
			goto wierd;
		for (s=Ifib->fib_FileName; *s; )
			*path++ = *s++;
		if (i>0) *path++ = '/';
		--i;
	}
	*path = '\0';
	return(path - &pathbuf[0]);
wierd:
	*path++ = '?';
	*path++ = '/';
	*path = '\0';
	return(path - &pathbuf[0]);
} /* Lock2Path() */

/*
 * is this a directory?
 */
IsDir(Ifib)
	struct	FileInfoBlock *Ifib;
{
	if (!Ifib) return(0);
	if (Ifib->fib_DirEntryType > 0) return(1);
	return(0);
} /* IsDir() */

main(argc, argv)
	int	argc;
	char	**argv;
{
	int	type;
	char	*typename;

	if (argc != 2 || !IsDevName(argv[1])) {
		printf("Usage (e.g)-- devinfo df0:\n");
		exit(1);
	}
	type = IsDevice(argv[1]);
	printf("%s -- ", argv[1]);
	switch(type) {
	case NONE_SUCH:
		typename = "does not exist";
		break;
	case DEVICE:
		typename = "device";
		break;
	case DIRECTORY:
		typename = "directory";
		break;
	case VOLUME:
		typename = "volume";
		break;
	default:
		typename = "???";
	}
	printf(" %s ", typename);
	if (ExtraInfo)
		printf("(%s)\n", ExtraInfo);
	else
		printf("\n");
}

err(s)
	char	*s;
{
	printf("error: %s\n", s);
}
-- 
Doug Merritt		{pyramid,apple}!xdos!doug
Member, Crusaders for a Better Tomorrow		Professional Wildeyed Visionary
Technical Details
Message-ID: <584@xdos.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uwm.edu!genbank!apple!motcsd!xdos!doug
References: <13920020@hpfelg.HP.COM> <13920027@hpfelg.HP.COM> <4730@sugar.hackercorp.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uwm.edu!genbank!apple!motcsd!xdos!doug
From: doug@xdos.UUCP (Doug Merritt)
Newsgroups: comp.sys.amiga.tech
Subject: Re: Anybody know how to do this stuff?
Summary: C code enclosed -- "fs.c"
Message-ID: <584@xdos.UUCP>
Date: 13 Dec 89 05:06:38 GMT
References: <13920020@hpfelg.HP.COM> <13920027@hpfelg.HP.COM> <4730@sugar.hackercorp.com>
Reply-To: doug@xdos.UUCP (Doug Merritt)
Organization: Hunter Systems, Mountain View CA (Silicon Valley)
Lines: 594