/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* |_o_o|\\ Copyright (c) 1987 The Software Distillery. All Rights Reserved */ /* |. o.| || This program may not be distributed without the permission of */ /* | . | || the authors: BBS: */ /* | o | || John Toebes Dave Baker John Mainwaring */ /* | . |// */ /* ====== */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Lock.c - lock manipulation */ /* ActLock, ActDupLock, ActUnLock */ /*---------------------------------------------------------------------------*/ /* Structure of a Lock: */ /* struct FileLock { */ /* BPTR fl_Link; Next lock in the chain of device locks */ /* LONG fl_Key; Block number of directory or file header */ /* LONG fl_Access; Shared Read (-2) or Exclusive Write (-1) */ /* struct MsgPort * fl_Task; Handler process for Lock (Us) */ /* BPTR fl_Volume; Node in DevInfo structure for Lock */ /* }; */ /*---------------------------------------------------------------------------*/ #include "handler.h" long GetKey(global,lock) struct global *global; struct FileLock *lock; { if (global->volume == NULL) { global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED; return(0); } if (lock == NULL) return(global->Root); return(lock->fl_Key); } /* create a lock to be returned */ struct FileLock *CreateLock(global, key, mode) GLOBAL global; KEY key; int mode; { struct FileLock *lock; int access; lock = NULL; if (global->volume == NULL) { global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED; key = 0; } if (key) { /* if we are creating a write lock, make sure we can lock the disk */ access = 0; BUG(("Searching for locks from %08lx\n", BADDR(global->volume->dl_Lock))); Forbid(); /* Now run through the list of locks for this volume to figure out */ /* What level of access it is currently locked for */ for (lock = (struct FileLock *)BADDR(global->volume->dl_Lock); lock != NULL && access == 0; lock = (struct FileLock *)BADDR(lock->fl_Link)) { /* Does it match what we want to access? */ if (lock->fl_Key == key) access = lock->fl_Access; } Permit(); BUG(("Access outstanding is %ld\n", access)); /* Given the prevailing access mode, see if we will allow the new lock */ switch(mode) { case SHARED_LOCK: if (access == EXCLUSIVE_LOCK) { /* Not legal, tell them so... */ global->pkt->dp_Res2 = ERROR_OBJECT_IN_USE; return(NULL); } break; case EXCLUSIVE_LOCK: /* Does anyone else have it open? */ if (access) { /* Not legal, tell them so... */ global->pkt->dp_Res2 = ERROR_OBJECT_IN_USE; return(NULL); } break; default: BUG(("Invalid access %ld requested for key %ld\n", mode, key)); global->pkt->dp_Res2 = ERROR_INVALID_LOCK; return(NULL); } if ((lock = (struct FileLock *) DosAllocMem(global, sizeof(struct FileLock))) != NULL) { BUG(("Creating the lock %08lx for key=%ld\n", lock, key)); /* now fill in the lock */ lock->fl_Key = key; lock->fl_Access = mode; lock->fl_Task = global->port; lock->fl_Volume = MKBADDR(global->volume); Forbid(); lock->fl_Link = global->volume->dl_Lock; global->volume->dl_Lock = MKBADDR(lock); Permit(); BUG(("Task=%08lx Vol=%08lx\n", lock->fl_Task, lock->fl_Volume)); } } return(lock); } void freelock(global, lock) GLOBAL global; struct FileLock *lock; { struct FileLock *this; /* freeing NULL (root lock) is a bad move */ if (lock == NULL) { BUG(("NULL Lock\n")); return; } if (global->volume == NULL) { global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED; return; } /* locate the lock on the global volume list */ Forbid(); if ((this = (struct FileLock *)BADDR(global->volume->dl_Lock)) == lock) global->volume->dl_Lock = lock->fl_Link; else { while(this != NULL && (struct FileLock *)BADDR(this->fl_Link) != lock) this = (struct FileLock *)BADDR(this->fl_Link); if (this == NULL) /* lock wasn't in chain - don't drop through to free memory */ { Permit(); BUG(("Lock not found in chain\n")); return; } else this->fl_Link = lock->fl_Link; } Permit(); DosFreeMem((char *)lock); } void ActLock(global, pkt) GLOBAL global; struct DosPacket *pkt; /* a pointer to the dos packet sent */ /* Arg1: Lock */ /* Arg2: Name */ /* Arg3: Mode: ACCESS_READ, ACCESS_WRITE */ { KEY key; struct FileLock *lock; BUG(("Action Lock\n")); BUGBSTR("File to lock: ", pkt->dp_Arg2); key = GetKey(global,(struct FileLock *)pkt->dp_Arg1); key = LocateEntry(global, key, (char *)pkt->dp_Arg2); lock = CreateLock(global, key, pkt->dp_Arg3); BUG(("Lock created at %08lx\n", lock)); pkt->dp_Res1 = MKBADDR(lock); } void ActDupLock(global,pkt) GLOBAL global; struct DosPacket *pkt; /* a pointer to the dos packet sent */ { struct FileLock *lock; BUG(("Action DupLock\n")); lock = (struct FileLock *)pkt->dp_Arg1; lock = CreateLock(global, lock->fl_Key, lock->fl_Access); pkt->dp_Res1 = MKBADDR(lock); } void ActUnLock(global, pkt) GLOBAL global; struct DosPacket *pkt; /* a pointer to the dos packet sent */ { struct FileLock *lock; lock = (struct FileLock *)pkt->dp_Arg1; BUG(("Action UnLock\n")); freelock(global, lock); pkt->dp_Res1 = DOS_TRUE; }