home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 18
/
amigaformatcd18.iso
/
-in_the_mag-
/
emulation
/
emus
/
fs1541
/
packet.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-31
|
28KB
|
1,178 lines
/*
FS1541
packet.c
This is the packet processor.
If you are new to this subject and want to learn about it, you *must*
have the Amiga Guru Book next to you and compare the routines for each
packet with the specifications in the book -- then you will understand!
*/
#include <string.h>
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>
#include "main.h"
#include "packet.h"
#include "support.h"
#include "volume.h"
#include "disk.h"
static BOOL getfiledata(UBYTE entry, struct FHArg1 *fharg1);
static BPTR trylockfile(LONG *err2, BSTR name, LONG access, struct FHArg1 *fharg1, BOOL allow_root);
static UBYTE fname1[20];
int inhibited = FALSE;
static LONG TestLock(struct FileLock *fl);
static inline LONG TestLockRef(struct FileLock *fl);
static struct BAM empty_bam = {
0x12,0x01,0x41,0x00,
{
0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,0x15FFFF1F,
0x15FFFF1F,0x15FFFF1F,0x11FCFF07,0x13FFFF07,
0x13FFFF07,0x13FFFF07,0x13FFFF07,0x13FFFF07,
0x13FFFF07,0x12FFFF03,0x12FFFF03,0x12FFFF03,
0x12FFFF03,0x12FFFF03,0x12FFFF03,0x11FFFF01,
0x11FFFF01,0x11FFFF01,0x11FFFF01,0x11FFFF01
},
{
0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58
},
{
0xA0,0xA0
},
{
0x59,0x59,0xA0,0x32,0x41
},
{
0xA0,0xA0,0xA0,0xA0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}
};
/*-------------------------------------------------------------------------*/
void DoPackets(void)
{
struct DosPacket *packet;
while((packet = GetPacket(ourport)))
{
LONG error = DOSFALSE;
LONG err2 = 0;
BOOL f = TRUE;
dpsender = packet->dp_Port;
if(inhibited)
{
switch(packet->dp_Type)
{
case ACTION_DISK_INFO:
case ACTION_INHIBIT:
case ACTION_FORMAT:
break;
default:
f = FALSE;
err2 = ERROR_NOT_A_DOS_DISK;
break;
}
}
if(f) switch(packet->dp_Type)
{
case ACTION_LOCATE_OBJECT:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
struct FHArg1 fharg1;
if((err2 = TestLock(fl)))
break;
else if(!curvolumenode)
{
err2 = disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
break;
}
/* This FileSystem is easy since we don't have to take
care of any FileLock path tracking and resolving */
error = trylockfile(&err2, packet->dp_Arg2, packet->dp_Arg3, &fharg1, TRUE);
MotorOff();
break;
}
case ACTION_FREE_LOCK:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
if(fl)
freelock(fl);
MotorOff();
error = DOSTRUE;
break;
}
case ACTION_COPY_DIR:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
if(fl) {
if(fl->fl_Access == EXCLUSIVE_LOCK) {
/* Don't duplicate exclusive locks */
err2 = ERROR_OBJECT_IN_USE;
}
else {
if(fl->fl_Volume == MKBADDR(curdoslist)) {
/* Try to duplicate it! */
err2 = ERROR_NO_FREE_STORE;
error = makelock(fl->fl_Key, SHARED_LOCK);
}
else {
/* The reference disk is currently not inserted. */
err2 = ERROR_DEVICE_NOT_MOUNTED;
}
}
}
else {
if(curvolumenode) {
/* Return shared lock on root directory */
err2 = ERROR_NO_FREE_STORE;
error = makelock(0, SHARED_LOCK);
}
else {
err2 = ERROR_NO_DISK;
}
}
break;
}
case ACTION_PARENT:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
if(fl) {
if(!(err2 = TestLockRef(fl))) {
if(fl->fl_Key != 0) {
/* Return shared lock on root directory */
err2 = ERROR_NO_FREE_STORE;
error = makelock(0, SHARED_LOCK);
}
else {
err2 = 0;
}
}
}
else {
err2 = 0;
}
break;
}
case ACTION_SAME_LOCK:
{
struct FileLock *fl1 = BADDR(packet->dp_Arg1);
struct FileLock *fl2 = BADDR(packet->dp_Arg2);
err2 = 0;
if(fl1 == fl2 || ((fl1->fl_Volume == fl2->fl_Volume) && (fl1->fl_Key == fl2->fl_Key)))
error = DOSTRUE;
break;
}
case ACTION_EXAMINE_OBJECT:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
struct FileInfoBlock *fib = BADDR(packet->dp_Arg2);
if(fl && fl->fl_Key != 0) {
/* Examine file */
struct FHArg1 fharg1;
int entry;
int special;
fib->fib_DiskKey = 0;
fib->fib_DirEntryType = fib->fib_EntryType = ST_FILE;
fib->fib_Protection = 0;
fib->fib_Comment[0] = '\0';
fib->fib_Date.ds_Days = 0;
fib->fib_Date.ds_Minute = 0;
fib->fib_Date.ds_Tick = 0;
if(fl->fl_Volume != MKBADDR(curdoslist)) {
/* The reference disk is currently not inserted. */
err2 = ERROR_DEVICE_NOT_MOUNTED;
break;
}
if((special = fl->fl_Key & FLKEY_SPECIALMASK)) {
/* Examine virtual files */
static struct { STRPTR s; ULONG l; } tbl[3] = {
{ VIRTUAL_FILE_D64, D64_SIZE },
{ VIRTUAL_FILE_OPT, 0 }
};
int index = (special>>FLKEY_SPECIALSHIFT)-2;
switch(special) {
case FLKEY_DOLLAR:
strcpy(&fib->fib_FileName[1], VIRTUAL_FILE_DOLLAR);
fib->fib_FileName[0] = strlen(VIRTUAL_FILE_DOLLAR);
fib->fib_Size = curvolumenode->dollarlen;
error = DOSTRUE;
break;
case FLKEY_D64: case FLKEY_OPT:
strcpy(&fib->fib_FileName[1], tbl[index].s);
fib->fib_FileName[0] = strlen(tbl[index].s);
fib->fib_Size = tbl[index].l;
error = DOSTRUE;
break;
case FLKEY_DISKINFO:
strcpy(&fib->fib_FileName[1], VIRTUAL_FILE_DISKINFO);
fib->fib_FileName[0] = strlen(VIRTUAL_FILE_DISKINFO);
fib->fib_Size = diskiconlength;
error = DOSTRUE;
break;
default:
err2 = ERROR_OBJECT_NOT_FOUND;
break;
}
}
else {
for(entry=0;entry<dirsize;entry++)
if(fl->fl_Key == ((directory[entry].datat<<8)|directory[entry].datas))
break;
if(entry<dirsize) {
if(getfiledata(entry, &fharg1)) {
copy64name(&fib->fib_FileName[1], directory[entry].name, 16);
fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
fib->fib_Size = fharg1.len;
error = DOSTRUE;
}
else err2 = ERROR_OBJECT_NOT_FOUND;
}
else err2 = ERROR_OBJECT_NOT_FOUND;
}
}
else {
/* Prepare for EXAMINE_NEXT, return volume name in
fib_FileName */
fib->fib_DiskKey = 0;
fib->fib_DirEntryType = fib->fib_EntryType = ST_ROOT;
strcpy(&fib->fib_FileName[1], &curvolumenode->name[1]);
fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
fib->fib_Protection = 0;
fib->fib_Comment[0] = '\0';
fib->fib_Date.ds_Days = 0;
fib->fib_Date.ds_Minute = 0;
fib->fib_Date.ds_Tick = 0;
error = DOSTRUE;
}
break;
}
case ACTION_EXAMINE_NEXT:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
struct FileInfoBlock *fib = BADDR(packet->dp_Arg2);
if((err2 = TestLock(fl)))
break;
fib->fib_DirEntryType = fib->fib_EntryType = ST_FILE;
err2 = ERROR_NO_MORE_ENTRIES;
while(fib->fib_DiskKey < dirsize) {
int entry;
struct FHArg1 fharg1;
entry = fib->fib_DiskKey++;
if(getfiledata(entry, &fharg1)) {
copy64name(&fib->fib_FileName[1], directory[entry].name, 16);
fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
fib->fib_Size = fharg1.len;
fib->fib_NumBlocks = fharg1.numblocks;
error = DOSTRUE;
break;
}
}
if(error == DOSFALSE)
MotorOff();
break;
}
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
{
struct FileHandle *fh = BADDR(packet->dp_Arg1);
struct FileLock *fl = BADDR(packet->dp_Arg2);
struct FHArg1 *fharg1;
LONG access = packet->dp_Type==ACTION_FINDINPUT ? SHARED_LOCK : EXCLUSIVE_LOCK;
if((err2 = TestLock(fl)))
break;
if((fharg1 = AllocVec(sizeof(struct FHArg1), MEMF_ANY|MEMF_CLEAR))) {
if(trylockfile(&err2, packet->dp_Arg3, access, fharg1, FALSE)) {
if(fharg1->number!=NUM_VIRTUAL || access==SHARED_LOCK
|| (((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) == FLKEY_D64) {
/* Allow virtual files only for reading, exception is $d64 */
fh->fh_Arg1 = (LONG)fharg1;
fh->fh_Port = DOSFALSE;
error = DOSTRUE;
}
else {
/* But new files with virtual file names can be created,
which will be real then. */
freelock((struct FileLock*)BADDR(fharg1->lock));
err2 = ERROR_OBJECT_NOT_FOUND;
}
}
if((error==DOSFALSE && access==EXCLUSIVE_LOCK && err2!=ERROR_INVALID_COMPONENT_NAME) || packet->dp_Type==ACTION_FINDOUTPUT) {
if(!wprotected) {
if(error==DOSFALSE) {
/* Create new file */
UWORD dblk;
if(dirsize < 144) {
if((dblk = AllocBlock(18,0))) {
UBYTE clrblk[256];
memset(&clrblk, 0, sizeof(clrblk));
clrblk[1] = 1;
if(putblock_ts(dblk>>8, dblk&0xff, &clrblk)) {
struct DirEntry *de = &directory[dirsize++];
memset(de, 0, sizeof(struct DirEntry));
de->type = 0x82; /* PRG, closed */
de->datat = dblk>>8;
de->datas = dblk&0xff;
de->lengthl = 1;
asciito64(de->name, fname1, 16);
StartUDSTimer();
if(trylockfile(&err2, packet->dp_Arg3, access, fharg1, FALSE)) {
fh->fh_Arg1 = (LONG)fharg1;
fh->fh_Port = DOSFALSE;
error = DOSTRUE;
}
}
else {
err2 = ABORT_DISK_ERROR;
FreeBlock(dblk>>8, dblk&0xff);
}
}
else err2 = ERROR_DISK_FULL;
}
else err2 = ERROR_DISK_FULL;
}
else if(fharg1->number != NUM_VIRTUAL) /* trying to overwrite $d64 */ {
/* Overwrite existing file */
struct DataBlock *block;
UBYTE t,s;
int i;
for(i=0,t=fharg1->t,s=fharg1->s; t; t=block->t,s=block->s,i++) {
block = getblock_ts(t,s);
if(i>0) FreeBlock(t,s);
}
fharg1->len = 0;
fharg1->numblocks = 1;
block = getblock_ts(fharg1->t, fharg1->s);
block->t = 0;
block->s = 1;
putblock_ts(fharg1->t, fharg1->s, block);
}
}
else err2 = ERROR_DISK_WRITE_PROTECTED;
}
else {
if(error==DOSTRUE) {
/* Open existing file, already done. */
}
/* else err2 still set from first trylockfile() call */
}
if(error == DOSFALSE) {
FreeVec(fharg1);
MotorOff();
}
}
else err2 = ERROR_NO_FREE_STORE;
break;
}
case ACTION_READ:
{
struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
APTR buffer = (APTR)packet->dp_Arg2;
ULONG togo = packet->dp_Arg3;
struct DataBlock *block = NULL;
if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock)))) {
error = -1;
break;
}
if(fharg1->pos + togo >= fharg1->len)
togo = fharg1->len - fharg1->pos;
error = 0;
if(fharg1->number == NUM_VIRTUAL) {
/* Handle virtual files */
int special = ((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK;
switch(special) {
case FLKEY_DOLLAR:
CopyMem(&curvolumenode->dollarbuf[fharg1->pos], buffer, togo);
fharg1->pos += togo;
error += togo;
break;
case FLKEY_DISKINFO:
CopyMem(&diskiconimg[fharg1->pos], buffer, togo);
fharg1->pos += togo;
error += togo;
break;
case FLKEY_D64:
while(togo) {
ULONG size, offset;
if(!(block = getputblock((fharg1->pos)>>8, FALSE)))
break;
offset = (fharg1->pos) & 255;
size = 256 - offset;
if(togo < size)
size = togo;
CopyMem(&((UBYTE*)block)[offset], buffer, size);
buffer += size;
fharg1->pos += size;
error += size;
togo -= size;
}
break;
default:
break;
}
}
else {
/* Handle real files */
while(togo) {
ULONG size;
if(fharg1->p == 254) {
if(!block)
if(!(block = getblock_ts(fharg1->t, fharg1->s)))
break;
fharg1->p = 0;
fharg1->t = block->t;
fharg1->s = block->s;
}
size = 254 - fharg1->p;
if(togo < size)
size = togo;
if(!(block = getblock_ts(fharg1->t, fharg1->s)))
break;
CopyMem(&block->data[fharg1->p], buffer, size);
buffer += size;
fharg1->p += size;
fharg1->pos += size;
error += size;
togo -= size;
}
}
break;
}
case ACTION_WRITE:
{
struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
APTR buffer = (APTR)packet->dp_Arg2;
ULONG togo = packet->dp_Arg3;
struct DataBlock *block = NULL;
struct DataBlock newblk;
error = -1;
if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
break;
if(wprotected) {
err2 = ERROR_DISK_WRITE_PROTECTED;
break;
}
error = 0;
if((((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) == FLKEY_D64) {
/* Handle writes to the $d64 file */
if(fharg1->pos + togo >= D64_SIZE)
togo = D64_SIZE - fharg1->pos;
while(togo) {
ULONG size, offset;
if(!(block = getputblock((fharg1->pos)>>8, FALSE)))
break;
offset = (fharg1->pos) & 255;
size = 256 - offset;
if(togo < size)
size = togo;
CopyMem(buffer, &((UBYTE*)block)[offset], size);
getputblock((fharg1->pos)>>8, TRUE);
buffer += size;
fharg1->pos += size;
error += size;
togo -= size;
}
break;
}
while(togo) {
ULONG size;
if(!block)
block = getblock_ts(fharg1->t, fharg1->s);
if(fharg1->p == 254) {
/* Switch to next block */
if(!block->t) {
/* Allocate new block */
UWORD dblk;
if(!(dblk = AllocBlock(fharg1->t, fharg1->s))) {
err2 = ERROR_DISK_FULL;
break;
}
fharg1->p = 0;
block->t = dblk>>8;
block->s = dblk&0xff;
putblock_ts(fharg1->t, fharg1->s, block); /* link to previous block */
fharg1->t = block->t;
fharg1->s = block->s;
fharg1->numblocks++;
block = &newblk;
memset(&newblk, 0, sizeof(newblk));
block->t = 0;
block->s = 1;
}
else {
/* Jump to existing next block */
fharg1->p = 0;
fharg1->t = block->t;
fharg1->s = block->s;
block = getblock_ts(fharg1->t, fharg1->s);
}
}
size = 254 - fharg1->p;
if(togo < size)
size = togo;
/* Insert data */
CopyMem(buffer, &block->data[fharg1->p], size);
buffer += size;
/* Advance block pointer and dump it */
fharg1->p += size;
if(!block->t)
block->s = fharg1->p + 1;
putblock_ts(fharg1->t, fharg1->s, block);
/* Adjust length field if necessary */
fharg1->pos += size;
if(fharg1->pos > fharg1->len)
fharg1->len = fharg1->pos;
error += size;
togo -= size;
}
break;
}
case ACTION_SET_FILE_SIZE: {
error = -1;
err2 = ERROR_ACTION_NOT_KNOWN;
break;
}
case ACTION_SEEK:
{
struct FHArg1 fharg1bak, *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
LONG move = packet->dp_Arg2;
if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
break;
error = fharg1->pos;
err2 = ERROR_SEEK_ERROR;
switch(packet->dp_Arg3) {
case OFFSET_BEGINNING:
move = move - error;
break;
case OFFSET_CURRENT:
break;
case OFFSET_END:
move = move + fharg1->len - error;
break;
default:
error = -1;
break;
}
if(error != -1) {
CopyMem(fharg1, &fharg1bak, sizeof(struct FHArg1));
if((error+move)<0 || (error+move)>fharg1->len)
error = -1;
else {
if(((struct FileLock*)BADDR(fharg1->lock))->fl_Key & FLKEY_SPECIALMASK) {
/* Virtual files are easy */
fharg1->pos += move;
}
else {
if(move<0) {
/* When moving back, we have to rescan the whole file */
move = move + error;
fharg1->p = 0;
fharg1->pos = 0;
fharg1->t = fharg1->t0;
fharg1->s = fharg1->s0;
}
while(move) {
ULONG size;
struct DataBlock *block;
if(fharg1->p == 254) {
block = getblock_ts(fharg1->t, fharg1->s);
if(!block) {
CopyMem(&fharg1bak, fharg1, sizeof(struct FHArg1));
error = -1;
err2 = ABORT_DISK_ERROR;
break;
}
fharg1->p = 0;
fharg1->t = block->t;
fharg1->s = block->s;
}
size = 254 - fharg1->p;
if(move < size)
size = move;
fharg1->p += size;
fharg1->pos += size;
move -= size;
}
}
}
}
break;
}
case ACTION_END:
{
struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
if((err2 = TestLockRef((struct FileLock*)BADDR(fharg1->lock))))
break;
if(fharg1->len != fharg1->len0) {
/* File has been modified, update disk structure */
int i;
for(i=0;i<dirsize;i++)
if(directory[i].datat == fharg1->t0
&& directory[i].datas == fharg1->s0)
{
UWORD blks = fharg1->numblocks;
directory[i].lengthl = blks&0xff;
directory[i].lengthh = blks>>8;
directory[i].type |= 0x80;
}
StartUDSTimer();
}
freelock(BADDR(fharg1->lock));
FreeVec(fharg1);
error = DOSTRUE;
break;
}
case ACTION_IS_FILESYSTEM:
/* Yes, we are. */
error = DOSTRUE;
break;
case ACTION_CURRENT_VOLUME:
{
struct FHArg1 *fharg1 = (struct FHArg1 *)packet->dp_Arg1;
/* The packet name is somewhat misleading... */
if(fharg1)
error = ((struct FileLock*)BADDR(fharg1->lock))->fl_Volume;
else {
if(curvolumenode)
error = (LONG)MKBADDR(curdoslist);
else
error = NULL;
}
break;
}
case ACTION_INFO:
case ACTION_DISK_INFO:
{
struct InfoData *id;
if(packet->dp_Type == ACTION_INFO) {
struct FileLock *fl = BADDR(packet->dp_Arg1);
if(fl && fl->fl_Volume != MKBADDR(curdoslist)) {
/* The reference disk is currently not inserted. */
err2 = ERROR_DEVICE_NOT_MOUNTED;
break;
}
id = BADDR(packet->dp_Arg2);
}
else {
id = BADDR(packet->dp_Arg1);
}
id->id_NumSoftErrors = numsofterrors;
id->id_NumBlocks = 683;
id->id_NumBlocksUsed = UsedBlocks();
id->id_BytesPerBlock = 254;
id->id_DiskState = hardwprot ? ID_WRITE_PROTECTED : (wprotected ? ID_VALIDATING : ID_VALIDATED);
id->id_UnitNumber = fssm->fssm_Unit;
if(curvolumenode) {
id->id_DiskType = ID_DOS_DISK;
id->id_VolumeNode = MKBADDR(curdoslist);
id->id_InUse = curvolumenode->locklist ? DOSTRUE : DOSFALSE;
}
else {
#ifndef ID_BUSY /* My v40 header files don't */
#define ID_BUSY 0x42555359
#endif
id->id_DiskType = inhibited ? ID_BUSY : (disk_inserted ? ID_UNREADABLE_DISK : ID_NO_DISK_PRESENT);
}
error = DOSTRUE;
break;
}
case ACTION_INHIBIT:
{
/* We could have trouble here if the DosList is locked,
but then again, one shouldn't lock it for INHIBIT. */
if(packet->dp_Arg1 == DOSTRUE) {
if(inhibited == FALSE) {
inhibited = TRUE;
StopUDSTimer();
MotorOff();
DoDiskRemove();
}
}
else if(inhibited == TRUE) {
DoDiskInsert();
inhibited = FALSE;
}
error = DOSTRUE;
break;
}
case ACTION_CREATE_DIR:
err2 = ERROR_INVALID_COMPONENT_NAME;
break;
case ACTION_DELETE_OBJECT:
{
struct FileLock *fl = BADDR(packet->dp_Arg1);
struct FHArg1 fharg1;
if((err2 = TestLock(fl)))
break;
if(!wprotected) {
if(trylockfile(&err2, packet->dp_Arg2, EXCLUSIVE_LOCK, &fharg1, FALSE)) {
struct DataBlock *block;
UBYTE t,s;
freelock((struct FileLock*)BADDR(fharg1.lock));
if(fharg1.number != NUM_VIRTUAL) {
/* We do this only for non-virtual files. */
for(t=fharg1.t,s=fharg1.s; t; t=block->t,s=block->s) {
block = getblock_ts(t,s);
FreeBlock(t,s);
}
directory[fharg1.number].type = 0x00;
StartUDSTimer();
error = DOSTRUE;
}
else err2 = ERROR_DELETE_PROTECTED;
}
}
else err2 = ERROR_DISK_WRITE_PROTECTED;
MotorOff();
break;
}
case ACTION_FORMAT:
{
UBYTE buf[18];
STRPTR a;
struct DataBlock blk1;
ResetDisk();
if(!hardwprot) {
if((a = BADDR(packet->dp_Arg1))) {
int l = a[0]>16 ? 16 : a[0];
CopyMem(&a[1], buf, l);
buf[l] = '\0';
}
else buf[0] = '\0';
asciito64(empty_bam.name, buf, 16);
putblock_ts(18,0,&empty_bam);
memset(&blk1, 0, sizeof(blk1));
blk1.s = 0xff;
putblock_ts(18,1,&blk1);
error = DOSTRUE;
}
else err2 = ERROR_DISK_WRITE_PROTECTED;
break;
}
case ACTION_RENAME_DISK:
{
UBYTE buf[18];
STRPTR a;
if(curvolumenode) {
if(!wprotected) {
if((a = BADDR(packet->dp_Arg1))) {
int l = a[0]>16 ? 16 : a[0];
CopyMem(&a[1], buf, l);
buf[l] = '\0';
}
else buf[0] = '\0';
asciito64(bam->name, buf, 16);
while(!AttemptLockDosList(LDF_VOLUMES|LDF_WRITE))
DoPackets();
copy64name(&curvolumenode->name[1], bam->name, 16);
curvolumenode->name[0] = strlen(&curvolumenode->name[1]);
UnLockDosList(LDF_VOLUMES|LDF_WRITE);
StartUDSTimer();
error = DOSTRUE;
}
else err2 = ERROR_DISK_WRITE_PROTECTED;
}
else err2 = disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
break;
}
case ACTION_RENAME_OBJECT:
{
struct FileLock *fl1 = BADDR(packet->dp_Arg1),
*fl2 = BADDR(packet->dp_Arg3);
struct FHArg1 fharg1;
if(!((err2 = TestLock(fl1)) || (err2 = TestLock(fl2)))) {
if(!wprotected) {
if(trylockfile(&err2, packet->dp_Arg2, SHARED_LOCK, &fharg1, FALSE)) {
freelock((struct FileLock*)BADDR(fharg1.lock));
if(fharg1.number != NUM_VIRTUAL) {
STRPTR a;
UBYTE buf[256];
if((a = BADDR(packet->dp_Arg4))) {
CopyMem(&a[1], buf, a[0]);
buf[a[0]] = '\0';
if(!strchr(buf, '/')) {
a = strchr(buf, ':');
strncpy(fname1, a ? a+1 : buf, 17);
fname1[16] = '\0';
asciito64(directory[fharg1.number].name, fname1, 16);
StartUDSTimer();
error = DOSTRUE;
}
else err2 = ERROR_INVALID_COMPONENT_NAME;
}
else err2 = ERROR_INVALID_COMPONENT_NAME;
}
else err2 = ERROR_OBJECT_NOT_FOUND;
}
}
else err2 = ERROR_DISK_WRITE_PROTECTED;
}
break;
}
default:
err2 = ERROR_ACTION_NOT_KNOWN;
break;
}
ReturnPacket(packet, error, err2);
}
}
static LONG TestLock(struct FileLock *fl)
{
if(fl) {
if(fl->fl_Volume != MKBADDR(curdoslist))
/* The reference disk is currently not inserted. */
return(ERROR_DEVICE_NOT_MOUNTED);
if(fl->fl_Key != 0)
/* An invalid lock has been passed. */
return(ERROR_OBJECT_WRONG_TYPE);
}
return(0);
}
static inline LONG TestLockRef(struct FileLock *fl)
{
if(fl->fl_Volume != MKBADDR(curdoslist))
/* The reference disk is currently not inserted. */
return(ERROR_DEVICE_NOT_MOUNTED);
return(0);
}
/*-------------------------------------------------------------------------*/
static BOOL getfiledata(UBYTE entry, struct FHArg1 *fharg1)
{
if(directory[entry].name[0] != 0xa0) {
UWORD type = (directory[entry].type) & 0x7;
if(type!=0x00) { // anything but DEL-Files
struct DataBlock *block;
int i,t,s,size;
for(i=0,t=directory[entry].datat,s=directory[entry].datas,size=0;
i<683; /* a primitive solution to overcome circular links */
t=block->t,s=block->s,i++)
{
if(!(block = getblock_ts(t,s)))
return(FALSE);
if(block->t)
size+=254;
else {
size+=block->s-1;
break;
}
}
if(i<683) {
fharg1->len = fharg1->len0 = size;
fharg1->numblocks = i+1;
fharg1->t = fharg1->t0 = directory[entry].datat;
fharg1->s = fharg1->s0 = directory[entry].datas;
fharg1->number = entry;
return(TRUE);
}
}
}
return(FALSE);
}
/*-------------------------------------------------------------------------*/
/* May only be called if curvolumenode is valid! */
static BPTR trylockfile(LONG *err2, BSTR name, LONG access, struct FHArg1 *fharg1, BOOL allow_root)
{
UBYTE buf[256];
STRPTR a;
LONG error;
error = DOSFALSE;
/* Convert BSTR argument into C string */
if((a = BADDR(name))) {
CopyMem(&a[1], buf, a[0]);
buf[a[0]] = '\0';
if(strchr(buf, '/')) {
/* User tries to access subdirectories */
*err2 = ERROR_INVALID_COMPONENT_NAME;
return(error);
}
a = strchr(buf, ':');
strncpy(fname1, a ? a+1 : buf, 17);
fname1[16] = '\0';
}
else
fname1[0] = '\0';
if(fname1[0] == '\0') {
if(allow_root) {
/* Return lock on root directory */
if(access == EXCLUSIVE_LOCK) {
*err2 = ERROR_OBJECT_IN_USE;
}
else {
*err2 = ERROR_NO_FREE_STORE;
error = makelock(0, access);
}
}
else *err2 = ERROR_OBJECT_WRONG_TYPE;
}
else {
int entry;
*err2 = ERROR_OBJECT_NOT_FOUND;
/* Look up file in directory and lock it */
for(entry=0;entry<dirsize;entry++) {
copy64name(buf, directory[entry].name, 16);
if(!Stricmp(buf, fname1))
break;
}
if(entry == dirsize) {
/* Perhaps we can provide a virtual file */
fharg1->number = NUM_VIRTUAL;
if(!Stricmp(VIRTUAL_FILE_DISKINFO,fname1)) {
*err2 = ERROR_NO_FREE_STORE;
error = fharg1->lock = makelock(FLKEY_DISKINFO, access);
fharg1->len = fharg1->len0 = diskiconlength;
}
else if(fname1[0] == '$') {
if(!Stricmp(VIRTUAL_FILE_DOLLAR,fname1)) {
*err2 = ERROR_NO_FREE_STORE;
error = fharg1->lock = makelock(FLKEY_DOLLAR, access);
fharg1->len = fharg1->len0 = curvolumenode->dollarlen;
}
else if(!Stricmp(VIRTUAL_FILE_D64,fname1)) {
*err2 = ERROR_NO_FREE_STORE;
error = fharg1->lock = makelock(FLKEY_D64, access);
fharg1->len = fharg1->len0 = D64_SIZE;
}
else if(!Stricmp(VIRTUAL_FILE_OPT,fname1)) {
if(!wprotected) {
*err2 = ERROR_NO_FREE_STORE;
error = fharg1->lock = makelock(FLKEY_OPT, access);
fharg1->len = fharg1->len0 = 0;
OptimizeDirectory();
StartUDSTimer();
}
else *err2 = ERROR_DISK_WRITE_PROTECTED;
}
}
}
else {
if(getfiledata(entry, fharg1)) {
if(lockable(fharg1->t, fharg1->s, access)) {
*err2 = ERROR_NO_FREE_STORE;
error = fharg1->lock = makelock(((fharg1->t)<<8)|fharg1->s, access);
}
else *err2 = ERROR_OBJECT_IN_USE;
}
}
}
return(error);
}