home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
182.lha
/
PathDev
/
support.c
< prev
Wrap
C/C++ Source or Header
|
1988-10-22
|
12KB
|
501 lines
#include "dos.h"
extern PORT *DosPort; /* Our DOS port... this is slick... */
extern PROC *DosProc; /* Our Process */
extern DEVNODE *DosNode; /* Our DOS node.. created by DOS for us */
extern DEVLIST *DevList; /* Device List structure for our volume node */
extern void *SysBase; /* EXEC library base */
extern DOSLIB *DOSBase; /* DOS library base for debug process */
extern RAMFILE RFRoot; /* Directory/File structure (root node) */
extern LIST FHBase; /* Open Files */
extern LIST LCBase; /* Open Locks */
extern long TotalBytes; /* total bytes of data in filesystem */
extern RAMFILE xpath; /* This is used in case of off device path */
extern char *buf1; /* This holds the translated path names */
RAMFILE * checkoutpath();
RAMFILE * vsearchpath();
void *DeviceProc();
/*
* PACKET ROUTINES. Dos Packets are in a rather strange format as you
* can see by this and how the PACKET structure is extracted in the
* GetMsg() of the main routine.
*/
void
returnpacket(packet)
register struct DosPacket *packet;
{
register struct Message *mess;
register struct MsgPort *replyport;
replyport = packet->dp_Port;
mess = packet->dp_Link;
packet->dp_Port = DosPort;
mess->mn_Node.ln_Name = (char *)packet;
mess->mn_Node.ln_Succ = NULL;
mess->mn_Node.ln_Pred = NULL;
PutMsg(replyport, mess);
}
/*
* Are there any packets queued to our device?
*/
packetsqueued()
{
return ((void *)DosPort->mp_MsgList.lh_Head !=
(void *)DosPort->mp_MsgList.lh_Tail);
}
/*
* DOS MEMORY ROUTINES
*
* DOS makes certain assumptions about LOCKS. A lock must minimally be
* a FileLock structure, with additional private information after the
* FileLock structure. The longword before the beginning of the structure
* must contain the length of structure + 4.
*
* NOTE!!!!! The workbench does not follow the rules and assumes it can
* copy lock structures. This means that if you want to be workbench
* compatible, your lock structures must be EXACTLY sizeof(struct FileLock).
*/
void *
dosalloc(bytes)
register ulong bytes;
{
register ulong *ptr;
bytes += 4;
ptr = AllocMem(bytes, MEMF_PUBLIC|MEMF_CLEAR);
*ptr = bytes;
return(ptr+1);
}
dosfree(ptr)
register ulong *ptr;
{
--ptr;
FreeMem(ptr, *ptr);
}
/*
* Convert a BSTR into a normal string.. copying the string into buf.
* I use normal strings for internal storage, and convert back and forth
* when required.
*/
void
btos(bstr,buf)
ubyte *bstr;
ubyte *buf;
{
bstr = BTOC(bstr);
bmov(bstr+1,buf,*bstr);
buf[*bstr] = 0;
}
/*
* Some EXEC list handling routines not found in the EXEC library.
*/
void *
NextNode(node)
NODE *node;
{
node = node->mln_Succ;
if (node->mln_Succ == NULL)
return(NULL);
return(node);
}
void *
GetHead(list)
LIST *list;
{
if ((void *)list->mlh_Head != (void *)&list->mlh_Tail)
return(list->mlh_Head);
return(NULL);
}
/*
* Compare two names which are at least n characters long each,
* ignoring case.
*/
nccmp(p1,p2,n)
register ubyte *p1, *p2;
register short n;
{
while (--n >= 0) {
if ((p1[n]|0x20) != (p2[n]|0x20))
return(0);
}
return(1);
}
/*
* Create a file or directory and link it into it's parent directory.
*/
RAMFILE *
createramfile(parentdir, type, name)
RAMFILE *parentdir;
char *name;
{
register RAMFILE *ramfile;
ramfile = AllocMem(sizeof(RAMFILE), MEMF_CLEAR|MEMF_PUBLIC);
AddTail(&parentdir->list, ramfile);
ramfile->parent = parentdir;
ramfile->name = AllocMem(strlen(name)+1, MEMF_PUBLIC);
strcpy(ramfile->name, name);
ramfile->type = type;
ramfile->protection = 0;
NewList(&ramfile->list);
DateStamp(&ramfile->date);
DateStamp(&ramfile->parent->date);
return(ramfile);
}
/*
* Free all data associated with a file
*/
void
freedata(ramfile)
RAMFILE *ramfile;
{
FENTRY *fen;
TotalBytes -= ramfile->bytes;
while (fen = RemHead(&ramfile->list)) {
/*DB*/ dbprintf("FREE FEN: %08lx %08lx %ld\n", fen, fen->buf, fen->bytes);
FreeMem(fen->buf, fen->bytes);
FreeMem(fen, sizeof(*fen));
}
ramfile->bytes = 0;
DateStamp(&ramfile->date);
DateStamp(&ramfile->parent->date);
}
/*
* Unlink and remove a file. Any data associated with the file or
* directory has already been freed up.
*/
void
freeramfile(ramfile)
RAMFILE *ramfile;
{
Remove(ramfile); /* unlink from parent directory */
if (ramfile->name)
FreeMem(ramfile->name,strlen(ramfile->name)+1);
if (ramfile->comment)
FreeMem(ramfile->comment,strlen(ramfile->comment)+1);
FreeMem(ramfile,sizeof(*ramfile));
}
/*
* The lock function. The file has already been checked to see if it
* is lockable given the mode.
*/
LOCK *
ramlock(ramfile, mode)
RAMFILE *ramfile;
{
LOCK *lock = dosalloc(sizeof(LOCK));
LOCKLINK *ln;
if (mode != ACCESS_WRITE)
mode = ACCESS_READ;
ln = AllocMem(sizeof(LOCKLINK), MEMF_PUBLIC);
AddHead(&LCBase,ln);
ln->lock = lock;
lock->fl_Link= (long)ln;
lock->fl_Key = (long)ramfile;
lock->fl_Access = mode;
lock->fl_Task = DosPort;
lock->fl_Volume = (BPTR)CTOB(DosNode);
if (mode == ACCESS_READ)
++ramfile->locks;
else
ramfile->locks = -1;
return(lock);
}
void
ramunlock(lock)
LOCK *lock;
{
RAMFILE *file = (RAMFILE *)lock->fl_Key;
Remove(lock->fl_Link); /* unlink from list */
FreeMem(lock->fl_Link, sizeof(LOCKLINK)); /* free link node */
if (lock->fl_Access == ACCESS_READ) /* undo lock effect */
--file->locks;
else
file->locks = 0;
dosfree(lock); /* free lock */
}
/*
* GETLOCKFILE(bptrlock)
*
* Return the RAMFILE entry (file or directory) associated with the
* given lock, which is passed as a BPTR.
*
* According to the DOS spec, the only way a NULL lock will ever be
* passed to you is if the DosNode->dn_Lock is NULL, but I'm not sure.
* In anycase, If a NULL lock is passed to me I simply assume it means
* the root directory of the RAM disk.
*/
RAMFILE *
getlockfile(lock)
void *lock; /* actually BPTR to LOCK */
{
register LOCK *rl = BTOC(lock);
if (rl) return((RAMFILE *)rl->fl_Key);
return(&RFRoot);
}
/*
* Search the specified path beginning at the specified directory.
* The directory pointer is updated to the directory containing the
* actual file. Return the file node or NULL if not found. If the
* path is illegal (an intermediate directory was not found), set *ppar
* to NULL and return NULL.
*
* *ppar may also be set to NULL if the search path IS the root.
*
* If pptr not NULL, Set *pptr to the final component in the path.
*/
char *rindex();
RAMFILE *
searchpath(ppar,buf,pptr)
RAMFILE **ppar;
char *buf;
char **pptr;
{
RAMFILE *file = *ppar;
RAMFILE *srch;
short len;
char *ptr;
ptr = rindex(buf,':');
if (ptr) buf = ptr+1;
*ppar = NULL;
for (;*buf && file;) {
ptr = getpathelement(&buf,&len);
if (*ptr == '/') { /* go back a directory */
if (!file->parent) { /* no parent directory */
return(NULL);
}
file = file->parent;
continue;
}
if (file->type == FILE_FILE)
return(checkoutpath(file,ptr));
for (srch = GetHead(&file->list); srch; srch = NextNode(srch)) {
if (srch->type && strlen(srch->name) == len && nccmp(srch->name, ptr, len)) {
file = srch; /* element found */
break;
}
}
if (srch == NULL) {
if (*buf == 0) /* Element not found. If it was the final */
*ppar = file; /* element the parent directory is valid */
if (pptr)
*pptr = ptr;
return(NULL);
}
}
if (pptr)
*pptr = ptr;
*ppar = file->parent;
return(file);
}
RAMFILE *
vsearchpath(ppar,buf,pptr)
RAMFILE **ppar;
char *buf;
char **pptr;
{
RAMFILE *file = *ppar;
RAMFILE *srch;
short len;
char *ptr;
ptr = rindex(buf,':'); /* this fixes up the colon treatment */
if (ptr) buf = ptr+1;
*ppar = NULL;
for (;*buf && file;) {
ptr = getpathelement(&buf,&len);
if (*ptr == '/') { /* go back a directory */
if (!file->parent) { /* no parent directory */
return(NULL);
}
file = file->parent;
continue;
}
if (file->type == FILE_FILE)
return(NULL);
for (srch = GetHead(&file->list); srch; srch = NextNode(srch)) {
if (srch->type && strlen(srch->name) == len && nccmp(srch->name, ptr, len)) {
file = srch; /* element found */
break;
}
}
if (srch == NULL) {
if (*buf == 0) /* Element not found. If it was the final */
*ppar = file; /* element the parent directory is valid */
if (pptr)
*pptr = ptr;
return(NULL);
}
}
if (pptr)
*pptr = ptr;
*ppar = file->parent;
return(file);
}
typedef struct {
FENTRY *fentry;
long offset;
} SFH; /* simple file handle */
RAMFILE *
checkoutpath(file,path)
RAMFILE *file;
char *path;
{
SFH fh;
int lck;
fh.fentry = GetHead(&file->list);
fh.offset = 0;
while (getnexttry(&fh,buf1)) {
strcat(buf1,path);
if (DeviceProc(buf1) == DosPort) {
/* refers to us.. ignore */
continue;
}
if (!index(buf1,':')) {
/* not an absolute path */
continue;
}
if (lck = Lock(buf1,ACCESS_READ)) {
UnLock(lck);
return(&xpath);
}
}
return(0);
}
getnexttry(fh,buf)
register SFH *fh;
register char *buf;
{
register int i;
register FENTRY *fe;
fe = fh->fentry;
i = fh->offset;
for (fe = fh->fentry; fe ; fe = NextNode(fe)) {
for (; i<fe->bytes; i++) {
*buf = fe->buf[i];
if (*buf == '\n') {
*buf = 0;
fh->fentry = fe;
fh->offset = ++i;
return(1);
}
buf++;
}
i=0;
}
return(0);
}
/*
* Return the next path element in the string. The routine effectively
* removes any trailing '/'s, but treats ':' as part of the next component
* (i.e. ':' is checked and skipped in SEARCHPATH()).
*/
char *
getpathelement(pstr,plen)
char **pstr;
short *plen;
{
char *base;
register char *ptr = *pstr;
register short len = 0;
if (*(base = ptr)) {
if (*ptr == '/') {
++ptr;
++len;
} else {
while (*ptr && *ptr != '/') {
++ptr;
++len;
}
if (*ptr == '/')
++ptr;
}
}
*pstr = ptr;
*plen = len;
return(base);
}
char *
typetostr(ty)
{
switch(ty) {
case ACTION_DIE: return("DIE");
case ACTION_OPENRW: return("OPEN-RW");
case ACTION_OPENOLD: return("OPEN-OLD");
case ACTION_OPENNEW: return("OPEN-NEW");
case ACTION_READ: return("READ");
case ACTION_WRITE: return("WRITE");
case ACTION_CLOSE: return("CLOSE");
case ACTION_SEEK: return("SEEK");
case ACTION_EXAMINE_NEXT: return("EXAMINE NEXT");
case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
case ACTION_INFO: return("INFO");
case ACTION_DISK_INFO: return("DISK INFO");
case ACTION_PARENT: return("PARENTDIR");
case ACTION_DELETE_OBJECT: return("DELETE");
case ACTION_CREATE_DIR: return("CREATEDIR");
case ACTION_LOCATE_OBJECT: return("LOCK");
case ACTION_COPY_DIR: return("DUPLOCK");
case ACTION_FREE_LOCK: return("FREELOCK");
case ACTION_SET_PROTECT: return("SETPROTECT");
case ACTION_SET_COMMENT: return("SETCOMMENT");
case ACTION_RENAME_OBJECT: return("RENAME");
case ACTION_INHIBIT: return("INHIBIT");
case ACTION_RENAME_DISK: return("RENAME DISK");
case ACTION_MORECACHE: return("MORE CACHE");
case ACTION_WAIT_CHAR: return("WAIT FOR CHAR");
case ACTION_FLUSH: return("FLUSH");
case ACTION_RAWMODE: return("RAWMODE");
default: return("---------UNKNOWN-------");
}
}