/***************************************************************************
* *
* Squish Developers Kit Source, Version 2.00 *
* Copyright 1989-1994 by SCI Communications. All rights reserved. *
* *
* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE *
* SQUISH DEVELOPERS KIT LICENSING AGREEMENT IN SQDEV.PRN. IF YOU DO NOT *
* FIND THE TEXT OF THIS AGREEMENT IN THE AFOREMENTIONED FILE, OR IF YOU *
* DO NOT HAVE THIS FILE, YOU SHOULD IMMEDIATELY CONTACT THE AUTHOR AT *
* ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT SHOULD YOU PROCEED TO *
* USE THIS FILE WITHOUT HAVING ACCEPTED THE TERMS OF THE SQUISH *
* DEVELOPERS KIT LICENSING AGREEMENT, OR SUCH OTHER AGREEMENT AS YOU ARE *
* ABLE TO REACH WITH THE AUTHOR. *
* *
* You can contact the author at one of the address listed below: *
* *
* Scott Dudley FidoNet 1:249/106 *
* 777 Downing St. Internet sjd@f106.n249.z1.fidonet.org *
* Kingston, Ont. CompuServe >INTERNET:sjd@f106.n249.z1.fidonet.org *
* Canada K7M 5N3 BBS 1-613-634-3058, V.32bis *
* *
***************************************************************************/
/*
#pragma off(unreferenced)
static char rcs_id[]="$Id: sq_lock.c,v 1.23 2003/01/15 05:40:38 stas_degteff Exp $";
#pragma on(unreferenced)
*/
#define MSGAPI_HANDLERS
#define MSGAPI_NO_OLD_TYPES
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "compiler.h"
#ifdef HAS_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAS_IO_H
# include <io.h>
#endif
#ifdef HAS_SHARE_H
#include <share.h>
#endif
#ifdef HAS_MALLOC_H
#include <malloc.h>
#endif
#include "prog.h"
#include "old_msg.h"
#include "msgapi.h"
#include "api_sq.h"
#include "api_sqp.h"
#include "apidebug.h"
#include "unused.h"
/* Base is locked for other processes */
#ifdef ALTLOCKING
int _alt_lock(HAREA ha)
{
if (ha->lck_handle > 0) return 0;
ha->lck_handle = open(ha->lck_path, O_RDWR|O_CREAT|O_EXCL, S_IREAD|S_IWRITE);
if (ha->lck_handle > 0)
return 0;
return -1;
}
int _squnlock(HAREA ha)
{
if (ha->lck_handle > 0) close(ha->lck_handle);
ha->lck_handle = 0;
remove(ha->lck_path);
return 1;
}
int _sqlock(HAREA ha, int t)
{
int forever = 0;
int rc;
if (t == -1)
return _alt_lock(ha) == 0;
if (t == 0)
forever = 1;
t *= 10;
while( (rc=_alt_lock(ha)) && (t>0 || forever))
{
tdelay(100);
t--;
}
return rc == 0;
}
#else
int _sqlock(HAREA ha, int t)
{
if (t==-1)
/* lock return 0 on success */
return lock(Sqd->sfd, 0, 1) == 0;
return waitlock2(Sqd->sfd, 0, 1, t) == 0;
}
int _squnlock(HAREA ha)
{
/* unlock returns 0 on success */
return unlock(Sqd->sfd, 0, 1) == 0;
}
#endif
/* Lock the first byte of the Squish file header. Do this up to *
* SQUISH_LOCK_RETRY number of times, in case someone else is using *
* the message base. */
static unsigned near _SquishLockBase(HAREA ha)
{
unsigned rc;
/* Only need to lock the area the first time */
if (Sqd->fLocked++ != 0)
return TRUE;
/* The first step is to obtain a lock on the Squish file header. Another *
* process may be attempting to do the same thing, so we retry a couple *
* of times just in case. */
rc = _sqlock(ha, SQUISH_LOCK_RETRY);
if (!rc)
{
msgapierr = MERR_SHARE;
Sqd->fLocked--;
}
return rc;
}
/* Unlock the first byte of the Squish file */
static unsigned near _SquishUnlockBase(HAREA ha)
{
/* If we have it locked more than once, only unlock on the last call */
if (--Sqd->fLocked)
return TRUE;
/* Unlock the first byte of the file */
if (mi.haveshare)
(void)_squnlock(ha);
return TRUE;
}
/* Obtain exclusive access to this message area. We need to do this to *
* synchronize access to critical fields in the Squish file header. */
unsigned _SquishExclusiveBegin(HAREA ha)
{
SQBASE sqb;
/* We can't open the header for exclusive access more than once */
if (Sqd->fHaveExclusive)
{
msgapierr=MERR_SHARE;
return FALSE;
}
/* Lock the header */
if (!_SquishLockBase(ha))
return FALSE;
/* Obtain an up-to-date copy of the file header */
if (!_SquishReadBaseHeader(ha, &sqb) ||
!_SquishCopyBaseToData(ha, &sqb))
{
(void)_SquishUnlockBase(ha);
return FALSE;
}
Sqd->fHaveExclusive=TRUE;
return TRUE;
}
/* Finish exclusive access to the area header. Sync the base header *
* with what we have in memory, then unlock the file. */
unsigned _SquishExclusiveEnd(HAREA ha)
{
SQBASE sqb;
unsigned rc;
if (!Sqd->fHaveExclusive)
{
msgapierr=MERR_NOLOCK;
return FALSE;
}
/* Copy the in-memory struct to sqb, then write to disk */
rc=_SquishCopyDataToBase(ha, &sqb);
rc = rc && _SquishWriteBaseHeader(ha, &sqb);
/* Relinquish access to the base */
if (!_SquishUnlockBase(ha))
rc=FALSE;
Sqd->fHaveExclusive=FALSE;
return rc;
}
/* Lock this message area for exclusive access */
sword _XPENTRY apiSquishLock(HAREA ha)
{
/* Only need to lock once */
if (Sqd->fLockFunc++ != 0)
{
return 0;
}
/* Lock the header */
if (!_SquishLockBase(ha))
{
return -1;
}
/* Read the index into memory */
if (!_SquishBeginBuffer(Sqd->hix))
{
(void)_SquishUnlockBase(ha);
return -1;
}
return 0;
}
/* Unlock an area that was opened for exclusive access */
sword _XPENTRY apiSquishUnlock(HAREA ha)
{
if (Sqd->fLockFunc==0)
{
msgapierr=MERR_NOLOCK;
return -1;
}
if (--Sqd->fLockFunc != 0)
{
return 0;
}
(void)_SquishEndBuffer(Sqd->hix);
(void)_SquishUnlockBase(ha);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1