/*************************************************************************** * * * 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 #include #include #include "compiler.h" #ifdef HAS_UNISTD_H #include #endif #ifdef HAS_IO_H # include #endif #ifdef HAS_SHARE_H #include #endif #ifdef HAS_MALLOC_H #include #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; }