/************************************************************************
* Whatever is needed for (un)locking files in various ways *
* *
* Copyright (c) 1990-1997, S.R. van den Berg, The Netherlands *
* #include "../README" *
************************************************************************/
#ifdef RCS
static /*const*/char rcsid[]=
"$Id: locking.c,v 1.7 1998/05/13 16:57:40 srb Exp $";
#endif
#include "config.h"
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
#include "cucipop.h"
#include "locking.h"
#ifndef USEfcntl_lock
#ifndef USElockf
#ifndef USEflock
#ifndef USEdot_lock
#error No locking mechanism enabled
#endif
#define fdlock(fd) 0
#define fdunlock() 0
#endif
#endif
#endif
#ifndef fdlock
static int fdlock(int fd);
static int fdunlock(void);
#endif
#ifndef tell
#define tell(fd) lseek(fd,0L,SEEK_CUR)
#endif
static char*lastlocked;
static const char lockext[]=".lock";
void unlockmbox(void)
{ fdunlock();
#ifdef USEdot_lock
blocksignals();
if(lastlocked)
unlink(lastlocked),free(lastlocked),lastlocked=0;
#endif
}
int lockmbox(int fd,const char*mbox)
{ char*ll;
if(fdlock(fd))
return 0;
#ifdef USEdot_lock
if(ll=malloc(strlen(mbox)+STRLEN(lockext)+1))
{ strcpy(ll,mbox);strcat(ll,lockext);
for(;;)
{ blocksignals();
switch(xcreat(ll,0644))
{ case 0:lastlocked=ll;setsignals();
return 1;
default:setsignals();
thatsall: free(ll);
return 0;
case -1:setsignals();sleep(LOCKSLEEP);
if(spoofcheck>=0)
{ int fdsockin=fileno(sockin),res;char c;
fcntl(fdsockin,F_SETFL,(long)O_NONBLOCK);
res=read(fdsockin,&c,1);fcntl(fdsockin,F_SETFL,0L);
switch(res)
{ case 0:
goto thatsall;
case 1:spoofcheck=-1;ungetc(c,sockin);
}
}
}
}
}
return 0;
#else
return 1;
#endif
}
/* if you've ever wondered what conditional compilation was good for */
#ifndef fdlock /* watch closely :-) */
#ifdef USEflock
#ifndef SYS_FILE_H_MISSING
#include <sys/file.h>
#endif
#define REITflock 1
#else
#define REITflock 0
#endif /* USEflock */
static int oldfdlock= -1; /* the fd we locked last */
#ifndef NOfcntl_lock
static struct flock flck; /* why can't it be a local variable? */
#define REITfcntl 1
#else
#define REITfcntl 0
#endif /* NOfcntl_lock */
#ifdef USElockf
static off_t oldlockoffset;
#define REITlockf 1
#else
#define REITlockf 0
#endif /* USElockf */
static int fdlock(int fd)
{ int ret;
#if REITfcntl+REITflock+REITlockf>1
for(;;syslog(LOG_DEBUG,"reiterating kernel-lock"),sleep(LOCKSLEEP))
#endif
{
#ifdef USElockf
oldlockoffset=0;
#endif
#ifndef NOfcntl_lock
flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_len=0;
#ifdef USElockf
flck.l_start=oldlockoffset;
#else
flck.l_start=tell(fd);
#endif
#endif
#ifndef NOfcntl_lock
ret=fcntl(fd,F_SETLKW,&flck);
#ifdef USElockf
if((ret|=lockf(fd,F_TLOCK,(off_t)0))&&(errno==EAGAIN||errno==EACCES||
errno==EWOULDBLOCK))
ufcntl:
{ flck.l_type=F_UNLCK;fcntl(fd,F_SETLK,&flck);
continue;
}
#ifdef USEflock
if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
errno==EWOULDBLOCK))
{ lockf(fd,F_ULOCK,(off_t)0);
goto ufcntl;
}
#endif /* USEflock */
#else /* USElockf */
#ifdef USEflock
if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
errno==EWOULDBLOCK))
{ flck.l_type=F_UNLCK;fcntl(fd,F_SETLK,&flck);
continue;
}
#endif /* USEflock */
#endif /* USElockf */
#else /* NOfcntl_lock */
#ifdef USElockf
ret=lockf(fd,F_LOCK,(off_t)0);
#ifdef USEflock
if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
errno==EWOULDBLOCK))
{ lockf(fd,F_ULOCK,(off_t)0);
continue;
}
#endif /* USEflock */
#else /* USElockf */
#ifdef USEflock
ret=flock(fd,LOCK_EX);
#endif /* USEflock */
#endif /* USElockf */
#endif /* NOfcntl_lock */
oldfdlock=fd;
return ret;
}
}
static int fdunlock(void)
{ int i;
if(oldfdlock<0)
return -1;
i=0;
#ifdef USEflock
i|=flock(oldfdlock,LOCK_UN);
#endif
#ifdef USElockf
;{ off_t curp=tell(oldfdlock);
lseek(oldfdlock,oldlockoffset,SEEK_SET);
i|=lockf(oldfdlock,F_ULOCK,(off_t)0);lseek(oldfdlock,curp,SEEK_SET);
}
#endif
#ifndef NOfcntl_lock
flck.l_type=F_UNLCK;i|=fcntl(oldfdlock,F_SETLK,&flck);
#endif
oldfdlock= -1;
return i;
}
#endif /* fdlock */
syntax highlighted by Code2HTML, v. 0.9.1