1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

moved some more locking routines to locking.c, and moved replacement

routines for broken OSes from util.c to replace.c.
(This used to be commit 3ee9d45426)
This commit is contained in:
Andrew Tridgell 1996-06-10 03:39:58 +00:00
parent e2eac352b1
commit de411c701e
4 changed files with 470 additions and 444 deletions

View File

@ -88,6 +88,9 @@ void lp_dump(void);
int lp_servicenumber(char *pszServiceName);
char *my_workgroup(void);
char *volume_label(int snum);
BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type);
int file_lock(char *name,int timeout);
void file_unlock(int fd);
BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset);
BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
@ -115,19 +118,19 @@ void do_announce_request(char *info, char *to_name, int announce_type,
void announce_backup(void);
void announce_host(void);
void announce_master(void);
struct work_record *remove_workgroup(struct domain_record *d,
struct work_record *remove_workgroup(struct subnet_record *d,
struct work_record *work);
void expire_browse_cache(time_t t);
struct work_record *find_workgroupstruct(struct domain_record *d,
struct work_record *find_workgroupstruct(struct subnet_record *d,
fstring name, BOOL add);
struct domain_record *find_domain(struct in_addr source_ip);
struct subnet_record *find_domain(struct in_addr ip);
void dump_workgroups(void);
struct domain_record *add_domain_entry(struct in_addr source_ip,
struct subnet_record *add_subnet_entry(struct in_addr source_ip,
struct in_addr source_mask,
char *name, BOOL add);
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
time_t ttl, struct in_addr ip);
struct server_record *add_server_entry(struct domain_record *d,
struct server_record *add_server_entry(struct subnet_record *d,
struct work_record *work,
char *name,int servertype,
int ttl,char *comment,
@ -136,9 +139,9 @@ void write_browse_list(void);
void expire_servers(time_t t);
void check_master_browser(void);
void browser_gone(char *work_name, struct in_addr ip);
void send_election(struct domain_record *d, char *group,uint32 criterion,
void send_election(struct subnet_record *d, char *group,uint32 criterion,
int timeup,char *name);
void become_nonmaster(struct domain_record *d, struct work_record *work);
void become_nonmaster(struct subnet_record *d, struct work_record *work);
void run_elections(void);
void process_election(struct packet_struct *p,char *buf);
BOOL check_elections(void);
@ -254,6 +257,13 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
char *Strstr(char *s, char *p);
time_t Mktime(struct tm *t);
int InNetGr(char *group,char *host,char *user,char *dom);
void *malloc_wrapped(int size,char *file,int line);
void *realloc_wrapped(void *ptr,int size,char *file,int line);
void free_wrapped(void *ptr,char *file,int line);
void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line);
int reply_special(char *inbuf,char *outbuf);
int reply_tcon(char *inbuf,char *outbuf);
int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize);
@ -402,9 +412,6 @@ struct passwd *Get_Pwnam(char *user,BOOL allow_change);
BOOL user_in_list(char *user,char *list);
void setup_logging(char *pname,BOOL interactive);
void reopen_logs(void);
BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type);
int file_lock(char *name,int timeout);
void file_unlock(int fd);
BOOL is_a_socket(int fd);
BOOL next_token(char **ptr,char *buff,char *sep);
char **toktocliplist(int *ctok, char *sep);
@ -509,13 +516,6 @@ char *gidtoname(int gid);
void BlockSignals(BOOL block);
void ajt_panic(void);
char *readdirname(void *p);
void *malloc_wrapped(int size,char *file,int line);
void *realloc_wrapped(void *ptr,int size,char *file,int line);
void free_wrapped(void *ptr,char *file,int line);
char *Strstr(char *s, char *p);
time_t Mktime(struct tm *t);
int InNetGr(char *group,char *host,char *user,char *dom);
void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line);
int VT_Check(char *buffer);
int VT_Start_utmp(void);
int VT_Stop_utmp(void);

322
source3/lib/replace.c Normal file
View File

@ -0,0 +1,322 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
replacement routines for broken systems
Copyright (C) Andrew Tridgell 1992-1995
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
void replace_dummy(void)
{}
#ifdef REPLACE_STRLEN
/****************************************************************************
a replacement strlen() that returns int for solaris
****************************************************************************/
int Strlen(char *s)
{
int ret=0;
if (!s) return(0);
while (*s++) ret++;
return(ret);
}
#endif
#ifdef NO_FTRUNCATE
/*******************************************************************
ftruncate for operating systems that don't have it
********************************************************************/
int ftruncate(int f,long l)
{
struct flock fl;
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = l;
fl.l_type = F_WRLCK;
return fcntl(f, F_FREESP, &fl);
}
#endif
#ifdef REPLACE_STRSTR
/****************************************************************************
Mips version of strstr doesn't seem to work correctly.
There is a #define in includes.h to redirect calls to this function.
****************************************************************************/
char *Strstr(char *s, char *p)
{
int len = strlen(p);
while ( *s != '\0' ) {
if ( strncmp(s, p, len) == 0 )
return s;
s++;
}
return NULL;
}
#endif /* REPLACE_STRSTR */
#ifdef REPLACE_MKTIME
/*******************************************************************
a mktime() replacement for those who don't have it - contributed by
C.A. Lademann <cal@zls.com>
********************************************************************/
#define MINUTE 60
#define HOUR 60*MINUTE
#define DAY 24*HOUR
#define YEAR 365*DAY
time_t Mktime(struct tm *t)
{
struct tm *u;
time_t epoch = 0;
int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
y, m, i;
if(t->tm_year < 70)
return((time_t)-1);
epoch = (t->tm_year - 70) * YEAR +
(t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
y = t->tm_year;
m = 0;
for(i = 0; i < t->tm_mon; i++) {
epoch += mon [m] * DAY;
if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
epoch += DAY;
if(++m > 11) {
m = 0;
y++;
}
}
epoch += (t->tm_mday - 1) * DAY;
epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
if((u = localtime(&epoch)) != NULL) {
t->tm_sec = u->tm_sec;
t->tm_min = u->tm_min;
t->tm_hour = u->tm_hour;
t->tm_mday = u->tm_mday;
t->tm_mon = u->tm_mon;
t->tm_year = u->tm_year;
t->tm_wday = u->tm_wday;
t->tm_yday = u->tm_yday;
t->tm_isdst = u->tm_isdst;
#ifndef NO_TM_NAME
memcpy(t->tm_name, u->tm_name, LTZNMAX);
#endif
}
return(epoch);
}
#endif /* REPLACE_MKTIME */
#ifdef REPLACE_RENAME
/* Rename a file. (from libiberty in GNU binutils) */
int rename (zfrom, zto)
const char *zfrom;
const char *zto;
{
if (link (zfrom, zto) < 0)
{
if (errno != EEXIST)
return -1;
if (unlink (zto) < 0
|| link (zfrom, zto) < 0)
return -1;
}
return unlink (zfrom);
}
#endif
#ifdef REPLACE_INNETGR
/*
* Search for a match in a netgroup. This replaces it on broken systems.
*/
int InNetGr(char *group,char *host,char *user,char *dom)
{
char *hst, *usr, *dm;
setnetgrent(group);
while (getnetgrent(&hst, &usr, &dm))
if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
endnetgrent();
return (1);
}
endnetgrent();
return (0);
}
#endif
#ifdef NO_INITGROUPS
#include <sys/types.h>
#include <limits.h>
#include <grp.h>
#ifndef NULL
#define NULL (void *)0
#endif
/****************************************************************************
some systems don't have an initgroups call
****************************************************************************/
int initgroups(char *name,gid_t id)
{
#ifdef NO_SETGROUPS
/* yikes! no SETGROUPS or INITGROUPS? how can this work? */
return(0);
#else
gid_t grouplst[NGROUPS_MAX];
int i,j;
struct group *g;
char *gr;
grouplst[0] = id;
i = 1;
while (i < NGROUPS_MAX &&
((g = (struct group *)getgrent()) != (struct group *)NULL))
{
if (g->gr_gid == id)
continue;
j = 0;
gr = g->gr_mem[0];
while (gr && (*gr != (char)NULL)) {
if (strcmp(name,gr) == 0) {
grouplst[i] = g->gr_gid;
i++;
gr = (char *)NULL;
break;
}
gr = g->gr_mem[++j];
}
}
endgrent();
return(setgroups(i,grouplst));
#endif
}
#endif
#if (defined(SecureWare) && defined(SCO))
/* This is needed due to needing the nap() function but we don't want
to include the Xenix libraries since that will break other things...
BTW: system call # 0x0c28 is the same as calling nap() */
long nap(long milliseconds) {
return syscall(0x0c28, milliseconds);
}
#endif
#if WRAP_MALLOC
/* undo the wrapping temporarily */
#undef malloc
#undef realloc
#undef free
/****************************************************************************
wrapper for malloc() to catch memory errors
****************************************************************************/
void *malloc_wrapped(int size,char *file,int line)
{
#ifdef xx_old_malloc
void *res = xx_old_malloc(size);
#else
void *res = malloc(size);
#endif
DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
file,line,
size,(unsigned int)res));
return(res);
}
/****************************************************************************
wrapper for realloc() to catch memory errors
****************************************************************************/
void *realloc_wrapped(void *ptr,int size,char *file,int line)
{
#ifdef xx_old_realloc
void *res = xx_old_realloc(ptr,size);
#else
void *res = realloc(ptr,size);
#endif
DEBUG(3,("Realloc\n"));
DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
file,line,
(unsigned int)ptr));
DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
file,line,
size,(unsigned int)res));
return(res);
}
/****************************************************************************
wrapper for free() to catch memory errors
****************************************************************************/
void free_wrapped(void *ptr,char *file,int line)
{
#ifdef xx_old_free
xx_old_free(ptr);
#else
free(ptr);
#endif
DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
file,line,(unsigned int)ptr));
return;
}
/* and re-do the define for spots lower in this file */
#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
#endif
#if WRAP_MEMCPY
#undef memcpy
/*******************************************************************
a wrapper around memcpy for diagnostic purposes
********************************************************************/
void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
{
if (l>64 && (((int)d)%4) != (((int)s)%4))
DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
#ifdef xx_old_memcpy
return(xx_old_memcpy(d,s,l));
#else
return(memcpy(d,s,l));
#endif
}
#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
#endif

