home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 2 / amigaformatcd02.iso / comms / netsoftware / nethandler.lha / NetHandler / handler / lock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-17  |  9.3 KB  |  315 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
  3. /* |. o.| || Reserved.  This program may not be distributed without the    */
  4. /* | .  | || permission of the authors:                            BBS:    */
  5. /* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
  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. /* create a lock to be returned */
  26. struct FileLock *CreateLock(global, nlock, RLock, Access)
  27. GLOBAL global;
  28. NETPTR nlock;
  29. RPTR RLock;
  30. LONG Access;
  31. {
  32.    struct FileLock *flock;
  33.    NETPTR newnlock;
  34.  
  35.    if(!(flock=(struct FileLock *)
  36.               DosAllocMem(global, sizeof(struct FileLock))) ||
  37.       !(newnlock=(NETPTR) DosAllocMem(global, sizeof(struct NetPtr)))
  38.       )
  39.       return(NULL);
  40.  
  41.    flock->fl_Key = (LONG)newnlock;
  42.    flock->fl_Access = Access;
  43.    flock->fl_Task = global->n.port;
  44.    flock->fl_Volume = MKBADDR(global->volume);
  45.    newnlock->NetNode = nlock->NetNode;
  46.    newnlock->RDevice = nlock->RDevice;
  47.    newnlock->RPtr    = RLock;
  48.  
  49.    /* Link the lock into the lock chain */
  50.    Forbid();
  51.    flock->fl_Link = global->volume->dl_Lock;
  52.    global->volume->dl_Lock = MKBADDR(flock);
  53.    Permit();
  54.  
  55.    return(flock);
  56. }
  57.  
  58. void FreeLock(global, flock)
  59. GLOBAL global;
  60. struct FileLock *flock;
  61. {
  62.    struct FileLock *current, *next;
  63.  
  64.    if(!flock) return;
  65.  
  66.    Forbid();
  67.    if((current=(struct FileLock *)BADDR(global->volume->dl_Lock)) == flock)
  68.    {
  69.       global->volume->dl_Lock = flock->fl_Link;
  70.       Permit();
  71.       BUG(("FreeLock: Head lock freed, new head = %lx\n", 
  72.          global->volume->dl_Lock));
  73.    }
  74.    else
  75.    {
  76.       for(next=NULL; 
  77.           current && 
  78.              (next=(struct FileLock *)BADDR(current->fl_Link)) != flock;
  79.           current = next);
  80.  
  81.       if(!next)
  82.       {
  83.          Permit();
  84.          BUG(("****************************************\n"));
  85.          BUG(("******* Lock not found in chain ********\n"));
  86.          BUG(("****************************************\n"));
  87.          return;
  88.       }
  89.       else
  90.       {
  91.          current->fl_Link = next->fl_Link;
  92.          Permit();
  93.          BUG(("Lock found and removed from chain\n"));
  94.       }
  95.    }
  96.  
  97.    /* If RDevice == NULL, we have a dummy nlock, so don't free it */
  98.    /* Otherwise, free it                                          */
  99.    if(((NETPTR)flock->fl_Key)->RDevice)
  100.       DosFreeMem((char *)flock->fl_Key);  /* Free the net lock   */
  101.  
  102.    DosFreeMem((char *)flock);          /* Free the local lock */
  103.  
  104. }
  105.  
  106. void ActLock(global, pkt)
  107. GLOBAL global;
  108. struct DosPacket      *pkt;      /* a pointer to the dos packet sent       */
  109. /* Arg1: Lock */
  110. /* Arg2: Name */
  111. /* Arg3: Mode: ACCESS_READ, ACCESS_WRITE */
  112. {
  113.    NETPTR nlock;
  114.    struct FileLock *flock;
  115.  
  116.    BUG(("Action Lock\n"));
  117.    BUGBSTR("File to lock: ", pkt->dp_Arg2);
  118.  
  119.    /**********************************************************************/
  120.    /* If the given lock is on the local root, call the ParseName routine */
  121.    /* to determine if we need to call the remote nodes.  If ParseName    */
  122.    /* returns 1, we have a name of the form "NET:" and we should return  */
  123.    /* a lock on the root of NET:.  If it returns 0, we have a name of    */
  124.    /* the form "NET:FOO" or "NET:FOO/BAR", etc and we need to call the   */
  125.    /* remote node specified in the pseudo-lock returned.                 */
  126.    /**********************************************************************/
  127.    
  128.    if((!(flock=(struct FileLock *)pkt->dp_Arg1) || 
  129.        !(nlock=(NETPTR)flock->fl_Key)->RDevice))
  130.    {
  131.       /* ParseName returns 1 if we are locking the root.  It fills in */
  132.       /* nlock with a pointer to the pseudolock for the node.  The    */
  133.       /* pseudolock is kept in the NetNode struct.                    */
  134.       /* Any leftover parts of the name are left in RP.Data as a      */
  135.       /* BCPL string.                                                 */
  136.       if(ParseName(global, (char *)pkt->dp_Arg2, &nlock, global->RP.Data))
  137.       {
  138.          BUG(("ActLock: Returning lock on root\n"));
  139.          /* Return lock on root */
  140.          /* ParseName has put the pseudolock for the root into nlock */
  141.          pkt->dp_Res1 = 
  142.                MKBADDR(CreateLock(global, nlock, NULL, pkt->dp_Arg3));
  143.          return;
  144.       }
  145.       else if(!nlock)
  146.       {
  147.          BUG(("ActLock: Couldn't find node\n"));
  148.          pkt->dp_Res1 = NULL;
  149.          pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
  150.          return;
  151.       }
  152. #if DEBUG
  153.       else
  154.          BUG(("ActLock: got nlock, falling through\n"));
  155. #endif
  156.    }
  157.    else
  158.    {
  159.       BUGBSTR("ActLock: Relative open, node ", nlock->NetNode->name);
  160.       /* We are doing a relative open - put filename in Data */
  161.       MBSTR(pkt->dp_Arg2, global->RP.Data);
  162.    }
  163.  
  164.    global->RP.Type = pkt->dp_Type;
  165.    global->RP.Arg1 = (LONG)nlock->RPtr;
  166.    global->RP.Arg3 = pkt->dp_Arg3;
  167.    global->RP.DLen = BSTRLEN(global->RP.Data)+1;
  168.    if(global->RP.DLen == 1) global->RP.DLen = 0;
  169.  
  170.    if(!RemotePacket(global, nlock) && pkt->dp_Res1)
  171.    {
  172.       BUG(("ActLock: Returned RPTR is %lx\n", pkt->dp_Res1));
  173.       pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock, 
  174.                                         (RPTR)pkt->dp_Res1, pkt->dp_Arg3));
  175.    }
  176. }
  177.  
  178. void ActDupLock(global,pkt)
  179. GLOBAL global;
  180. struct DosPacket      *pkt;      /* a pointer to the dos packet sent       */
  181. {
  182.    NETPTR nlock;
  183.    struct FileLock *flock;
  184.  
  185.    BUG(("Action DupLock\n"));
  186.  
  187.    /* If this is a lock on the local root, it is a special case */
  188.    if((!(flock=(struct FileLock *)pkt->dp_Arg1) || 
  189.        !(nlock=(NETPTR)flock->fl_Key)->RDevice))
  190.    {
  191.       pkt->dp_Res1 = NULL;
  192.       if(!flock) return;    /* Dup of null lock is null lock            */
  193.       goto GETLOCK;         /* Dup of real lock on root is real lock (?)*/
  194.    }
  195.  
  196.    global->RP.Type = pkt->dp_Type;
  197.    global->RP.Arg1 = (LONG)nlock->RPtr;
  198.    global->RP.DLen = 0;
  199.  
  200.    if(!RemotePacket(global, nlock) && pkt->dp_Res1)
  201.    {
  202. GETLOCK:
  203.       pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
  204.                                  (RPTR)pkt->dp_Res1, flock->fl_Access));
  205.    }
  206. }
  207.  
  208. void ActUnLock(global, pkt)
  209. GLOBAL global;
  210. struct DosPacket      *pkt;      /* a pointer to the dos packet sent       */
  211. {
  212.    NETPTR nlock;
  213.    struct FileLock *flock;
  214.  
  215.    BUG(("Action UnLock\n"));
  216.  
  217.    if(!(flock = (struct FileLock *)pkt->dp_Arg1))
  218.    {
  219.       /* No lock - do nothing */
  220.       pkt->dp_Res1 = DOS_TRUE;
  221.       return;
  222.    }
  223.  
  224.    /* If this lock exists on a remote node, delete it */
  225.    if((nlock=(NETPTR)flock->fl_Key)->RDevice)
  226.    {
  227.       global->RP.Type = pkt->dp_Type;
  228.       global->RP.Arg1 = (LONG)nlock->RPtr;
  229.       global->RP.DLen = 0;
  230.       RemotePacket(global, nlock);
  231.    }
  232.    else
  233.       pkt->dp_Res1 = DOS_TRUE;
  234.  
  235.    FreeLock(global, flock);
  236. }
  237.  
  238. int ParseName(global, name, nlock, outname)
  239. GLOBAL global;
  240. char *name;
  241. NETPTR *nlock;
  242. char *outname;
  243. {
  244.    int len, cur;
  245.    struct NetNode *node;
  246.  
  247. BUGBSTR("ParseName: Parsing name ", name);
  248.  
  249.    for(len=*(name++), cur=0; len && *name != '/'; len--, name++)
  250.    {
  251.       if(*name==':')
  252.          cur=0;
  253.       else
  254.          outname[cur++] = *name;
  255.    }
  256.    outname[cur] = '\0';
  257.    if(len>0 && *name == '/') name++, len--;
  258.  
  259.    if(len <= 1 && cur == 0)
  260.    {
  261.       /* It is the root of NET: */
  262.       *nlock = &global->netchain.RootLock;
  263.       return(1);
  264.    }
  265.  
  266.    /* We have a network node name - find it */
  267.    node = FindNode(global, outname);
  268.  
  269.    /* OK, check to see if it is a .info file for a node */
  270.    if(!node && cur >= 6 && !stricmp(outname+cur-5, ".info"))
  271.    {
  272.       outname[cur-5] = '\0';
  273.       if(node = FindNode(global, outname))
  274.       {
  275.          BUG(("Got a .info file for node '%s'\n", outname));
  276.          name = "Node.rinfo";
  277.          len = 10;
  278.       }
  279.    }
  280.  
  281.    /* No node found - return null nlock */
  282.    if(!node)
  283.    {
  284.       BUG(("ParseName: No node found, nlock is NULL\n"));
  285.       *nlock = NULL; 
  286.    }
  287.    else
  288.    {
  289.       /* Node found - return template lock */
  290.       *nlock = &node->RootLock;
  291.       BUGBSTR("ParseName: Sending packet to node ", node->name);
  292.    }
  293.  
  294.    /* Move the rest of the name into outname as a BSTR */
  295.    outname[0] = (char)len+1;
  296.    outname[1] = ':';
  297.    if(len) MQ(name, outname+2, len);
  298.    outname[len+2] = '\0';
  299.    BUG(("Remote filename: len %d text '%s'\n", (int)*outname, outname+1));
  300.    return(0);
  301. }
  302.  
  303. struct NetNode *FindNode(global, name)
  304. GLOBAL global;
  305. char *name;
  306. {
  307.    struct NetNode *node;
  308.  
  309.    for(node=global->netchain.next; node; node=node->next)
  310.       if(!stricmp(name, node->name+1)) break;
  311.  
  312.    return(node);
  313. }
  314.  
  315.