home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
cdrom
/
FS+FS-Tools
/
AmiCDFileSystem
/
src
/
device.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-03
|
42KB
|
1,717 lines
/* device.c:
*
* Handler for ISO-9660 (+ Rock Ridge) + HFS CDROM filing system.
* Originally based on DOSDEV V1.10 (2 Nov 87) by Matthew Dillon.
* Major changes made by Nicola Salmoria.
*
* ----------------------------------------------------------------------
* This code is (C) Copyright 1993,1994 by Frank Munkert.
* All rights reserved.
* This software may be freely distributed and redistributed for
* non-commercial purposes, provided this notice is included.
* ----------------------------------------------------------------------
* [History removed]
*/
#include <stdlib.h>
#include <string.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <exec/resident.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <dos/filehandler.h>
#include <devices/timer.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <devices/trackdisk.h>
#include <utility/date.h>
#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>
#include <resources/filesysres.h>
#include <clib/alib_protos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/wb.h>
#include "cdrom.h"
#include "generic.h"
#include "rock.h"
#define VERSION 37
#define REVISION 5
static const UBYTE versionstring20[] = "\0$VER: amicdfilesystem 37.5 (2.10.94)";
/*
* The only purpose of this Resident structure is to make
* Version CD0:
* return the version number of the filesystem.
*/
static const struct Resident versiontag =
{
RTC_MATCHWORD,
&versiontag,
&versiontag + 1,
0,
VERSION,
0,
-81,
NULL,
&versionstring20[7],
NULL
};
/* the only global data used is library bases, therefore this code is */
/* reentrant, and could be run several times. If we added the filesystem */
/* to the filesystem resource, one instance would be used for multiple */
/* devices. */
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;
struct IntuitionBase *IntuitionBase;
struct Library *InputBase;
struct Library *IconBase;
struct Library *WorkbenchBase;
/* global data is kept in the HData structure, instead, which is located */
/* on the stack. */
struct HConfig
{
BOOL UseTrackdisk; /* Use trackdisk calls instead of SCSI-direct */
BOOL Lowercase; /* Map ISO names to lower case */
ULONG ScanInterval; /* Time between successive diskchange checks */
};
struct HData
{
struct MsgPort *MyPort; /* our handler port */
struct DosList *MyDevNode; /* our device node */
struct FileSysStartupMsg *fssm;
struct DosEnvec *envec;
struct DosList *CurrentVolume; /* current volume, or NULL */
BPTR LockList; /* list of open locks */
LONG DiskInserted; /* see #defines below */
LONG Inhibited; /* !0 if the volume is inhibited (nesting count) */
CDROM *CD;
VOLUME *CDVolume;
CDROM_OBJ *TopLevelObj;
UBYTE VolumeName[40]; /* When a dos disk is inserted, contains the */
/* volume name in BCPL form. */
/* When an audio disk is inserted, contains */
/* tha name which will be used for the AppIcon, */
/* for example CD0:CDDA */
struct AppIcon *AppIcon; /* CDDA AppIcon */
struct MsgPort *AppPort; /* MsgPort used by the AppIcon */
struct MsgPort *TimerPort; /* timer.device I/O port */
struct timerequest *TimerIO; /* timer.device I/O request */
struct IOStdReq *InputIO; /* input.device I/O request */
UBYTE PlayCDDA[128]; /* Command invoked if appicon is activated */
/* (initialized by Show_CDDA_Icon()) */
BOOL Playing; /* TRUE if a CDDA disk is playing */
BOOL pad;
struct HConfig HConfig; /* configuration */
};
/* allowed values for the DiskInserted field */
#define DI_NO_DISK 0 /* no disk in the drive */
#define DI_DISK_OK 1 /* disk in drive */
#define DI_UNREADABLE_DISK 2 /* disk in drive, but couldn't be read for some reason */
#define DI_CDDA_DISK 3 /* CDDA disk in drive */
ULONG Centrypoint(VOID);
VOID ReturnPacket(struct DosPacket *packet,struct MsgPort *port,LONG res1,LONG res2);
VOID AddToFSResource(ULONG dostype,BPTR seglist);
void btos(LONG, char *);
CDROM_OBJ *OpenObject(BPTR parentlock,BSTR name,struct HData *HData);
BPTR cdlock(CDROM_OBJ *, int,struct HData *HData);
void cdunlock(BPTR lock,struct HData *HData);
LONG CheckLock(BPTR lock,struct HData *HData);
CDROM_OBJ *getlockfile(BPTR lock,struct HData *HData);
int Check_For_Volume_Name_Prefix (char *);
VOID Fill_InfoData(struct InfoData *id,struct HData *HData);
void Fill_FileInfoBlock (struct FileInfoBlock *, CDROM_INFO *, VOLUME *,struct HData *HData);
void Mount(struct HData *HData);
struct DosList *CreateVolumeNode(struct HData *HData);
void RemoveVolumeNode (struct HData *HData);
VOID RemoveDosList(struct DosList *vol);
void Check_Disk (struct HData *HData);
void Send_Timer_Request(struct HData *HData);
int Open_Timer_Device(struct HData *HData);
int Open_Input_Device(struct HData *HData);
VOID CreateInputEvent(BOOL inserted,struct HData *HData);
int Get_Startup (struct HData *HData);
VOID Display_Error(UBYTE *text,APTR par1, ...);
VOID Show_CDDA_Icon(struct HData *HData);
VOID Hide_CDDA_Icon (struct HData *HData);
ULONG _stackswap(ULONG function(),...);
ULONG entrypoint(VOID)
{
/* we must always swap the stack because when mounted from RDB we will get */
/* only 600 bytes of stack. */
return(_stackswap(Centrypoint));
}
ULONG __saveds Centrypoint(VOID)
{
struct DosPacket *packet;
struct Process *process;
struct HData HData;
LONG timercount = 0;
SysBase = *((struct ExecBase **)4);
process = (struct Process *)FindTask(NULL);
/* if we were run from a shell, fail */
if (process->pr_CLI) return(RETURN_FAIL);
WaitPort(&process->pr_MsgPort); /* get startup packet */
packet = (struct DosPacket *)GetMsg(&process->pr_MsgPort)->mn_Node.ln_Name;
memset(&HData,0,sizeof(struct HData));
if (!(HData.fssm = BADDR(packet->dp_Arg2)) ||
!(HData.envec = BADDR(HData.fssm->fssm_Environ)) ||
/* make sure that the mountlist has enough fields */
HData.envec->de_TableSize < DE_DOSTYPE)
{
Forbid();
ReturnPacket(packet,&process->pr_MsgPort,DOSFALSE,0);
return(0); /* exit */
}
HData.MyDevNode = BADDR(packet->dp_Arg3);
/* add the seglist to the filesystem.resource so it will be reused by other */
/* devices with the same DosType */
AddToFSResource(HData.envec->de_DosType,HData.MyDevNode->dol_misc.dol_handler.dol_SegList);
if (SysBase->LibNode.lib_Version < 37 ||
!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)) ||
!(UtilityBase = OpenLibrary("utility.library",37)) ||
!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) ||
!(HData.MyPort = CreateMsgPort()) ||
!Open_Timer_Device(&HData) ||
!Open_Input_Device(&HData) ||
!Get_Startup(&HData))
{
if (DOSBase)
{
DeleteMsgPort(HData.MyPort);
CloseLibrary(IntuitionBase);
CloseLibrary(UtilityBase);
CloseLibrary(DOSBase);
}
Forbid();
ReturnPacket(packet,&process->pr_MsgPort,DOSFALSE,0);
return(0); /* exit */
}
/* initialize dn_Task so that DOS won't start a new process for every access */
HData.MyDevNode->dol_Task = HData.MyPort;
ReturnPacket(packet,HData.MyPort,DOSTRUE,0);
Send_Timer_Request(&HData);
Check_Disk(&HData);
for (;;)
{
ULONG dossignal,appsignal,timersignal,sigrec;
dossignal = 1L << HData.MyPort->mp_SigBit;
appsignal = HData.AppPort ? 1L << HData.AppPort->mp_SigBit : 0;
timersignal = 1L << HData.TimerPort->mp_SigBit;
sigrec = Wait(dossignal | timersignal | appsignal | SIGBREAKF_CTRL_F);
if (sigrec & SIGBREAKF_CTRL_F)
{
D(kprintf("diskchange interrupt!\n"));
Check_Disk(&HData);
}
if (sigrec & timersignal)
{
if (HData.HConfig.ScanInterval)
{
if (++timercount == HData.HConfig.ScanInterval)
{
Check_Disk(&HData);
timercount = 0;
}
}
/* turn off the motor if it is on (Motor_Off() knows whether it's on) */
Motor_Off(HData.CD);
/* retry to display the AppIcon, in case something went wrong before */
if (HData.DiskInserted == DI_CDDA_DISK) Show_CDDA_Icon(&HData);
GetMsg(HData.TimerPort);
Send_Timer_Request(&HData);
}
if (sigrec & appsignal)
{
struct Message *msg;
while (msg = GetMsg(HData.AppPort))
{
ReplyMsg (msg);
if (HData.PlayCDDA[0])
SystemTags(HData.PlayCDDA,
SYS_Input,Open("NIL:",MODE_OLDFILE),
SYS_Output,Open("NIL:",MODE_NEWFILE),
SYS_Asynch,TRUE,
TAG_END);
else
{
int res;
if (HData.Playing) res = Stop_Play_Audio(HData.CD);
else res = Start_Play_Audio(HData.CD);
if (res) HData.Playing = !HData.Playing;
}
}
}
if (sigrec & dossignal)
{
struct Message *msg;
while (msg = GetMsg(HData.MyPort))
{
LONG res1,res2;
packet = (struct DosPacket *)msg->mn_Node.ln_Name;
switch (packet->dp_Type)
{
case ACTION_FINDINPUT:
case ACTION_FINDUPDATE:
case ACTION_FINDOUTPUT:
D(switch (packet->dp_Type)
{
case ACTION_FINDUPDATE:
kprintf("ACTION_FINDUPDATE fh %lx lock %lx name \"%b\" ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3);
break;
case ACTION_FINDINPUT:
kprintf("ACTION_FINDINPUT fh %lx lock %lx name \"%b\" ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3);
break;
case ACTION_FINDOUTPUT:
kprintf("ACTION_FINDOUTPUT fh %lx lock %lx name \"%b\" ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3);
break;
}
)
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg2,&HData)))
{
CDROM_OBJ *obj;
if (!(obj = OpenObject(packet->dp_Arg2,packet->dp_Arg3,&HData)))
{
res2 = IoErr();
if (res2 == ERROR_OBJECT_NOT_FOUND &&
packet->dp_Type == ACTION_FINDOUTPUT)
res2 = ERROR_DISK_WRITE_PROTECTED;
else if (res2 == TDERR_DiskChanged)
res2 = packet->dp_Arg2 ? ERROR_DEVICE_NOT_MOUNTED : ERROR_NO_DISK;
}
else
{
if (packet->dp_Type == ACTION_FINDOUTPUT)
{
Close_Object(obj);
res2 = ERROR_DISK_WRITE_PROTECTED;
}
else if (obj->directory_f)
{
Close_Object(obj);
res2 = ERROR_OBJECT_WRONG_TYPE;
}
else
{
/* make a lock out of the object, this way the icon will not */
/* disappear from the Workbench if there are files open */
if (((struct FileHandle *)BADDR(packet->dp_Arg1))->fh_Args =
cdlock(obj,ACCESS_READ,&HData))
res1 = DOSTRUE;
else res2 = ERROR_NO_FREE_STORE;
}
}
}
break;
case ACTION_FH_FROM_LOCK:
D(kprintf("ACTION_FH_FROM_LOCK fh %lx lock %lx ->\n",packet->dp_Arg1,packet->dp_Arg2));
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg2,&HData)))
{
CDROM_OBJ *obj = getlockfile(packet->dp_Arg2,&HData);
if (obj->directory_f)
res2 = ERROR_OBJECT_WRONG_TYPE;
else
{
((struct FileHandle *)BADDR(packet->dp_Arg1))->fh_Args = packet->dp_Arg2;
res1 = DOSTRUE;
}
}
break;
case ACTION_END:
D(kprintf("ACTION_END fh_Args %lx ->\n",packet->dp_Arg1));
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
cdunlock(packet->dp_Arg1,&HData);
res1 = DOSTRUE;
}
break;
case ACTION_READ:
D(kprintf("ACTION_READ fh_Args %lx buffer %lx len %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3));
res1 = -1;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
res1 = Read_From_File(HData.CDVolume,
getlockfile(packet->dp_Arg1,&HData),
(APTR)packet->dp_Arg2,packet->dp_Arg3);
res2 = IoErr();
if (res2 == TDERR_DiskChanged)
res2 = ERROR_DEVICE_NOT_MOUNTED;
if (res1 > 0) res2 = 0;
}
break;
case ACTION_SEEK:
D(kprintf("ACTION_SEEK fh_Args %lx pos %ld offs %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3));
res1 = -1;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
CDROM_OBJ *obj = getlockfile(packet->dp_Arg1,&HData);
res1 = obj->pos;
if (res2 = Seek_Position(obj,packet->dp_Arg2,packet->dp_Arg3))
res1 = -1;
}
break;
case ACTION_LOCATE_OBJECT:
D(kprintf("ACTION_LOCATE_OBJECT lock %lx name \"%b\" mode %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3));
res1 = NULL;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
CDROM_OBJ *obj;
if (!(obj = OpenObject(packet->dp_Arg1,packet->dp_Arg2,&HData)))
{
res2 = IoErr();
if (res2 == TDERR_DiskChanged)
res2 = packet->dp_Arg1 ? ERROR_DEVICE_NOT_MOUNTED : ERROR_NO_DISK;
}
else
{
if (!(res1 = cdlock(obj,packet->dp_Arg3,&HData)))
res2 = ERROR_NO_FREE_STORE;
}
}
break;
case ACTION_FREE_LOCK:
D(kprintf("ACTION_FREE_LOCK lock %lx ->\n",packet->dp_Arg1));
cdunlock(packet->dp_Arg1,&HData);
res1 = DOSTRUE;
break;
case ACTION_COPY_DIR:
case ACTION_COPY_DIR_FH:
D(switch (packet->dp_Type)
{
case ACTION_COPY_DIR:
kprintf("ACTION_COPY_DIR lock %lx ->\n",packet->dp_Arg1);
break;
case ACTION_COPY_DIR_FH:
kprintf("ACTION_COPY_DIR_FH fh_Args %lx ->\n",packet->dp_Arg1);
break;
}
)
res1 = NULL;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)) && packet->dp_Arg1)
{
CDROM_OBJ *new;
if (!(new = Clone_Object(getlockfile(packet->dp_Arg1,&HData))))
res2 = ERROR_NO_FREE_STORE;
else
{
if (!(res1 = cdlock(new,ACCESS_READ,&HData)))
res2 = ERROR_NO_FREE_STORE;
}
}
break;
case ACTION_PARENT:
case ACTION_PARENT_FH:
D(switch (packet->dp_Type)
{
case ACTION_PARENT:
D(kprintf("ACTION_PARENT lock %lx ->\n",packet->dp_Arg1));
break;
case ACTION_PARENT_FH:
kprintf("ACTION_PARENT_FH fh_Args %lx ->\n",packet->dp_Arg1);
break;
}
)
res1 = NULL;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
if (packet->dp_Arg1)
{
CDROM_OBJ *obj = getlockfile(packet->dp_Arg1,&HData);
CDROM_OBJ *parent;
if (Is_Top_Level_Object(HData.CDVolume,obj))
res2 = 0;
else
{
if (!(parent = Find_Parent(HData.CDVolume,obj)))
{
res2 = IoErr();
if (res2 == TDERR_DiskChanged)
res2 = ERROR_DEVICE_NOT_MOUNTED;
}
else
{
if (!(res1 = cdlock(parent,ACCESS_READ,&HData)))
res2 = ERROR_NO_FREE_STORE;
}
}
}
else
res2 = ERROR_OBJECT_NOT_FOUND;
}
break;
case ACTION_SAME_LOCK: /* Lock Lock Bool */
{
CDROM_OBJ *obj1 = getlockfile(packet->dp_Arg1,&HData);
CDROM_OBJ *obj2 = getlockfile(packet->dp_Arg2,&HData);
struct FileLock *plock1,*plock2;
D(kprintf("ACTION_SAME_LOCK lock1 %lx lock2 %lx ->\n",packet->dp_Arg1,packet->dp_Arg2));
plock1 = BADDR(packet->dp_Arg1);
plock2 = BADDR(packet->dp_Arg2);
if (plock1->fl_Volume != plock2->fl_Volume)
res1 = DOSFALSE;
else if (Same_Objects(obj1,obj2))
res1 = DOSTRUE;
else
res1 = DOSFALSE;
res2 = 0;
}
break;
case ACTION_EXAMINE_OBJECT:
case ACTION_EXAMINE_FH:
D(switch (packet->dp_Type)
{
case ACTION_EXAMINE_OBJECT:
kprintf("ACTION_EXAMINE_OBJECT lock %lx fib %lx ->\n",packet->dp_Arg1,packet->dp_Arg2);
break;
case ACTION_EXAMINE_FH:
kprintf("ACTION_EXAMINE_FH fh_Args %lx fib %lx ->\n",packet->dp_Arg1,packet->dp_Arg2);
break;
}
)
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
struct FileInfoBlock *fib;
CDROM_INFO info;
fib = BADDR(packet->dp_Arg2);
memset(fib,0,sizeof(struct FileInfoBlock));
if (!(res2 = CDROM_Info(HData.CDVolume,
getlockfile(packet->dp_Arg1,&HData),&info)))
{
Fill_FileInfoBlock(fib,&info,HData.CDVolume,&HData);
res1 = DOSTRUE;
}
}
break;
case ACTION_EXAMINE_NEXT:
D(kprintf("ACTION_EXAMINE_NEXT lock %lx fib %lx (%s) ->\n",packet->dp_Arg1,packet->dp_Arg2,&((struct FileInfoBlock *)BADDR(packet->dp_Arg2))->fib_FileName[1]));
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
struct FileInfoBlock *fib;
CDROM_OBJ *dir = getlockfile(packet->dp_Arg1,&HData);
CDROM_INFO info;
fib = BADDR(packet->dp_Arg2);
if (!dir->directory_f)
res2 = ERROR_OBJECT_WRONG_TYPE;
else if (res2 = Examine_Next(HData.CDVolume,dir, &info,(unsigned long *)&fib->fib_DiskKey))
{
if (res2 == TDERR_DiskChanged)
res2 = ERROR_DEVICE_NOT_MOUNTED;
}
else
{
Fill_FileInfoBlock(fib,&info,HData.CDVolume,&HData);
res1 = DOSTRUE;
}
}
break;
case ACTION_INFO:
D(kprintf("ACTION_INFO lock %lx infodata %lx ->\n",packet->dp_Arg1,packet->dp_Arg2));
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
Fill_InfoData(BADDR(packet->dp_Arg2),&HData);
res1 = DOSTRUE;
}
break;
case ACTION_DISK_INFO:
D(kprintf("ACTION_DISK_INFO infodata %lx ->\n",packet->dp_Arg1));
Fill_InfoData(BADDR(packet->dp_Arg1),&HData);
res1 = DOSTRUE;
break;
case ACTION_CURRENT_VOLUME:
D(kprintf("ACTION_CURRENT_VOLUME fh_Args %lx ->\n",packet->dp_Arg1));
if (packet->dp_Arg1)
res1 = ((struct FileLock *)BADDR(packet->dp_Arg1))->fl_Volume;
else res1 = MKBADDR(HData.CurrentVolume);
res2 = HData.fssm->fssm_Unit;
break;
case ACTION_INHIBIT:
D(kprintf("ACTION_INHIBIT bool %ld ->\n",packet->dp_Arg1));
if (packet->dp_Arg1 != DOSFALSE)
{
RemoveVolumeNode(&HData);
HData.Inhibited++;
HData.DiskInserted = DI_DISK_OK; /* this way any operation */
/* will fail with error "not a dos disk" */
}
else
{
if (HData.Inhibited)
{
HData.Inhibited--;
HData.CD->t_changeint2 = (unsigned long)-2;
HData.DiskInserted = DI_NO_DISK; /* force a disk check */
Check_Disk(&HData);
}
}
break;
case ACTION_READ_LINK:
{
CDROM_OBJ *obj;
CDROM_OBJ *parentdir = getlockfile (packet->dp_Arg1,&HData);
char *outbuf = (char *) packet->dp_Arg3;
t_ulong maxlength = packet->dp_Arg4;
int offs;
char buf[256];
int res;
D(kprintf("ACTION_READ_LINK lock %lx path %s buffer %lx bufsiz %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4));
res1 = 0;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
{
offs = Check_For_Volume_Name_Prefix ((char *) packet->dp_Arg2);
obj = Open_Object(HData.CDVolume,parentdir, (char *) packet->dp_Arg2 + offs);
if (obj)
{
res = Get_Link_Name (HData.CDVolume,obj, buf, sizeof (buf));
if (res == 0 || strlen (buf) + HData.VolumeName[0] + 1 >= maxlength)
strncpy (outbuf, "illegal_link", maxlength - 1);
else
{
if (buf[0] == ':')
strcpy (outbuf,&HData.VolumeName[0]);
else
outbuf[0] = 0;
strcat (outbuf, buf);
}
outbuf[maxlength - 1] = 0;
Close_Object(obj);
res1 = strlen (outbuf);
}
else
{
res2 = IoErr();
if (res2 == TDERR_DiskChanged)
res2 = packet->dp_Arg1 ? ERROR_DEVICE_NOT_MOUNTED : ERROR_NO_DISK;
}
}
}
break;
case ACTION_RENAME_DISK:
case ACTION_SERIALIZE_DISK:
D(switch (packet->dp_Type)
{
case ACTION_RENAME_DISK:
kprintf("ACTION_RENAME_DISK name \"%b\" ->\n",packet->dp_Arg1);
break;
case ACTION_SERIALIZE_DISK:
kprintf("ACTION_SERIALIZE_DISK ->\n");
break;
}
)
res1 = DOSFALSE;
if (!HData.CurrentVolume)
res2 = HData.DiskInserted == DI_NO_DISK ? ERROR_NO_DISK : ERROR_NOT_A_DOS_DISK;
else res2 = ERROR_DISK_WRITE_PROTECTED;
break;
case ACTION_FORMAT:
D(kprintf("ACTION_FORMAT name \"%b\" dostype %lx ->\n",packet->dp_Arg1,packet->dp_Arg2));
res1 = DOSFALSE;
if (HData.DiskInserted == DI_NO_DISK) res2 = ERROR_NO_DISK;
else res2 = ERROR_DISK_WRITE_PROTECTED;
break;
case ACTION_WRITE:
case ACTION_SET_FILE_SIZE:
D(switch (packet->dp_Type)
{
case ACTION_WRITE:
kprintf("ACTION_WRITE fh_Args %lx buffer %lx len %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3);
break;
case ACTION_SET_FILE_SIZE:
kprintf("ACTION_SET_FILE_SIZE fh_Args %lx pos %ld mode %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3);
break;
}
)
res1 = -1;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
res2 = ERROR_DISK_WRITE_PROTECTED;
break;
case ACTION_DELETE_OBJECT:
case ACTION_RENAME_OBJECT:
case ACTION_CREATE_DIR:
case ACTION_MAKE_LINK:
D(switch (packet->dp_Type)
{
case ACTION_DELETE_OBJECT:
kprintf("ACTION_DELETE_OBJECT lock %lx name \"%b\" ->\n",packet->dp_Arg1,packet->dp_Arg2);
break;
case ACTION_RENAME_OBJECT:
kprintf("ACTION_RENAME_OBJECT lock %lx name \"%b\" newlock %lx newname \"%b\" ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4);
break;
case ACTION_CREATE_DIR:
kprintf("ACTION_CREATE_DIR lock %lx name \"%b\" ->\n",packet->dp_Arg1,packet->dp_Arg2);
break;
case ACTION_MAKE_LINK:
kprintf("ACTION_MAKE_LINK lock %lx name \"%b\" dest %lx soft %ld ->\n",packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4);
break;
}
)
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg1,&HData)))
res2 = ERROR_DISK_WRITE_PROTECTED;
break;
case ACTION_SET_PROTECT:
case ACTION_SET_COMMENT:
case ACTION_SET_DATE:
case ACTION_SET_OWNER:
D(switch (packet->dp_Type)
{
case ACTION_SET_PROTECT:
kprintf("ACTION_SET_PROTECT (arg1 unused) lock %lx name \"%b\" bits %lx ->\n",packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4);
break;
case ACTION_SET_COMMENT:
kprintf("ACTION_SET_COMMENT (arg1 unused) lock %lx name \"%b\" comment \"%b\" ->\n",packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4);
break;
case ACTION_SET_DATE:
kprintf("ACTION_SET_DATE (arg1 unused) lock %lx name \"%b\" date %lx ->\n",packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4);
break;
case ACTION_SET_OWNER:
kprintf("ACTION_SET_OWNER (arg1 unused) lock %lx name \"%b\" owner %lx ->\n",packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4);
break;
}
)
res1 = DOSFALSE;
if (!(res2 = CheckLock(packet->dp_Arg2,&HData)))
res2 = ERROR_DISK_WRITE_PROTECTED;
break;
case ACTION_IS_FILESYSTEM:
D(kprintf("ACTION_IS_FILESYSTEM ->\n"));
res1 = DOSTRUE;
break;
case ACTION_FLUSH:
D(kprintf("ACTION_FLUSH ->\n"));
res1 = DOSTRUE;
break;
default:
D(kprintf("Unknown pkt #%ld %lx %lx %lx %lx %lx ->\n",(LONG)packet->dp_Type,
packet->dp_Arg1,packet->dp_Arg2,packet->dp_Arg3,packet->dp_Arg4,packet->dp_Arg5));
res1 = DOSFALSE;
res2 = ERROR_ACTION_NOT_KNOWN;
break;
}
ReturnPacket(packet,HData.MyPort,res1,res2);
}
}
}
}
VOID AddToFSResource(ULONG dostype,BPTR seglist)
{
struct FileSysResource *FileSysResBase;
if (FileSysResBase = (struct FileSysResource *)OpenResource(FSRNAME))
{
struct FileSysEntry *fse,*nfse;
Forbid();
fse = (struct FileSysEntry *)FileSysResBase->fsr_FileSysEntries.lh_Head;
while (nfse = (struct FileSysEntry *)fse->fse_Node.ln_Succ)
{
/* if filesystem already in resource, return */
if (fse->fse_DosType == dostype) break;
fse = nfse;
}
Permit();
if (!nfse && (fse = AllocMem(sizeof(struct FileSysEntry),MEMF_PUBLIC | MEMF_CLEAR)))
{
fse->fse_Node.ln_Name = (UBYTE *)&versionstring20[7];
fse->fse_DosType = dostype;
fse->fse_Version = ((LONG)VERSION) << 16 | REVISION;
fse->fse_PatchFlags = 0x180;
fse->fse_SegList = seglist;
fse->fse_GlobalVec = -1;
Forbid();
AddHead(&FileSysResBase->fsr_FileSysEntries,fse);
Permit();
}
}
}
/*
* Return a packet back to DOS.
*/
VOID ReturnPacket(struct DosPacket *packet,struct MsgPort *port,LONG res1,LONG res2)
{
struct Message *mess;
struct MsgPort *replyport;
D(kprintf("%lx %ld\n",res1,res2));
packet->dp_Res1 = res1;
packet->dp_Res2 = res2;
replyport = packet->dp_Port;
mess = packet->dp_Link;
packet->dp_Port = port;
mess->mn_Node.ln_Name = (UBYTE *)packet;
PutMsg(replyport,mess);
}
/*
* 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(LONG bstr, char *buf)
{
unsigned char *str = BADDR(bstr);
memcpy(buf,&str[1],str[0]);
buf[str[0]] = 0;
}
/*
* Locate and open an object on the CD-ROM. Returns a CDROM_OBJ pointer,
* or NULL if an error occurred. If an error occurred, IoErr() contains
* the error code.
*/
CDROM_OBJ *OpenObject(BPTR parentlock,BSTR name,struct HData *HData)
{
CDROM_OBJ *parentdir;
CDROM_OBJ *obj;
int offs;
char buf[256];
parentdir = getlockfile(parentlock,HData);
btos(name,buf);
offs = Check_For_Volume_Name_Prefix(buf);
if (!buf[offs])
{
if (parentdir)
obj = Clone_Object(parentdir);
else
obj = Open_Top_Level_Directory(HData->CDVolume);
}
else
obj = Open_Object(HData->CDVolume,parentdir,buf + offs);
if (obj)
{
if (obj->symlink_f)
{
Close_Object(obj);
obj = NULL;
SetIoErr(ERROR_IS_SOFT_LINK);
}
}
/* else IoErr() already contains the error code set by Open_Object() */
return(obj);
}
/*
* The lock function. The file has already been checked to see if it
* is lockable given the mode.
* Returns NULL if out of memory.
*/
BPTR cdlock(CDROM_OBJ *cdfile, int mode,struct HData *HData)
{
struct FileLock *lock;
if (lock = AllocVec(sizeof(struct FileLock),MEMF_PUBLIC | MEMF_CLEAR))
{
lock->fl_Key = (long) cdfile;
lock->fl_Access = ACCESS_READ;
lock->fl_Task = HData->MyPort;
lock->fl_Volume = MKBADDR(HData->CurrentVolume);
lock->fl_Link = HData->LockList;
HData->LockList = MKBADDR(lock);
}
return(MKBADDR(lock));
}
void cdunlock (BPTR lock,struct HData *HData)
{
struct FileLock *flock,*cl,*ncl;
struct DosList *vol;
if (!lock) return;
flock = BADDR(lock);
vol = BADDR(flock->fl_Volume);
if (vol == HData->CurrentVolume)
cl = (struct FileLock *)&HData->LockList;
else
cl = (struct FileLock *)&vol->dol_misc.dol_volume.dol_LockList;
while (cl && (ncl = BADDR(cl->fl_Link)) != flock) cl = ncl;
if (cl) cl->fl_Link = ncl->fl_Link;
if (vol != HData->CurrentVolume && !vol->dol_misc.dol_volume.dol_LockList)
{
RemoveDosList(vol);
CreateInputEvent(FALSE,HData);
}
Close_Object(getlockfile(lock,HData));
FreeVec(flock); /* free lock */
}
/*
* Check if the volume associated to the given lock is present in the drive.
* Return 0 if everything OK, or an error code (to be assigned to res2) if
* an error occurred.
*/
LONG CheckLock(BPTR lock,struct HData *HData)
{
if (lock && BADDR(((struct FileLock *)BADDR(lock))->fl_Volume) != HData->CurrentVolume)
return(ERROR_DEVICE_NOT_MOUNTED);
else if (!HData->CurrentVolume)
return(HData->DiskInserted == DI_NO_DISK ? ERROR_NO_DISK : ERROR_NOT_A_DOS_DISK);
else return(0);
}
/*
* GETLOCKFILE(bptrlock)
*
* Return the CDROM_OBJ (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 CDROM.
*/
CDROM_OBJ *getlockfile(BPTR lock,struct HData *HData)
{
struct FileLock *rl = BADDR(lock);
if (rl)
return (CDROM_OBJ *) rl->fl_Key;
return HData->TopLevelObj;
}
/*
* If p_pathname contains a ':' character, return the position of the first
* character after ':'
* Otherwise, return 0.
*/
int Check_For_Volume_Name_Prefix (char *p_pathname)
{
char *pos = strchr (p_pathname, ':');
return pos ? (pos - p_pathname) + 1 : 0;
}
/*
* Fill an InfoData structure with info on the current volume.
*/
VOID Fill_InfoData(struct InfoData *id,struct HData *HData)
{
memset(id,0,sizeof(struct InfoData));
id->id_UnitNumber = HData->fssm->fssm_Unit;
id->id_DiskState = ID_WRITE_PROTECTED;
if (HData->CurrentVolume)
{
id->id_NumBlocks = Volume_Size(HData->CDVolume);
id->id_NumBlocksUsed = id->id_NumBlocks - Volume_Free(HData->CDVolume);
D(kprintf("total %ld used %ld\n",id->id_NumBlocks,id->id_NumBlocksUsed));
id->id_DiskType = ID_DOS_DISK;
id->id_VolumeNode = MKBADDR(HData->CurrentVolume);
id->id_BytesPerBlock = Block_Size(HData->CDVolume);
id->id_InUse = HData->LockList;
}
else
{
if (HData->Inhibited) id->id_DiskType = 0x42555359; /* BUSY */
else switch (HData->DiskInserted)
{
case DI_NO_DISK:
case DI_CDDA_DISK:
id->id_DiskType = ID_NO_DISK_PRESENT;
break;
case DI_UNREADABLE_DISK:
id->id_DiskType = ID_UNREADABLE_DISK;
break;
case DI_DISK_OK:
default:
id->id_DiskType = ID_NOT_REALLY_DOS;
break;
}
}
}
/*
* Fills a FileInfoBlock with the information contained in the
* directory record of a CD-ROM directory or file.
*/
void Fill_FileInfoBlock (struct FileInfoBlock *p_fib, CDROM_INFO *p_info, VOLUME *p_volume,struct HData *HData)
{
char *src = p_info->name;
char *dest = p_fib->fib_FileName+1;
int len = p_info->name_length;
if (p_info->symlink_f)
p_fib->fib_DirEntryType = ST_SOFTLINK;
else
p_fib->fib_DirEntryType = p_info->directory_f ? ST_USERDIR : ST_FILE;
p_fib->fib_EntryType = p_fib->fib_DirEntryType;
if (len == 1 && *src == ':')
{
/* root of file system: */
p_fib->fib_DirEntryType = ST_USERDIR;
/* file name == volume name: */
/* VolumeName is a BCPL string, but it's NULL-terminated. */
strcpy(p_fib->fib_FileName,HData->VolumeName);
}
else
{
short real_len;
/* copy file name: */
memcpy(dest,src,len);
real_len = len;
/* remove version number */
{
WORD i;
i = len;
while (i)
{
if (src[--i] == ';')
{
real_len = i;
break;
}
}
}
p_fib->fib_FileName[0] = real_len;
/* NULL terminate the string */
p_fib->fib_FileName[real_len + 1] = 0;
}
p_fib->fib_Protection = 0;
p_fib->fib_Size = p_info->file_length;
p_fib->fib_NumBlocks = p_info->file_length >> 11;
if (p_info->symlink_f)
strcpy (p_fib->fib_Comment, "\x0DSymbolic link");
else
p_fib->fib_Comment[0] = 0;
p_fib->fib_Date.ds_Days = p_info->date / (24 * 60 * 60);
p_fib->fib_Date.ds_Minute = (p_info->date % (24 * 60 * 60)) / 60;
p_fib->fib_Date.ds_Tick = (p_info->date % 60) * TICKS_PER_SECOND;
}
/*
* Mount a volume.
*/
void Mount(struct HData *HData)
{
Clear_Sector_Buffers(HData->CD); /* make sure the buffers are empty */
HData->CD->t_changeint2 = HData->CD->t_changeint;
HData->DiskInserted = DI_DISK_OK;
if (!(HData->CDVolume = Open_Volume(HData->CD,
HData->HConfig.Lowercase)))
{
D(kprintf ("!!! cannot open VOLUME !!!\n"));
/* A secondary error less than ERROR_NO_FREE_STORE is supposed to be a device */
/* error. */
if (IoErr() < ERROR_NO_FREE_STORE)
HData->DiskInserted = DI_UNREADABLE_DISK;
if (Has_Audio_Tracks(HData->CD))
{
HData->DiskInserted = DI_CDDA_DISK;
Show_CDDA_Icon(HData);
}
CreateInputEvent(TRUE,HData);
return;
}
if (!(HData->TopLevelObj = Open_Top_Level_Directory(HData->CDVolume)))
{
D(kprintf ("!!! cannot open top level directory !!!\n"));
Close_Volume(HData->CDVolume);
HData->CDVolume = NULL;
CreateInputEvent(TRUE,HData);
return;
}
D(kprintf ("***mounting***\n"));
Volume_ID(HData->CDVolume,&HData->VolumeName[1],sizeof(HData->VolumeName)-2);
if (!(HData->VolumeName[0] = strlen(&HData->VolumeName[1])))
strcpy(HData->VolumeName,"\7Unnamed");
/* if we are (probably) dealing with a floppy, read geometry */
if (HData->CD->use_trackdisk && !HData->envec->de_LowCyl &&
Volume_Size(HData->CDVolume) < 10000)
{
struct DriveGeometry dg;
HData->CD->scsireq->io_Command = TD_GETGEOMETRY;
HData->CD->scsireq->io_Data = &dg;
HData->CD->scsireq->io_Length = sizeof(struct DriveGeometry);
if (!DoIO((struct IORequest *)HData->CD->scsireq))
{
HData->envec->de_SizeBlock = dg.dg_SectorSize / 4;
HData->envec->de_HighCyl = dg.dg_Cylinders - 1;
HData->envec->de_Surfaces = dg.dg_Heads;
HData->envec->de_BlocksPerTrack = dg.dg_TrackSectors;
}
}
if (!CreateVolumeNode(HData))
{
Close_Object(HData->TopLevelObj);
Close_Volume(HData->CDVolume);
HData->CDVolume = NULL;
}
CreateInputEvent(TRUE,HData);
}
/*
* Create Volume node and add to the device list. This will
* cause the WORKBENCH to recognize us as a disk. If we don't
* create a Volume node, Wb will not recognize us.
*/
struct DosList *CreateVolumeNode(struct HData *HData)
{
struct DosInfo *di = BADDR(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
struct DosList *dl;
ULONG p_volume_date = Volume_Creation_Date(HData->CDVolume);
Forbid();
for (dl = BADDR(di->di_DevInfo);dl;dl = BADDR(dl->dol_Next))
{
if (dl->dol_Type == DLT_VOLUME &&
!Stricmp(BADDR(dl->dol_Name),HData->VolumeName) &&
dl->dol_misc.dol_volume.dol_DiskType == HData->envec->de_DosType &&
dl->dol_misc.dol_volume.dol_VolumeDate.ds_Days == p_volume_date / (24 * 60 * 60) &&
dl->dol_misc.dol_volume.dol_VolumeDate.ds_Minute == (p_volume_date % (24 * 60 * 60)) / 60 &&
dl->dol_misc.dol_volume.dol_VolumeDate.ds_Tick == (p_volume_date % 60) * TICKS_PER_SECOND)
break;
}
if (!dl)
{
if (dl = MakeDosEntry(&HData->VolumeName[1],DLT_VOLUME))
{
dl->dol_misc.dol_volume.dol_DiskType = HData->envec->de_DosType;
dl->dol_misc.dol_volume.dol_VolumeDate.ds_Days = p_volume_date / (24 * 60 * 60);
dl->dol_misc.dol_volume.dol_VolumeDate.ds_Minute = (p_volume_date % (24 * 60 * 60)) / 60;
dl->dol_misc.dol_volume.dol_VolumeDate.ds_Tick = (p_volume_date % 60) * TICKS_PER_SECOND;
dl->dol_Next = di->di_DevInfo;
di->di_DevInfo = MKBADDR(dl);
}
}
/* make sure that dl_Task is NULL, otherwise it means that another handler */
/* is using the same disk - we can't create our volume */
if (dl && !dl->dol_Task)
{
struct FileLock *lock;
dl->dol_Task = HData->MyPort;
HData->CurrentVolume = dl;
HData->LockList = dl->dol_misc.dol_volume.dol_LockList;
dl->dol_misc.dol_volume.dol_LockList = NULL;
lock = BADDR(HData->LockList);
while (lock)
{
lock->fl_Task = HData->MyPort;
lock = BADDR(lock->fl_Link);
}
}
else dl = NULL;
Permit();
return(dl);
}
/*
* Remove Volume entry.
*/
void RemoveVolumeNode(struct HData *HData)
{
if (HData->DiskInserted != DI_NO_DISK)
{
Hide_CDDA_Icon(HData);
HData->CD->t_changeint2 = HData->CD->t_changeint;
HData->DiskInserted = DI_NO_DISK;
HData->Playing = FALSE;
if (HData->CurrentVolume)
{
D(kprintf("***unmounting***\n"));
/* remove the volume node only if there are no outstanding locks */
if (!HData->LockList)
RemoveDosList(HData->CurrentVolume);
else
{
HData->CurrentVolume->dol_Task = NULL;
HData->CurrentVolume->dol_misc.dol_volume.dol_LockList = HData->LockList;
}
Close_Object(HData->TopLevelObj);
Close_Volume(HData->CDVolume);
HData->CurrentVolume = NULL;
HData->LockList = NULL;
HData->CDVolume = NULL;
}
CreateInputEvent(FALSE,HData);
}
}
VOID RemoveDosList(struct DosList *vol)
{
struct DosInfo *di;
struct DosList *dl;
void *dlp;
D(kprintf("Removing Volume node\n"));
Forbid ();
di = BADDR(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
dlp = &di->di_DevInfo;
for (dl = BADDR(di->di_DevInfo);dl && dl != vol;dl = BADDR(dl->dol_Next))
dlp = &dl->dol_Next;
if (dl == vol)
{
*(BPTR *)dlp = dl->dol_Next;
FreeDosEntry(dl);
}
Permit();
}
/*
* Open timer device structures:
*/
int Open_Timer_Device(struct HData *HData)
{
if (HData->TimerPort = CreateMsgPort())
{
if (HData->TimerIO = (struct timerequest *)
CreateIORequest(HData->TimerPort,sizeof(struct timerequest)))
{
if (!OpenDevice(TIMERNAME,UNIT_VBLANK,HData->TimerIO,0))
return(1);
DeleteIORequest(HData->TimerIO);
}
DeleteMsgPort(HData->TimerPort);
HData->TimerPort = NULL;
}
return(0);
}
/*
* Open input device structures:
*/
int Open_Input_Device(struct HData *HData)
{
struct MsgPort *port;
if (port = CreateMsgPort())
{
if (HData->InputIO = CreateIORequest(port,sizeof(struct IOStdReq)))
{
if (!OpenDevice("input.device",0,HData->InputIO,0))
{
InputBase = (struct Library *)HData->InputIO->io_Device;
return(1);
}
DeleteIORequest(HData->InputIO);
}
DeleteMsgPort(port);
}
return(0);
}
/*
* Send timer request
*/
void Send_Timer_Request(struct HData *HData)
{
HData->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
HData->TimerIO->tr_time.tv_secs = 1;
HData->TimerIO->tr_time.tv_micro = 0;
SendIO(HData->TimerIO);
}
/*
* Check whether the disk has been removed or inserted.
*/
void Check_Disk (struct HData *HData)
{
int i;
unsigned long l1, l2;
/* don't check for disk if we are inhibited */
if (HData->Inhibited) return;
D(kprintf ("Checking Disk...\n"));
if (HData->CD->use_trackdisk)
{
i = (Test_Unit_Ready(HData->CD));
l1 = HData->CD->t_changeint;
l2 = HData->CD->t_changeint2;
if (l1 != l2)
{
if (i)
{
D(kprintf ("disk has been inserted (T %ld)\n", l1));
RemoveVolumeNode(HData);
Mount(HData);
}
else
{
if (HData->DiskInserted != DI_NO_DISK)
{
D(kprintf ("disk has been removed (T %ld)\n", l1));
RemoveVolumeNode(HData);
}
}
}
}
else
{
if (HData->DiskInserted != DI_NO_DISK)
{
if (!Test_Unit_Ready(HData->CD))
{
D(kprintf ("disk has been removed\n"));
RemoveVolumeNode(HData);
}
}
else
{
/* have to call Test_Unit_Ready() twice because the first SCSI command */
/* after a disk insertion is always rejected. */
if (Test_Unit_Ready (HData->CD) || Test_Unit_Ready (HData->CD))
{
D(kprintf ("disk has been inserted\n"));
Mount(HData);
}
}
}
}
/*
* generate a `disk inserted/removed' event, in order to get Workbench to
* rescan the DosList and update the list of volume icons.
*/
VOID CreateInputEvent(BOOL inserted,struct HData *HData)
{
struct InputEvent ie;
memset(&ie,0,sizeof(struct InputEvent));
ie.ie_Class = inserted ? IECLASS_DISKINSERTED : IECLASS_DISKREMOVED;
HData->InputIO->io_Command = IND_WRITEEVENT;
HData->InputIO->io_Data = &ie;
HData->InputIO->io_Length = sizeof(struct InputEvent);
DoIO(HData->InputIO);
}
int
Get_Startup (struct HData *HData)
{
enum {
ARG_LOWERCASE,
ARG_TRACKDISK,
ARG_POLL,
ARGCOUNT
};
LONG Args[ARGCOUNT];
UBYTE *LocalBuffer;
struct RDArgs *ArgsPtr;
int result = FALSE,len,i;
UBYTE *p_startup;
/* Clear the argument vector. */
memset (Args, 0, sizeof(Args));
/* valid startup entry? */
if (HData->envec->de_TableSize >= DE_CONTROL)
p_startup = BADDR(HData->envec->de_Control);
else p_startup = NULL;
if (!p_startup) p_startup = "";
/* Get the contents of the startup field. */
len = p_startup[0];
if (!(LocalBuffer = AllocVec(len + 2,MEMF_ANY)))
return(FALSE);
memcpy (LocalBuffer, p_startup + 1, len);
/* terminate string with LF (fix ReadArgs() bug) */
LocalBuffer[len] = '\n';
/* Provide null-termination. */
/* Provide null-termination. */
LocalBuffer[len+1] = 0;
/* Remove leading quotes. */
for (i = 0 ; i < len ; i++) {
if (LocalBuffer[i] != ' ') {
if (LocalBuffer[i] == '\"')
LocalBuffer[i] = ' ';
break;
}
}
/* Remove trailing quotes. */
for (i = len - 1 ; i >= 0 ; i--) {
if (LocalBuffer[i] != ' '){
if (LocalBuffer[i] == '\"')
LocalBuffer[i] = ' ';
break;
}
}
if (ArgsPtr = (struct RDArgs *) AllocDosObjectTags (DOS_RDARGS,TAG_DONE))
{
/* Don't prompt for input! */
ArgsPtr->RDA_Flags |= RDAF_NOPROMPT;
/* Set up for local parsing. */
ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
ArgsPtr->RDA_Source.CS_CurChr = 0;
/* Read the arguments. */
if (ReadArgs(
"L=LOWERCASE/S,"
"T=TRACKDISK/S,"
"P=POLL/S",
Args,ArgsPtr))
{
result = TRUE;
HData->HConfig.Lowercase = Args[ARG_LOWERCASE];
D(kprintf("lowercase = %ld\n",HData->HConfig.Lowercase));
HData->HConfig.UseTrackdisk = Args[ARG_TRACKDISK];
D(kprintf("trackdisk = %ld\n",HData->HConfig.UseTrackdisk));
if (Args[ARG_POLL])
HData->HConfig.ScanInterval = 3;
D(kprintf("scaninterval = %ld\n",HData->HConfig.ScanInterval));
FreeArgs(ArgsPtr);
}
FreeDosObject (DOS_RDARGS, ArgsPtr);
}
if (result) {
if (!(HData->CD = Open_CDROM (&((UBYTE *)BADDR(HData->fssm->fssm_Device))[1],
HData->fssm->fssm_Unit,HData->fssm->fssm_Flags,
HData->envec->de_LowCyl * HData->envec->de_Surfaces *
HData->envec->de_BlocksPerTrack * 4 * HData->envec->de_SizeBlock,
HData->HConfig.UseTrackdisk,
/* if the Mask is in 24-bit range, use 24BITDMA memory */
(HData->envec->de_Mask & 0xff000000) ?
HData->envec->de_BufMemType : HData->envec->de_BufMemType | MEMF_24BITDMA,
HData->envec->de_NumBuffers,5, /* file buffers */
!HData->HConfig.ScanInterval))) {
result = FALSE;
}
}
FreeVec(LocalBuffer);
return result;
}
VOID Show_CDDA_Icon(struct HData *HData)
{
struct DiskObject *appicon;
if (!IconBase) IconBase = OpenLibrary("icon.library",37);
if (!WorkbenchBase) WorkbenchBase = OpenLibrary("workbench.library",37);
if (!IconBase || !WorkbenchBase || HData->AppIcon) return;
if (!(appicon = GetDiskObject("ENV:sys/def_CDDAdisk")) &&
!(appicon = GetDefDiskObject(WBKICK)))
return;
strncpy(HData->VolumeName,&((UBYTE *)BADDR(HData->MyDevNode->dol_Name))[1],sizeof(HData->VolumeName)-1);
if (strlen(HData->VolumeName) < sizeof(HData->VolumeName)-5)
strcat(HData->VolumeName,":CDDA");
if (HData->AppPort = CreateMsgPort())
HData->AppIcon = AddAppIconA(0,0,HData->VolumeName,HData->AppPort,NULL,appicon,NULL);
/* copy the default tool name */
if (appicon->do_DefaultTool)
strcpy(HData->PlayCDDA,appicon->do_DefaultTool);
else HData->PlayCDDA[0] = 0;
/* the icon may be freed immediately, the Workbench copies it internally */
FreeDiskObject(appicon);
/* AddAppIconA may fail if the Workbench has not yet been loaded. */
if (!HData->AppIcon)
{
DeleteMsgPort(HData->AppPort);
HData->AppPort = NULL;
}
}
void Hide_CDDA_Icon(struct HData *HData)
{
struct Message *msg;
if (HData->AppIcon)
{
RemoveAppIcon(HData->AppIcon);
HData->AppIcon = NULL;
if (HData->AppPort)
{
while (msg = GetMsg(HData->AppPort))
ReplyMsg(msg);
DeleteMsgPort(HData->AppPort);
HData->AppPort = NULL;
}
}
}