View File

@ -266,136 +266,6 @@ va_dcl
return(0);
}
/****************************************************************************
routine to do file locking
****************************************************************************/
BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
{
#if HAVE_FCNTL_LOCK
struct flock lock;
int ret;
#if 1
uint32 mask = 0xC0000000;
/* make sure the count is reasonable, we might kill the lockd otherwise */
count &= ~mask;
/* the offset is often strange - remove 2 of its bits if either of
the top two bits are set. Shift the top ones by two bits. This
still allows OLE2 apps to operate, but should stop lockd from
dieing */
if ((offset & mask) != 0)
offset = (offset & ~mask) | ((offset & mask) >> 2);
#else
unsigned long mask = ((unsigned)1<<31);
/* interpret negative counts as large numbers */
if (count < 0)
count &= ~mask;
/* no negative offsets */
offset &= ~mask;
/* count + offset must be in range */
while ((offset < 0 || (offset + count < 0)) && mask)
{
offset &= ~mask;
mask = mask >> 1;
}
#endif
DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
lock.l_type = type;
lock.l_whence = SEEK_SET;
lock.l_start = (int)offset;
lock.l_len = (int)count;
lock.l_pid = 0;
errno = 0;
ret = fcntl(fd,op,&lock);
if (errno != 0)
DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
/* a lock query */
if (op == F_GETLK)
{
if ((ret != -1) &&
(lock.l_type != F_UNLCK) &&
(lock.l_pid != 0) &&
(lock.l_pid != getpid()))
{
DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
return(True);
}
/* it must be not locked or locked by me */
return(False);
}
/* a lock set or unset */
if (ret == -1)
{
DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
offset,count,op,type,strerror(errno)));
/* perhaps it doesn't support this sort of locking?? */
if (errno == EINVAL)
{
DEBUG(3,("locking not supported? returning True\n"));
return(True);
}
return(False);
}
/* everything went OK */
DEBUG(5,("Lock call successful\n"));
return(True);
#else
return(False);
#endif
}
/*******************************************************************
lock a file - returning a open file descriptor or -1 on failure
The timeout is in seconds. 0 means no timeout
********************************************************************/
int file_lock(char *name,int timeout)
{
int fd = open(name,O_RDWR|O_CREAT,0666);
time_t t=0;
if (fd < 0) return(-1);
#if HAVE_FCNTL_LOCK
if (timeout) t = time(NULL);
while (!timeout || (time(NULL)-t < timeout)) {
if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);
msleep(LOCK_RETRY_TIMEOUT);
}
return(-1);
#else
return(fd);
#endif
}
/*******************************************************************
unlock a file locked by file_lock
********************************************************************/
void file_unlock(int fd)
{
if (fd<0) return;
#if HAVE_FCNTL_LOCK
fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
#endif
close(fd);
}
/****************************************************************************
determine if a file descriptor is in fact a socket
****************************************************************************/
@ -2915,39 +2785,6 @@ void Abort(void )
exit(2);
}
#ifdef REPLACE_STRLEN
/****************************************************************************
a replacement strlen() that returns int for solaris
****************************************************************************/
int Strlen(char *s)
{
int ret=0;
if (!s) return(0);
while (*s++) ret++;
return(ret);
}
#endif
#ifdef NO_FTRUNCATE
/*******************************************************************
ftruncate for operating systems that don't have it
********************************************************************/
int ftruncate(int f,long l)
{
struct flock fl;
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = l;
fl.l_type = F_WRLCK;
return fcntl(f, F_FREESP, &fl);
}
#endif
/****************************************************************************
get my own name and IP
****************************************************************************/
@ -3451,267 +3288,3 @@ char *readdirname(void *p)
#if (defined(SecureWare) && defined(SCO))
/* This is needed due to needing the nap() function but we don't want
to include the Xenix libraries since that will break other things...
BTW: system call # 0x0c28 is the same as calling nap() */
long nap(long milliseconds) {
return syscall(0x0c28, milliseconds);
}
#endif
#ifdef NO_INITGROUPS
#include <sys/types.h>
#include <limits.h>
#include <grp.h>
#ifndef NULL
#define NULL (void *)0
#endif
/****************************************************************************
some systems don't have an initgroups call
****************************************************************************/
int initgroups(char *name,gid_t id)
{
#ifdef NO_SETGROUPS
/* yikes! no SETGROUPS or INITGROUPS? how can this work? */
return(0);
#else
gid_t grouplst[NGROUPS_MAX];
int i,j;
struct group *g;
char *gr;
grouplst[0] = id;
i = 1;
while (i < NGROUPS_MAX &&
((g = (struct group *)getgrent()) != (struct group *)NULL))
{
if (g->gr_gid == id)
continue;
j = 0;
gr = g->gr_mem[0];
while (gr && (*gr != (char)NULL)) {
if (strcmp(name,gr) == 0) {
grouplst[i] = g->gr_gid;
i++;
gr = (char *)NULL;
break;
}
gr = g->gr_mem[++j];
}
}
endgrent();
return(setgroups(i,grouplst));
#endif
}
#endif
#if WRAP_MALLOC
/* undo the wrapping temporarily */
#undef malloc
#undef realloc
#undef free
/****************************************************************************
wrapper for malloc() to catch memory errors
****************************************************************************/
void *malloc_wrapped(int size,char *file,int line)
{
#ifdef xx_old_malloc
void *res = xx_old_malloc(size);
#else
void *res = malloc(size);
#endif
DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
file,line,
size,(unsigned int)res));
return(res);
}
/****************************************************************************
wrapper for realloc() to catch memory errors
****************************************************************************/
void *realloc_wrapped(void *ptr,int size,char *file,int line)
{
#ifdef xx_old_realloc
void *res = xx_old_realloc(ptr,size);
#else
void *res = realloc(ptr,size);
#endif
DEBUG(3,("Realloc\n"));
DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
file,line,
(unsigned int)ptr));
DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
file,line,
size,(unsigned int)res));
return(res);
}
/****************************************************************************
wrapper for free() to catch memory errors
****************************************************************************/
void free_wrapped(void *ptr,char *file,int line)
{
#ifdef xx_old_free
xx_old_free(ptr);
#else
free(ptr);
#endif
DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
file,line,(unsigned int)ptr));
return;
}
/* and re-do the define for spots lower in this file */
#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
#endif
#ifdef REPLACE_STRSTR
/****************************************************************************
Mips version of strstr doesn't seem to work correctly.
There is a #define in includes.h to redirect calls to this function.
****************************************************************************/
char *Strstr(char *s, char *p)
{
int len = strlen(p);
while ( *s != '\0' ) {
if ( strncmp(s, p, len) == 0 )
return s;
s++;
}
return NULL;
}
#endif /* REPLACE_STRSTR */
#ifdef REPLACE_MKTIME
/*******************************************************************
a mktime() replacement for those who don't have it - contributed by
C.A. Lademann <cal@zls.com>
********************************************************************/
#define MINUTE 60
#define HOUR 60*MINUTE
#define DAY 24*HOUR
#define YEAR 365*DAY
time_t Mktime(struct tm *t)
{
struct tm *u;
time_t epoch = 0;
int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
y, m, i;
if(t->tm_year < 70)
return((time_t)-1);
epoch = (t->tm_year - 70) * YEAR +
(t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
y = t->tm_year;
m = 0;
for(i = 0; i < t->tm_mon; i++) {
epoch += mon [m] * DAY;
if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
epoch += DAY;
if(++m > 11) {
m = 0;
y++;
}
}
epoch += (t->tm_mday - 1) * DAY;
epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
if((u = localtime(&epoch)) != NULL) {
t->tm_sec = u->tm_sec;
t->tm_min = u->tm_min;
t->tm_hour = u->tm_hour;
t->tm_mday = u->tm_mday;
t->tm_mon = u->tm_mon;
t->tm_year = u->tm_year;
t->tm_wday = u->tm_wday;
t->tm_yday = u->tm_yday;
t->tm_isdst = u->tm_isdst;
#ifndef NO_TM_NAME
memcpy(t->tm_name, u->tm_name, LTZNMAX);
#endif
}
return(epoch);
}
#endif /* REPLACE_MKTIME */
#ifdef REPLACE_RENAME
/* Rename a file. (from libiberty in GNU binutils) */
int rename (zfrom, zto)
const char *zfrom;
const char *zto;
{
if (link (zfrom, zto) < 0)
{
if (errno != EEXIST)
return -1;
if (unlink (zto) < 0
|| link (zfrom, zto) < 0)
return -1;
}
return unlink (zfrom);
}
#endif
#ifdef REPLACE_INNETGR
/*
* Search for a match in a netgroup. This replaces it on broken systems.
*/
int InNetGr(char *group,char *host,char *user,char *dom)
{
char *hst, *usr, *dm;
setnetgrent(group);
while (getnetgrent(&hst, &usr, &dm))
if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
endnetgrent();
return (1);
}
endnetgrent();
return (0);
}
#endif
#if WRAP_MEMCPY
#undef memcpy
/*******************************************************************
a wrapper around memcpy for diagnostic purposes
********************************************************************/
void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
{
if (l>64 && (((int)d)%4) != (((int)s)%4))
DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
#ifdef xx_old_memcpy
return(xx_old_memcpy(d,s,l));
#else
return(memcpy(d,s,l));
#endif
}
#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
#endif

