home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff236.lzh / DiskHandler / lock.c < prev    next >
C/C++ Source or Header  |  1989-08-09  |  6KB  |  226 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1987 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors:                                          BBS:      */
  5. /* | o  | ||   John Toebes     Dave Baker     John Mainwaring                */
  6. /* |  . |//                                                                  */
  7. /* ======                                                                    */
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9.  
  10. /* Lock.c - lock manipulation */
  11. /* ActLock, ActDupLock, ActUnLock */
  12.  
  13. /*---------------------------------------------------------------------------*/
  14. /* Structure of a Lock:                                                      */
  15. /*   struct FileLock {                                                       */
  16. /*      BPTR fl_Link;             Next lock in the chain of device locks     */
  17. /*      LONG fl_Key;              Block number of directory or file header   */
  18. /*      LONG fl_Access;           Shared Read (-2) or Exclusive Write (-1)   */
  19. /*      struct MsgPort * fl_Task; Handler process for Lock (Us)              */
  20. /*      BPTR fl_Volume;           Node in DevInfo structure for Lock         */
  21. /*      };                                                                   */
  22. /*---------------------------------------------------------------------------*/
  23. #include "handler.h"
  24.  
  25. long GetKey(global,lock)
  26. struct global *global;
  27. struct FileLock *lock;
  28. {
  29.    if (global->volume == NULL)
  30.       {
  31.       global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
  32.       return(0);
  33.       }
  34.  
  35.    if (lock == NULL)
  36.       return(global->Root);
  37.    return(lock->fl_Key);
  38. }
  39.  
  40. /* create a lock to be returned */
  41. struct FileLock *CreateLock(global, key, mode)
  42. GLOBAL global;
  43. KEY key;
  44. int mode;
  45. {
  46. struct FileLock *lock;
  47. int access;
  48.  
  49.    lock = NULL;
  50.  
  51.    if (global->volume == NULL)
  52.       {
  53.       global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
  54.       key = 0;
  55.       }
  56.  
  57.    if (key)
  58.       {
  59.       /* if we are creating a write lock, make sure we can lock the disk */
  60.       access = 0;
  61.  
  62.       BUG(("Searching for locks from %08lx\n", BADDR(global->volume->dl_Lock)));
  63.  
  64.       Forbid();
  65.       /* Now run through the list of locks for this volume to figure out */
  66.       /* What level of access it is currently locked for                 */
  67.       for (lock = (struct FileLock *)BADDR(global->volume->dl_Lock);
  68.            lock != NULL && access == 0;
  69.            lock = (struct FileLock *)BADDR(lock->fl_Link))
  70.          {
  71.          /* Does it match what we want to access? */
  72.          if (lock->fl_Key == key)
  73.             access = lock->fl_Access;
  74.          }
  75.       Permit();
  76.  
  77.       BUG(("Access outstanding is %ld\n", access));
  78.  
  79.       /* Given the prevailing access mode, see if we will allow the new lock */
  80.       switch(mode)
  81.          {
  82.          case SHARED_LOCK:
  83.             if (access == EXCLUSIVE_LOCK)
  84.                {
  85.                /* Not legal, tell them so... */
  86.                global->pkt->dp_Res2 = ERROR_OBJECT_IN_USE;
  87.                return(NULL);
  88.                }
  89.             break;
  90.  
  91.          case EXCLUSIVE_LOCK:
  92.             /* Does anyone else have it open? */
  93.             if (access)
  94.                {
  95.                /* Not legal, tell them so... */
  96.                global->pkt->dp_Res2 = ERROR_OBJECT_IN_USE;
  97.                return(NULL);
  98.                }
  99.             break;
  100.  
  101.          default:
  102.             BUG(("Invalid access %ld requested for key %ld\n", mode, key));
  103.             global->pkt->dp_Res2 = ERROR_INVALID_LOCK;
  104.             return(NULL);
  105.          }
  106.  
  107.  
  108.       if ((lock = (struct FileLock *)
  109.                   DosAllocMem(global, sizeof(struct FileLock))) != NULL)
  110.          {
  111.          BUG(("Creating the lock %08lx for key=%ld\n", lock, key));
  112.  
  113.          /* now fill in the lock */
  114.          lock->fl_Key = key;
  115.          lock->fl_Access = mode;
  116.          lock->fl_Task = global->port;
  117.          lock->fl_Volume = MKBADDR(global->volume);
  118.  
  119.          Forbid();
  120.          lock->fl_Link = global->volume->dl_Lock;
  121.          global->volume->dl_Lock = MKBADDR(lock);
  122.          Permit();
  123.  
  124.          BUG(("Task=%08lx Vol=%08lx\n", lock->fl_Task, lock->fl_Volume));
  125.          }
  126.       }
  127.    return(lock);
  128. }
  129.  
  130. void freelock(global, lock)
  131. GLOBAL global;
  132. struct FileLock *lock;
  133. {
  134. struct FileLock *this;
  135.  
  136.    /* freeing NULL (root lock) is a bad move    */
  137.    if (lock == NULL)
  138.       {
  139.       BUG(("NULL Lock\n"));
  140.       return;
  141.       }
  142.  
  143.    if (global->volume == NULL)
  144.       {
  145.       global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
  146.       return;
  147.       }
  148.  
  149.    /* locate the lock on the global volume list */
  150.    Forbid();
  151.  
  152.    if ((this = (struct FileLock *)BADDR(global->volume->dl_Lock)) == lock)
  153.       global->volume->dl_Lock = lock->fl_Link;
  154.    else
  155.       {
  156.       while(this != NULL && (struct FileLock *)BADDR(this->fl_Link) != lock)
  157.          this = (struct FileLock *)BADDR(this->fl_Link);
  158.       if (this == NULL)
  159.          /* lock wasn't in chain - don't drop through to free memory */
  160.          {
  161.          Permit();
  162.          BUG(("Lock not found in chain\n"));
  163.          return;
  164.          }
  165.       else
  166.          this->fl_Link = lock->fl_Link;
  167.       }
  168.    Permit();
  169.  
  170.    DosFreeMem((char *)lock);
  171. }
  172.  
  173. void ActLock(global, pkt)
  174. GLOBAL global;
  175. struct DosPacket      *pkt;      /* a pointer to the dos packet sent       */
  176. /* Arg1: Lock */
  177. /* Arg2: Name */
  178. /* Arg3: Mode: ACCESS_READ, ACCESS_WRITE */
  179. {
  180.    KEY key;
  181.    struct FileLock *lock;
  182.  
  183.    BUG(("Action Lock\n"));
  184.    BUGBSTR("File to lock: ", pkt->dp_Arg2);
  185.  
  186.    key = GetKey(global,(struct FileLock *)pkt->dp_Arg1);
  187.  
  188.    key = LocateEntry(global, key, (char *)pkt->dp_Arg2);
  189.  
  190.    lock = CreateLock(global, key, pkt->dp_Arg3);
  191.  
  192.    BUG(("Lock created at %08lx\n", lock));
  193.  
  194.    pkt->dp_Res1 = MKBADDR(lock);
  195. }
  196.  
  197. void ActDupLock(global,pkt)
  198. GLOBAL global;
  199. struct DosPacket      *pkt;      /* a pointer to the dos packet sent       */
  200. {
  201.    struct FileLock *lock;
  202.  
  203.    BUG(("Action DupLock\n"));
  204.  
  205.    lock = (struct FileLock *)pkt->dp_Arg1;
  206.  
  207.    lock = CreateLock(global, lock->fl_Key, lock->fl_Access);
  208.  
  209.    pkt->dp_Res1 = MKBADDR(lock);
  210. }
  211.  
  212. void ActUnLock(global, pkt)
  213. GLOBAL global;
  214. struct DosPacket      *pkt;      /* a pointer to the dos packet sent       */
  215. {
  216.    struct FileLock *lock;
  217.  
  218.    lock = (struct FileLock *)pkt->dp_Arg1;
  219.  
  220.    BUG(("Action UnLock\n"));
  221.  
  222.    freelock(global, lock);
  223.  
  224.    pkt->dp_Res1 = DOS_TRUE;
  225. }
  226.