home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
compress
/
misc
/
xfh
/
source.lha
/
src
/
CFS.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-09
|
32KB
|
993 lines
/* CFS.c - main packet loop.
Copyright (C) 1991, 1992, 1993 Kristian Nielsen.
This file is part of XFH, the compressing file system handler.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file replaces the startup code! Make sure the object file
* corresponding to this source is linked into the head of the final
* executeable.
*/
#include "CFS.h"
#include <exec/ports.h>
#include <exec/memory.h>
#include <libraries/filehandler.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <clib/alib_protos.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <dossupport.h>
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
const char versiontag[] = "\0$VER: XFH-Handler " VERSION " (" __DATE__ ")";
const char cporighttag[]
= "\0$COPYRIGHT: Copyright (C) 1991, 1992, 1993 Kristian Nielsen";
/**************************************************************************
* *
* Handler entry point. *
* *
* Do initialisation and allocation, then enter main loop after returning *
* our initial packet. *
* *
**************************************************************************/
int __saveds NotReallyMain(void){
glb glob;
struct DosPacket *pkt;
int ret=0;
struct FileLock *parent;
void handle_packet(glb glob, struct DosPacket *pkt);
SysBase=(void *)*(ULONG *)4L;
if(!(glob=AllocMem(sizeof(struct glob),MEMF_CLEAR))) return(100);
glob->ioerr = ERROR_ACTION_NOT_KNOWN; /* Default error code. */
#ifdef DEBUG
opendebug();
debug(("XFH/CFS compressing file system handler v" VERSION ".\n"
"Copyright (C) 1991,1992,1993 Kristian Nielsen.\n"));
debug(("Starting handler with task at 0x%lx.\n",FindTask(0L)));
#endif
glob->dosport=&(glob->myproc=(struct Process *)
(glob->mytask=FindTask(0L)))->pr_MsgPort;
pkt=getpkt(glob);
glob->devnode = (struct DeviceNode *)b2c(pkt->dp_Arg3);
if(!glob->devnode->dn_Name){
debug(("Error: NULL device name - exiting.\n"));
glob->ioerr = ERROR_INVALID_COMPONENT_NAME;
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
goto exitthis;
}
if(!(glob->devname=copybstr(glob->devnode->dn_Name))){
debug(("Error copying device name - exiting.\n"));
OUTOFMEM;
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
goto exitthis;
}
if(!glob->devname[0]){
debug(("Error: Empty device name - exiting.\n"));
glob->ioerr = ERROR_INVALID_COMPONENT_NAME;
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
goto exitthis;
}
debug(("Using device name '%s'.\n",glob->devname));
glob->bcplstartup = glob->devnode->dn_Startup;
if(!(glob->ioport=CreatePort(NULL,0L))){
OUTOFMEM;
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error creating message port - exiting.\n"));
goto exitthis;
}
if(!(glob->DOSBase=OpenLibrary("dos.library",0L))){
glob->ioerr = ERROR_INVALID_RESIDENT_LIBRARY;
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
debug(("Error opening dos.library - exiting.\n"));
ret=100;
goto exitthis;
}
DOSBase=glob->DOSBase;
/* Set primary options (from S:.xfhrc.<unit>, if available). */
if( !InitOptions(glob) ){
returnpkt(pkt,DOSFALSE,ERROR_BAD_TEMPLATE,glob);
debug(("Error setting primary options - exiting.\n"));
ret=100;
goto exitthis;
}
if( !InitXpk(glob) ){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
debug(("Error initialising Xpk routines - exiting.\n"));
ret=100;
goto exitthis;
}
debug(("Using '%s' as root directory...\n",glob->xRootName));
glob->xprocid = DoDeviceProc( (LONG *)&glob->xrootlock, glob->xRootName, glob );
if( !glob->xprocid ){
glob->xrootlock = 0L; /* Don't xUnLock() */
returnpkt(pkt,DOSFALSE,ERROR_OBJECT_NOT_FOUND,glob);
ret=100;
debug(("Error doing DeviceProc(%s) - exiting.\n",glob->xRootName));
goto exitthis;
}
glob->xrootlock = b2c(glob->xrootlock);
debug(("DeviceProc(%s) returned: %lx %lx\n",glob->xRootName,
glob->xprocid,glob->xrootlock));
glob->xrootlock = xLock( glob, glob->xrootlock, glob->xRootName, ACCESS_READ );
if( !glob->xrootlock ){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error obtaining xrootlock: %ld - exiting.\n",glob->ioerr,
glob->xRootName));
goto exitthis;
}
debug(("Obtained xrootlock: %lx\n",glob->xrootlock ));
if(!SetOptionsFromFile(glob, glob->xrootlock, ALTOPTIONPATH)){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error setting secondary options.\n"));
goto exitthis;
}
if(!xInfo(glob, glob->xrootlock, &glob->infodata)){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error obtaining disk info: %ld\n",glob->ioerr));
goto exitthis;
}
glob->bytesperblock = glob->infodata.id_BytesPerBlock;
if(parent = xParentDir(glob, glob->xrootlock)){
xUnLock(glob, parent);
}
if(!xExamine(glob, glob->xrootlock, &glob->fib1)){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error finding name for volume: %ld\n",glob->ioerr));
goto exitthis;
}
if( !(glob->rootlock = makerootlockdayone(glob)) ){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error creating rootlock: %ld - exiting.\n",glob->ioerr));
goto exitthis;
}
if(!createvolnode(glob, parent == NULL, &glob->fib1)){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error creating volume node - exiting.\n"));
goto exitthis;
}
if(!InitArexx(glob)){
returnpkt(pkt,DOSFALSE,glob->ioerr,glob);
ret=100;
debug(("Error initialising AREXX stuff.\n"));
goto exitthis;
}
if(!UpdateXFHNode(glob)){
debug(("Error initialising XFHNode.\n"));
/* Carry on... */
}
/* Handler opened succesfully. Patch in task address so that we will
* stay in control for all future references.
*/
glob->devnode->dn_Task = glob->dosport;
debug(("1: Packet type received: %lx\n",pkt->dp_Type));
returnpkt(pkt,DOSTRUE,0L,glob);
glob->opencnt=0; /* Just for good measure... */
/* Ready to go for the main loop.
* Lets pray that we get no new messages before the initial ReplyPkt()
* (otherwise we may loose the signal for the message port).
*/
for(glob->done=FALSE;!glob->done;){
ULONG signals = Wait(arexxsigmask(glob) | getpktsigmask(glob)
| guisigmask(glob));
if(signals & arexxsigmask(glob)) checkarexxmsg(glob);
if(signals & guisigmask(glob)){
if(!UpdateXFHNode(glob)){
debug(("Error during UpdateXFHNode().\n"));
}
}
if(signals & getpktsigmask(glob)){
while(!glob->done && (pkt=checkpkt(glob))){
handle_packet(glob, pkt);
}
}
}
exitthis:
debug(("CFS exiting...\n"));
CleanupArexx(glob);
if( glob->volnode ) freevolnode(glob);
if( glob->rootlock ) CFSUnLock( glob, glob->rootlock );
CleanupXpk(glob);
CleanupOptions(glob);
if(glob->ioport) DeletePort(glob->ioport);
if(glob->devname) freestr(glob->devname);
#ifdef DEBUG
closedebug();
#endif
/*
* Unload the code. This is mostly to serve the ACTION_DIE packet.
* Useful for debugging (otherwise countless copies might end up in memory.
* It is rather ugly, however, and propably not really useful.
*/
Forbid();
UnLoadSeg(glob->devnode->dn_SegList);
glob->devnode->dn_SegList=NULL;
if(glob->DOSBase) CloseLibrary(glob->DOSBase);
FreeMem(glob,sizeof(struct glob));
return(ret);
}
void handle_packet(glb glob, struct DosPacket *pkt){
glob->ioerr = 0L;
switch(pkt->dp_Type){
case ACTION_LOCATE_OBJECT:{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug(("ACTION_LOCATE_OBJECT(%lx,\"%s\",%ld)",
pkt->dp_Arg1,
bstr2c(pkt->dp_Arg2,glob->debugbuf1),
pkt->dp_Arg3));
mylock = b2c(pkt->dp_Arg1);
mycfslock = mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock;
mycfslock = CFSLock( glob,
mycfslock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
pkt->dp_Arg3);
if (mycfslock){
if( mylock = CreateFileLock( glob, mycfslock ) )
glob->opencnt++;
else{
LONG saveioerr;
saveioerr = glob->ioerr;
CFSUnLock(glob, mycfslock);
glob->ioerr = saveioerr;
}
}else{
mylock = NULL;
}
debug((" = %lx\n",c2b(mylock)));
returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_COPY_DIR:{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug(("ACTION_COPY_DIR(%lx)",pkt->dp_Arg1));
mylock = b2c(pkt->dp_Arg1);
mycfslock = mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock;
if( mycfslock = CFSDupLock( glob, mycfslock ) ){
if( mylock = CreateFileLock(glob, mycfslock ) ){
glob->opencnt++;
}else{
LONG saveioerr;
saveioerr = glob->ioerr;
CFSUnLock(glob, mycfslock);
glob->ioerr = saveioerr;
}
}else mylock = NULL;
debug((" = %lx\n",c2b(mylock)));
returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_PARENT:{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug(("ACTION_PARENT(%lx)",pkt->dp_Arg1));
mylock = b2c(pkt->dp_Arg1);
mycfslock = mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock;
if( mycfslock = CFSParentDir( glob, mycfslock ) ){
if( mylock = CreateFileLock(glob, mycfslock ) ){
glob->opencnt++;
}else{
LONG saveioerr;
saveioerr = glob->ioerr;
CFSUnLock(glob, mycfslock);
glob->ioerr = saveioerr;
}
}else mylock = NULL;
debug((" = %lx\n",c2b(mylock)));
returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_FREE_LOCK:{
BOOL err;
struct FileLock *mylock;
debug(("ACTION_FREE_LOCK(%lx)\n",pkt->dp_Arg1));
mylock = b2c(pkt->dp_Arg1);
if(mylock){
err = CFSUnLock(glob, (void *)mylock->fl_Key);
if(err){
dfree(mylock);
glob->opencnt--;
}
}else err = ERROR_OBJECT_WRONG_TYPE;
returnpkt(pkt,err,glob->ioerr,glob);
break;
}
/* ToDo: Handle NULL locks correct (but what is correct?)
* Now, a NULL lock is equal to out root lock.
*/
case ACTION_SAME_LOCK:{
struct FileLock *fl1,*fl2;
BOOL res;
fl1 = b2c(pkt->dp_Arg1);
fl2 = b2c(pkt->dp_Arg2);
debug(("ACTION_SAME_LOCK(%lx,%lx)",fl1,fl2));
/* ToDo: This bit tests that both locks belong to us - this
* is probably bogus.
*/
if(fl1 && fl1->fl_Task != glob->dosport){
res = FALSE;
}else if(fl2 && fl2->fl_Task!=glob->dosport){
res = FALSE;
}else{
struct CFSLock *f1,*f2;
f1 = fl1 ? (struct CFSLock *)fl1->fl_Key : glob->rootlock;
f2 = fl2 ? (struct CFSLock *)fl2->fl_Key : glob->rootlock;
res = CFSSameLock( glob, f1, f2 );
}
debug((" = %ld\n",res));
/* ToDo: DOCS mention error code in case of zero return.
* Not currently implemented.
*/
returnpkt(pkt,res,glob->ioerr,glob);
break;
}
case ACTION_FINDINPUT: /* (filehandle, lock, name)->BOOL */
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
{
struct FileHandle *fh;
struct CFSFH *cfsfh;
char *name;
struct FileLock *parentlock;
struct CFSLock *cfsparentlock;
debug(("%s(%lx,%lx,\"%s\")\n",
pkt->dp_Type==ACTION_FINDINPUT ? "ACTION_FINDINPUT" :
pkt->dp_Type==ACTION_FINDOUTPUT ? "ACTION_FINDOUTPUT" :
"ACTION_FINDUPDATE" ,
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1)));
fh = b2c(pkt->dp_Arg1);
parentlock = b2c(pkt->dp_Arg2);
cfsparentlock =
parentlock ? (struct CFSLock *)parentlock->fl_Key : glob->rootlock;
name = bstr2c(pkt->dp_Arg3, glob->pktstringbuf);
cfsfh = CFSOpen(glob, cfsparentlock, name, pkt->dp_Type);
debug(("(=%lx)\n",cfsfh));
if( cfsfh ){
glob->opencnt++;
fh->fh_Arg1 = c2b(cfsfh);
returnpkt(pkt, DOSTRUE, glob->ioerr, glob);
}else{
returnpkt(pkt, DOSFALSE, glob->ioerr, glob);
}
break;
}
case ACTION_READ: /* (fh->arg1, buf, len)->actlen */
{
struct CFSFH *cfsfh;
LONG len;
void *buf;
debug(("ACTION_READ(%lx,%lx,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
cfsfh = b2c(pkt->dp_Arg1);
buf = (void *)pkt->dp_Arg2;
len = pkt->dp_Arg3;
len = CFSRead(glob, cfsfh, buf, len);
returnpkt(pkt, len, glob->ioerr, glob);
break;
}
case ACTION_WRITE: /* (fh->arg1, buf, len)->actlen */
{
struct CFSFH *cfsfh;
LONG len;
void *buf;
debug(("ACTION_WRITE(%lx,%lx,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
cfsfh = b2c(pkt->dp_Arg1);
buf = (void *)pkt->dp_Arg2;
len = pkt->dp_Arg3;
len = CFSWrite(glob, cfsfh, buf, len);
debug(("ACTION_WRITE returns %ld %ld.\n",len, glob->ioerr));
returnpkt(pkt, len, glob->ioerr, glob);
break;
}
case ACTION_SEEK: /* (fh->arg1, pos, offset)->actlen */
{
struct CFSFH *cfsfh;
LONG pos;
LONG offset;
debug(("ACTION_SEEK(%lx,%lx,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,pkt->dp_Arg3));
cfsfh = b2c(pkt->dp_Arg1);
pos = pkt->dp_Arg2;
offset = pkt->dp_Arg3;
pos = CFSSeek(glob, cfsfh, pos, offset);
returnpkt(pkt, pos, glob->ioerr, glob);
break;
}
case ACTION_END: /* (fh->arg1) -> BOOL */
{
struct CFSFH *cfsfh;
BOOL res;
cfsfh = b2c(pkt->dp_Arg1);
debug(("ACTION_END(%lx)\n",cfsfh));
res = CFSClose( glob, cfsfh );
if( res ) glob->opencnt--;
debug(("Closing file - still %ld files open.\n",glob->opencnt));
returnpkt(pkt,res,pkt->dp_Res2,glob);
break;
}
case ACTION_DIE:
debug(("ACTION_DIE()\n"));
Forbid();
if(!glob->opencnt){
glob->done=TRUE;
returnpkt(pkt,DOSTRUE,pkt->dp_Res2,glob);
glob->devnode->dn_Task = NULL;
debug(("No open files - Handler exiting.\n"));
}else{
returnpkt(pkt,DOSFALSE,ERROR_OBJECT_IN_USE,glob);
debug(("Cannot end yet - still %ld open files.\n",glob->opencnt));
}
Permit();
break;
case ACTION_EXAMINE_OBJECT:{
struct FileInfoBlock *fib;
struct FileLock *mylock;
BOOL err;
debug(("ACTION_EXAMINE_OBJECT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
mylock = b2c(pkt->dp_Arg1);
fib = b2c(pkt->dp_Arg2);
err = CFSExamine(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
fib);
debug(("NAME: %s DirEntryType: %ld err: %ld\n",
fib->fib_FileName, fib->fib_DirEntryType,err));
cstr2binplace(&fib->fib_FileName[0]);
cstr2binplace(&fib->fib_Comment[0]);
returnpkt(pkt,err,glob->ioerr,glob);
break;
}
case ACTION_EXAMINE_NEXT:{
struct FileInfoBlock *fib;
struct FileLock *mylock;
BOOL err;
debug(("ACTION_EXAMINE_NEXT(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
mylock = b2c(pkt->dp_Arg1);
fib = b2c(pkt->dp_Arg2);
bstr2cinplace(&fib->fib_FileName[0]);
safebstr2cinplace(&fib->fib_Comment[0],80);
err = CFSExamineNext(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
fib);
debug(("NAME: %s DirEntryType: %ld err: %ld\n",
fib->fib_FileName, fib->fib_DirEntryType,err));
cstr2binplace(&fib->fib_FileName[0]);
cstr2binplace(&fib->fib_Comment[0]);
returnpkt(pkt,err,glob->ioerr,glob);
break;
}
case ACTION_CREATE_DIR:{ /* (parentlock, name) -> lock */
struct FileLock *mylock;
struct CFSLock *lock;
debug(("ACTION_CREATE_DIR(%lx,\"%s\") ",
pkt->dp_Arg1,bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
mylock = b2c(pkt->dp_Arg1);
lock = CFSCreateDir(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf) );
if (lock){
if( mylock = CreateFileLock( glob, lock ) )
glob->opencnt++;
else{
LONG saveioerr;
saveioerr = glob->ioerr;
CFSUnLock(glob, lock);
glob->ioerr = saveioerr;
}
}else{
mylock = NULL;
}
debug(("= %lx\n",mylock));
returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
break;
}
case ACTION_DELETE_OBJECT:{ /* (parentlock, name) -> succes */
struct FileLock *mylock;
BOOL err;
debug(("ACTION_DELETE_OBJECT(%lx,\"%s\")\n", pkt->dp_Arg1,
bstr2c(pkt->dp_Arg2,glob->debugbuf1)));
mylock = b2c(pkt->dp_Arg1);
err = CFSDeleteFile(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf) );
if( !err )
debug(("Error deleting file!\n"));
returnpkt(pkt, err, glob->ioerr, glob);
break;
}
case ACTION_RENAME_OBJECT:{ /* (lock1,name1,lock2,name2) -> succes */
struct FileLock *mylock1, *mylock2;
BOOL err;
/* ToDo: Check that both locks belong to us? */
debug(("ACTION_RENAME_OBJECT(%lx,\"%s\", %lx,\"%s\")\n",pkt->dp_Arg1,
bstr2c(pkt->dp_Arg2,glob->debugbuf1),
pkt->dp_Arg3,
bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
mylock1 = b2c(pkt->dp_Arg1);
mylock2 = b2c(pkt->dp_Arg3);
err = CFSRename(glob,
mylock1 ? (struct CFSLock *)mylock1->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg2,glob->pktstringbuf),
mylock2 ? (struct CFSLock *)mylock2->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg4,glob->pktstringbuf2) );
if( !err )
debug(("Error renaming file!\n"));
returnpkt(pkt, err, glob->ioerr, glob);
break;
}
case ACTION_SET_PROTECT:{ /* (dummy, parentlock, name, bits) -> succes */
struct FileLock *mylock;
BOOL err;
debug(("ACTION_SET_PROTECT([%lx] %lx,\"%s\",%lx)\n",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1),
pkt->dp_Arg4));
mylock = b2c(pkt->dp_Arg2);
err = CFSSetProtection(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
pkt->dp_Arg4 );
if( !err )
debug(("Error changing protection bits!\n"));
returnpkt(pkt, err, glob->ioerr, glob);
break;
}
case ACTION_SET_COMMENT:{ /* (dummy, parentlock, name, comment) -> succes */
struct FileLock *mylock;
BOOL err;
debug(("ACTION_SET_COMMENT([%lx] %lx,\"%s\",\"%s\")\n",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1),
bstr2c(pkt->dp_Arg4,glob->debugbuf2)));
mylock = b2c(pkt->dp_Arg2);
err = CFSSetComment(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
bstr2c(pkt->dp_Arg4,glob->pktstringbuf2) );
if( !err )
debug(("Error changing file comment!\n"));
returnpkt(pkt, err, glob->ioerr, glob);
break;
}
case ACTION_SET_DATE:{ /* (dummy, parentlock, name, datestamp) -> succes */
struct FileLock *mylock;
BOOL err;
debug(("ACTION_SET_DATE([%lx] %lx,\"%s\",%ld,%ld,%ld)\n",
pkt->dp_Arg1,pkt->dp_Arg2,
bstr2c(pkt->dp_Arg3,glob->debugbuf1),
((struct DateStamp *)(pkt->dp_Arg4))->ds_Days,
((struct DateStamp *)(pkt->dp_Arg4))->ds_Minute,
((struct DateStamp *)(pkt->dp_Arg4))->ds_Tick
));
mylock = b2c(pkt->dp_Arg2);
err = CFSSetDate(glob,
mylock ? (struct CFSLock *)mylock->fl_Key : glob->rootlock,
bstr2c(pkt->dp_Arg3,glob->pktstringbuf),
(struct DateStamp *)pkt->dp_Arg4 );
if( !err )
debug(("Error changing objects date!\n"));
returnpkt(pkt, err, glob->ioerr, glob);
break;
}
case ACTION_DISK_INFO: /* (infodata) = BOOL */
debug(("ACTION_DISK_INFO(%lx)\n",pkt->dp_Arg1));
returnpkt(pkt, diskinfo(glob,b2c(pkt->dp_Arg1)), 0L, glob);
break;
case ACTION_INFO: /* (lock,infodata) = BOOL */
debug(("ACTION_INFO(%lx,%lx)\n",pkt->dp_Arg1,pkt->dp_Arg2));
returnpkt(pkt, diskinfo(glob,b2c(pkt->dp_Arg2)), 0L, glob);
break;
case ACTION_RENAME_DISK:{ /* (BCPLNAME) = BOOL */
BOOL res;
debug(("ACTION_RENAME_DISK(%s)\n",
bstr2c(pkt->dp_Arg1,glob->debugbuf1)));
res = SetOptionPermanent(glob, "VOLUMENAME",
bstr2c(pkt->dp_Arg1,glob->pktstringbuf));
if(!res) debug(("Error during relabel: %ld.\n",glob->ioerr));
returnpkt(pkt, res, glob->ioerr, glob);
break;
}
case ACTION_IS_FILESYSTEM:
debug(("ACTION_IS_FILESYSTEM\n"));
returnpkt(pkt, DOSTRUE, 0L, glob);
break;
case ACTION_PARENT_FH:{
struct FileLock *mylock;
struct CFSLock *mycfslock;
debug(("ACTION_PARENT_FH(%lx)",pkt->dp_Arg1));
if ( mycfslock = CFSParentFH( glob, b2c(pkt->dp_Arg1) ) ){
if( mylock = CreateFileLock(glob, mycfslock ) ){
glob->opencnt++;
}else{
LONG saveioerr;
saveioerr = glob->ioerr;
CFSUnLock(glob, mycfslock);
glob->ioerr = saveioerr;
}
}else mylock = NULL;
debug((" = %lx\n",c2b(mylock)));
returnpkt(pkt, c2b(mylock), glob->ioerr, glob);
break;
}
default:
debug(("Unknown packet received: %ld\n",pkt->dp_Type));
returnpkt(pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN,glob);
}
}
struct DosPacket *getpkt(glb glob){
struct Message *msg;
while(!(msg=GetMsg(glob->dosport)))
WaitPort(glob->dosport);
return (struct DosPacket *)msg->mn_Node.ln_Name;
}
ULONG getpktsigmask(glb glob){
return (ULONG)1 << glob->dosport->mp_SigBit;
}
struct DosPacket *checkpkt(glb glob){
struct Message *msg;
if(msg = GetMsg(glob->dosport)){
return (struct DosPacket *)msg->mn_Node.ln_Name;
}else{
return NULL;
}
}
void returnpkt(struct DosPacket *pkt,LONG res1,LONG res2,glb glob){
struct MsgPort *port;
struct Message *msg;
port=pkt->dp_Port;
msg=pkt->dp_Link;
msg->mn_Node.ln_Succ=msg->mn_Node.ln_Pred=NULL;
msg->mn_Node.ln_Name=(char *)pkt;
pkt->dp_Res1=res1;
pkt->dp_Res2=res2;
pkt->dp_Port=glob->dosport;
PutMsg(port,msg);
}
struct devprocmsg{
struct Message msg;
void (*func)();
char *filedesc;
struct MsgPort *procid;
LONG res2;
};
void __asm CallDeviceProc(register __a0 struct devprocmsg *msg){
msg->procid=DeviceProc(msg->filedesc);
msg->res2=IoErr();
}
struct MsgPort *DoDeviceProc(LONG *res2,char *filedesc,glb glob){
struct devprocmsg msg,*msg2;
extern void DoDOSSeg();
struct MsgPort *procid;
msg.msg.mn_Node.ln_Succ=NULL;
msg.msg.mn_Node.ln_Pred=NULL;
msg.msg.mn_Node.ln_Name=NULL;
msg.msg.mn_Node.ln_Type=NT_MESSAGE;
msg.msg.mn_Node.ln_Pri=0;
msg.msg.mn_ReplyPort=glob->ioport;
msg.msg.mn_Length=sizeof(msg);
msg.func=(void (*)())CallDeviceProc;
msg.filedesc=filedesc;
if(!(procid=CreateProc
("DoDOS",glob->mytask->tc_Node.ln_Pri,(BPTR)((ULONG)DoDOSSeg>>2),4000L)))
return 0L;
PutMsg(procid,(struct Message *)&msg);
do WaitPort(glob->ioport);
while(!(msg2=(struct devprocmsg *)GetMsg(glob->ioport)));
#ifdef DEBUG
if(msg2!=&msg)
dprintf("ERROR: bogus return message: &msg=%lx msg2=%lx\n",&msg,msg2);
#endif
if(res2) *res2=msg2->res2;
return msg2->procid;
}
/* DOS device list locking.
* ToDo: Use correct 2.0 locking calls.
*/
static void MyLockDosList(glb glob){
Forbid();
}
static void MyUnlockDosList(glb glob){
Permit();
}
void addvolnode(glb glob, struct DeviceList *volnode){
struct DosInfo *dosinfo;
MyLockDosList(glob);
dosinfo = b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
volnode->dl_Next = dosinfo->di_DevInfo;
dosinfo->di_DevInfo = c2b(volnode);
MyUnlockDosList(glob);
}
BOOL removevolnode(glb glob, struct DeviceList *volnode){
struct DosInfo *dosinfo;
BPTR *p;
/* ToDo: check for 2.0 device list locking. */
MyLockDosList(glob);
dosinfo = b2c( ((struct RootNode *)DOSBase->dl_Root)->rn_Info);
p = &dosinfo->di_DevInfo;
while(*p){
if(b2c(*p) == volnode ){
*p = volnode->dl_Next;
MyUnlockDosList(glob);
return TRUE;
}
p = &( ((struct DeviceList *)b2c(*p)) -> dl_Next);
}
MyUnlockDosList(glob);
/* Hey - we didn't find the node in the list! */
debug(("WARNING!:removevolnode(): volume node not found.\n"));
return FALSE;
}
/* Used to update the 'Startup' field in our device node (used in option
* 'KILLSTARTUP').
*/
void DevNode_Stuff_Startup_String(glb glob, BSTR value){
MyLockDosList(glob);
glob->devnode->dn_Startup = value;
MyUnlockDosList(glob);
}
/* NOTE: this function assumes properly dos device list locking!
* This function will fail if 'name' is NULL.
* NOTE: createvolnode(), below does this in it's own way.
*/
static BOOL stuffvolnamevolnode(glb glob, char *name){
UBYTE *bcplname, *oldbcplname;
/* NASTY BUG: It seems that the volume name is expected to be zero
* terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
/* Check if user specified a volume name. */
if(name){
if(!(bcplname=dosalloc(strlen(name)+2))){
OUTOFMEM;
return FALSE;
}
/* Free any old name. */
oldbcplname = b2c(glob->volnode->dl_Name);
if(oldbcplname) dosfree(oldbcplname);
strcpy(bcplname,name);
cstr2binplace(bcplname);
glob->volnode->dl_Name = c2b(bcplname);
debug(("Using user suplied volumename '%s'.\n",bcplname+1));
return TRUE;
}else{
glob->ioerr = ERROR_INVALID_COMPONENT_NAME;
return FALSE;
}
}
/* This function creates our volumenode. The argument 'fixroot' is
* a hack, telling whether the volumename should be changed to prevent
* name-clashing with the volume name of the UFS.
*/
BOOL createvolnode(glb glob, BOOL fixroot, struct FileInfoBlock *fib){
UBYTE *bcplname;
if(!dalloc(glob->volnode)) return FALSE;
/* NASTY BUG: It seems that the volume name is expected to be zero
* terminated even though it is a BSTR. Hence strlen()+2 in alloc. */
/* Check if user specified a volume name. */
if(glob->uservolname){
if(!(bcplname=dosalloc(strlen(glob->uservolname)+2))){
dfree(glob->volnode);
return FALSE;
}
strcpy(bcplname,glob->uservolname);
debug(("Using user suplied volumename '%s'.\n",bcplname));
}else{
if(!(bcplname=dosalloc(strlen(fib->fib_FileName)+2
+ (fixroot ? strlen(XROOTNAME)+1 : 0) ))){
dfree(glob->volnode);
return FALSE;
}
strcpy(bcplname, fixroot ? XROOTNAME "_" : "");
strcat(bcplname, &fib->fib_FileName[0]);
debug(("Using default volume name '%s'.\n",bcplname));
}
glob->volnode->dl_Type = DLT_VOLUME;
glob->volnode->dl_Task = glob->dosport;
glob->volnode->dl_Lock = c2b(NULL);
glob->volnode->dl_VolumeDate = fib->fib_Date;
glob->volnode->dl_LockList = c2b(NULL);
glob->volnode->dl_DiskType = ID_DOS_DISK; /*Wonder what would be right*/
glob->volnode->dl_unused = 0L;
cstr2binplace(bcplname);
glob->volnode->dl_Name = c2b(bcplname);
/* Check if user requested that we create a volume node. */
/* if(glob->createvolnode){*/
addvolnode(glob, glob->volnode);
/* }*/
return TRUE;
}
/* Set the volume name in the volnode. */
BOOL SetVolumeNameVolNode(glb glob, char *name){
BOOL res;
MyLockDosList(glob);
res = stuffvolnamevolnode(glob, name);
MyUnlockDosList(glob);
return res;
}
BOOL freevolnode(glb glob){
/* Check if user requested that we create a volume node. */
/* if(glob->createvolnode){*/
if( !removevolnode( glob, glob->volnode ) ) return FALSE;
/* }*/
dosfree( b2c(glob->volnode->dl_Name) );
dfree( glob->volnode );
return TRUE;
}
BOOL diskinfo(glb glob, struct InfoData *infodata){
if(!xInfo( glob, glob->xrootlock, infodata )){
debug(("Error: diskinfo(): xInfo() returned zero (%ld).\n",glob->ioerr));
return DOSFALSE;
}
/* infodata->id_NumSoftErrors = 0;*/
/* infodata->id_UnitNumber = glob->fsstartup ?*/
/* glob->fsstartup->fssm_Unit : 0;*/
/* infodata->id_DiskState = ID_VALIDATED;*/
/* infodata->id_NumBlocks = 1;*/
/* infodata->id_NumBlocksUsed = 1;*/
/* infodata->id_BytesPerBlock = 1;*/
/* infodata->id_DiskType = ID_DOS_DISK;*/
infodata->id_VolumeNode = c2b( glob->volnode );
infodata->id_InUse = glob->opencnt ? 1 : 0;
debug(("diskinfo(): U=%ld DS=%lx #=%ld #u=%ld #b=%ld IU=%ld.\n",
infodata->id_UnitNumber,infodata->id_DiskState,infodata->id_NumBlocks,
infodata->id_NumBlocksUsed,infodata->id_BytesPerBlock,
infodata->id_InUse));
return DOSTRUE;
}
/* End of CFS.c */