View File

@ -28,6 +28,137 @@ extern files_struct Files[];
pstring share_del_pending="";
/****************************************************************************
routine to do file locking
****************************************************************************/
BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
{
#if HAVE_FCNTL_LOCK
struct flock lock;
int ret;
#if 1
uint32 mask = 0xC0000000;
/* make sure the count is reasonable, we might kill the lockd otherwise */
count &= ~mask;
/* the offset is often strange - remove 2 of its bits if either of
the top two bits are set. Shift the top ones by two bits. This
still allows OLE2 apps to operate, but should stop lockd from
dieing */
if ((offset & mask) != 0)
offset = (offset & ~mask) | ((offset & mask) >> 2);
#else
unsigned long mask = ((unsigned)1<<31);
/* interpret negative counts as large numbers */
if (count < 0)
count &= ~mask;
/* no negative offsets */
offset &= ~mask;
/* count + offset must be in range */
while ((offset < 0 || (offset + count < 0)) && mask)
{
offset &= ~mask;
mask = mask >> 1;
}
#endif
DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
lock.l_type = type;
lock.l_whence = SEEK_SET;
lock.l_start = (int)offset;
lock.l_len = (int)count;
lock.l_pid = 0;
errno = 0;
ret = fcntl(fd,op,&lock);
if (errno != 0)
DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
/* a lock query */
if (op == F_GETLK)
{
if ((ret != -1) &&
(lock.l_type != F_UNLCK) &&
(lock.l_pid != 0) &&
(lock.l_pid != getpid()))
{
DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
return(True);
}
/* it must be not locked or locked by me */
return(False);
}
/* a lock set or unset */
if (ret == -1)
{
DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
offset,count,op,type,strerror(errno)));
/* perhaps it doesn't support this sort of locking?? */
if (errno == EINVAL)
{
DEBUG(3,("locking not supported? returning True\n"));
return(True);
}
return(False);
}
/* everything went OK */
DEBUG(5,("Lock call successful\n"));
return(True);
#else
return(False);
#endif
}
/*******************************************************************
lock a file - returning a open file descriptor or -1 on failure
The timeout is in seconds. 0 means no timeout
********************************************************************/
int file_lock(char *name,int timeout)
{
int fd = open(name,O_RDWR|O_CREAT,0666);
time_t t=0;
if (fd < 0) return(-1);
#if HAVE_FCNTL_LOCK
if (timeout) t = time(NULL);
while (!timeout || (time(NULL)-t < timeout)) {
if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);
msleep(LOCK_RETRY_TIMEOUT);
}
return(-1);
#else
return(fd);
#endif
}
/*******************************************************************
unlock a file locked by file_lock
********************************************************************/
void file_unlock(int fd)
{
if (fd<0) return;
#if HAVE_FCNTL_LOCK
fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
#endif
close(fd);
}
/****************************************************************************
utility function called to see if a file region is locked
****************************************************************************/