home *** CD-ROM | disk | FTP | other *** search
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery. All Rights */
- /* |. o.| || Reserved. This program may not be distributed without the */
- /* | . | || permission of the authors: BBS: */
- /* | o | || John Toebes Doug Walker Dave Baker */
- /* | . |// */
- /* ====== */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- /* 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"
-
- /* create a lock to be returned */
- struct FileLock *CreateLock(global, nlock, RLock, Access)
- GLOBAL global;
- NETPTR nlock;
- RPTR RLock;
- LONG Access;
- {
- struct FileLock *flock;
- NETPTR newnlock;
-
- if(!(flock=(struct FileLock *)
- DosAllocMem(global, sizeof(struct FileLock))) ||
- !(newnlock=(NETPTR) DosAllocMem(global, sizeof(struct NetPtr)))
- )
- return(NULL);
-
- flock->fl_Key = (LONG)newnlock;
- flock->fl_Access = Access;
- flock->fl_Task = global->n.port;
- flock->fl_Volume = MKBADDR(global->volume);
- newnlock->NetNode = nlock->NetNode;
- newnlock->RDevice = nlock->RDevice;
- newnlock->RPtr = RLock;
-
- /* Link the lock into the lock chain */
- Forbid();
- flock->fl_Link = global->volume->dl_Lock;
- global->volume->dl_Lock = MKBADDR(flock);
- Permit();
-
- return(flock);
- }
-
- void FreeLock(global, flock)
- GLOBAL global;
- struct FileLock *flock;
- {
- struct FileLock *current, *next;
-
- if(!flock) return;
-
- Forbid();
- if((current=(struct FileLock *)BADDR(global->volume->dl_Lock)) == flock)
- {
- global->volume->dl_Lock = flock->fl_Link;
- Permit();
- BUG(("FreeLock: Head lock freed, new head = %lx\n",
- global->volume->dl_Lock));
- }
- else
- {
- for(next=NULL;
- current &&
- (next=(struct FileLock *)BADDR(current->fl_Link)) != flock;
- current = next);
-
- if(!next)
- {
- Permit();
- BUG(("****************************************\n"));
- BUG(("******* Lock not found in chain ********\n"));
- BUG(("****************************************\n"));
- return;
- }
- else
- {
- current->fl_Link = next->fl_Link;
- Permit();
- BUG(("Lock found and removed from chain\n"));
- }
- }
-
- /* If RDevice == NULL, we have a dummy nlock, so don't free it */
- /* Otherwise, free it */
- if(((NETPTR)flock->fl_Key)->RDevice)
- DosFreeMem((char *)flock->fl_Key); /* Free the net lock */
-
- DosFreeMem((char *)flock); /* Free the local 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 */
- {
- NETPTR nlock;
- struct FileLock *flock;
-
- BUG(("Action Lock\n"));
- BUGBSTR("File to lock: ", pkt->dp_Arg2);
-
- /**********************************************************************/
- /* If the given lock is on the local root, call the ParseName routine */
- /* to determine if we need to call the remote nodes. If ParseName */
- /* returns 1, we have a name of the form "NET:" and we should return */
- /* a lock on the root of NET:. If it returns 0, we have a name of */
- /* the form "NET:FOO" or "NET:FOO/BAR", etc and we need to call the */
- /* remote node specified in the pseudo-lock returned. */
- /**********************************************************************/
-
- if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
- !(nlock=(NETPTR)flock->fl_Key)->RDevice))
- {
- /* ParseName returns 1 if we are locking the root. It fills in */
- /* nlock with a pointer to the pseudolock for the node. The */
- /* pseudolock is kept in the NetNode struct. */
- /* Any leftover parts of the name are left in RP.Data as a */
- /* BCPL string. */
- if(ParseName(global, (char *)pkt->dp_Arg2, &nlock, global->RP.Data))
- {
- BUG(("ActLock: Returning lock on root\n"));
- /* Return lock on root */
- /* ParseName has put the pseudolock for the root into nlock */
- pkt->dp_Res1 =
- MKBADDR(CreateLock(global, nlock, NULL, pkt->dp_Arg3));
- return;
- }
- else if(!nlock)
- {
- BUG(("ActLock: Couldn't find node\n"));
- pkt->dp_Res1 = NULL;
- pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
- return;
- }
- #if DEBUG
- else
- BUG(("ActLock: got nlock, falling through\n"));
- #endif
- }
- else
- {
- BUGBSTR("ActLock: Relative open, node ", nlock->NetNode->name);
- /* We are doing a relative open - put filename in Data */
- MBSTR(pkt->dp_Arg2, global->RP.Data);
- }
-
- global->RP.Type = pkt->dp_Type;
- global->RP.Arg1 = (LONG)nlock->RPtr;
- global->RP.Arg3 = pkt->dp_Arg3;
- global->RP.DLen = BSTRLEN(global->RP.Data)+1;
- if(global->RP.DLen == 1) global->RP.DLen = 0;
-
- if(!RemotePacket(global, nlock) && pkt->dp_Res1)
- {
- BUG(("ActLock: Returned RPTR is %lx\n", pkt->dp_Res1));
- pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
- (RPTR)pkt->dp_Res1, pkt->dp_Arg3));
- }
- }
-
- void ActDupLock(global,pkt)
- GLOBAL global;
- struct DosPacket *pkt; /* a pointer to the dos packet sent */
- {
- NETPTR nlock;
- struct FileLock *flock;
-
- BUG(("Action DupLock\n"));
-
- /* If this is a lock on the local root, it is a special case */
- if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
- !(nlock=(NETPTR)flock->fl_Key)->RDevice))
- {
- pkt->dp_Res1 = NULL;
- if(!flock) return; /* Dup of null lock is null lock */
- goto GETLOCK; /* Dup of real lock on root is real lock (?)*/
- }
-
- global->RP.Type = pkt->dp_Type;
- global->RP.Arg1 = (LONG)nlock->RPtr;
- global->RP.DLen = 0;
-
- if(!RemotePacket(global, nlock) && pkt->dp_Res1)
- {
- GETLOCK:
- pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
- (RPTR)pkt->dp_Res1, flock->fl_Access));
- }
- }
-
- void ActUnLock(global, pkt)
- GLOBAL global;
- struct DosPacket *pkt; /* a pointer to the dos packet sent */
- {
- NETPTR nlock;
- struct FileLock *flock;
-
- BUG(("Action UnLock\n"));
-
- if(!(flock = (struct FileLock *)pkt->dp_Arg1))
- {
- /* No lock - do nothing */
- pkt->dp_Res1 = DOS_TRUE;
- return;
- }
-
- /* If this lock exists on a remote node, delete it */
- if((nlock=(NETPTR)flock->fl_Key)->RDevice)
- {
- global->RP.Type = pkt->dp_Type;
- global->RP.Arg1 = (LONG)nlock->RPtr;
- global->RP.DLen = 0;
- RemotePacket(global, nlock);
- }
- else
- pkt->dp_Res1 = DOS_TRUE;
-
- FreeLock(global, flock);
- }
-
- int ParseName(global, name, nlock, outname)
- GLOBAL global;
- char *name;
- NETPTR *nlock;
- char *outname;
- {
- int len, cur;
- struct NetNode *node;
-
- BUGBSTR("ParseName: Parsing name ", name);
-
- for(len=*(name++), cur=0; len && *name != '/'; len--, name++)
- {
- if(*name==':')
- cur=0;
- else
- outname[cur++] = *name;
- }
- outname[cur] = '\0';
- if(len>0 && *name == '/') name++, len--;
-
- if(len <= 1 && cur == 0)
- {
- /* It is the root of NET: */
- *nlock = &global->netchain.RootLock;
- return(1);
- }
-
- /* We have a network node name - find it */
- node = FindNode(global, outname);
-
- /* OK, check to see if it is a .info file for a node */
- if(!node && cur >= 6 && !stricmp(outname+cur-5, ".info"))
- {
- outname[cur-5] = '\0';
- if(node = FindNode(global, outname))
- {
- BUG(("Got a .info file for node '%s'\n", outname));
- name = "Node.rinfo";
- len = 10;
- }
- }
-
- /* No node found - return null nlock */
- if(!node)
- {
- BUG(("ParseName: No node found, nlock is NULL\n"));
- *nlock = NULL;
- }
- else
- {
- /* Node found - return template lock */
- *nlock = &node->RootLock;
- BUGBSTR("ParseName: Sending packet to node ", node->name);
- }
-
- /* Move the rest of the name into outname as a BSTR */
- outname[0] = (char)len+1;
- outname[1] = ':';
- if(len) MQ(name, outname+2, len);
- outname[len+2] = '\0';
- BUG(("Remote filename: len %d text '%s'\n", (int)*outname, outname+1));
- return(0);
- }
-
- struct NetNode *FindNode(global, name)
- GLOBAL global;
- char *name;
- {
- struct NetNode *node;
-
- for(node=global->netchain.next; node; node=node->next)
- if(!stricmp(name, node->name+1)) break;
-
- return(node);
- }
-
-