1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

Moved uglyness needed in fcntl locking (64->32 bit mapping, NFS

errors etc.) into locking/posix.c, where it is needed. fcntl_lock in lib/util.c
is now very small and clean.
Added (*lock) op to vfs layer.
Jeremy.
(This used to be commit 46092ee141)
This commit is contained in:
Jeremy Allison 2000-05-02 03:20:47 +00:00
parent 693ffb8466
commit ba020b0612
6 changed files with 141 additions and 108 deletions

View File

@ -335,7 +335,6 @@ char *readdirname(DIR *p);
BOOL is_in_path(char *name, name_compare_entry *namelist);
void set_namearray(name_compare_entry **ppname_array, char *namelist);
void free_namearray(name_compare_entry *name_array);
uint32 map_lock_offset(uint32 high, uint32 low);
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
BOOL is_myname(char *s);
void set_remote_arch(enum remote_arch_types type);
@ -3374,6 +3373,7 @@ int vfswrap_unlink(char *path);
int vfswrap_chmod(char *path, mode_t mode);
int vfswrap_utime(char *path, struct utimbuf *times);
int vfswrap_ftruncate(int fd, SMB_OFF_T offset);
BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
/*The following definitions come from smbd/vfs.c */

View File

@ -137,6 +137,7 @@ struct vfs_ops {
int (*chmod)(char *path, mode_t mode);
int (*utime)(char *path, struct utimbuf *times);
int (*ftruncate)(int fd, SMB_OFF_T offset);
BOOL (*lock)(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
};
struct vfs_options {

View File

@ -1499,57 +1499,15 @@ void free_namearray(name_compare_entry *name_array)
}
/****************************************************************************
Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
****************************************************************************/
uint32 map_lock_offset(uint32 high, uint32 low)
{
unsigned int i;
uint32 mask = 0;
uint32 highcopy = high;
/*
* Try and find out how many significant bits there are in high.
*/
for(i = 0; highcopy; i++)
highcopy >>= 1;
/*
* We use 31 bits not 32 here as POSIX
* lock offsets may not be negative.
*/
mask = (~0) << (31 - i);
if(low & mask)
return 0; /* Fail. */
high <<= (31 - i);
return (high|low);
}
/****************************************************************************
routine to do file locking
Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
is dealt with in posix.c
****************************************************************************/
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
#if HAVE_FCNTL_LOCK
SMB_STRUCT_FLOCK lock;
int ret;
#if defined(LARGE_SMB_OFF_T)
/*
* In the 64 bit locking case we store the original
* values in case we have to map to a 32 bit lock on
* a filesystem that doesn't support 64 bit locks.
*/
SMB_OFF_T orig_offset = offset;
SMB_OFF_T orig_count = count;
#endif /* LARGE_SMB_OFF_T */
DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
lock.l_type = type;
@ -1561,22 +1519,9 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
errno = 0;
ret = fcntl(fd,op,&lock);
if (errno == EFBIG)
{
if( DEBUGLVL( 0 ))
{
dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
}
/* 32 bit NFS file system, retry with smaller offset */
errno = 0;
lock.l_len = count & 0x7fffffff;
ret = fcntl(fd,op,&lock);
}
if (errno != 0)
DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
/* a lock query */
if (op == SMB_F_GETLK)
@ -1586,7 +1531,7 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
(lock.l_pid != 0) &&
(lock.l_pid != sys_getpid()))
{
DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
return(True);
}
@ -1597,56 +1542,15 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
/* a lock set or unset */
if (ret == -1)
{
DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
(double)offset,(double)count,op,type,strerror(errno)));
/* perhaps it doesn't support this sort of locking?? */
if (errno == EINVAL)
{
#if defined(LARGE_SMB_OFF_T)
{
/*
* Ok - if we get here then we have a 64 bit lock request
* that has returned EINVAL. Try and map to 31 bits for offset
* and length and try again. This may happen if a filesystem
* doesn't support 64 bit offsets (efs/ufs) although the underlying
* OS does.
*/
uint32 off_low = (orig_offset & 0xFFFFFFFF);
uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
lock.l_len = (orig_count & 0x7FFFFFFF);
lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low);
ret = fcntl(fd,op,&lock);
if (ret == -1)
{
if (errno == EINVAL)
{
DEBUG(3,("locking not supported? returning True\n"));
return(True);
}
return False;
}
DEBUG(3,("64 -> 32 bit modified lock call successful\n"));
return True;
}
#else /* LARGE_SMB_OFF_T */
DEBUG(3,("locking not supported? returning True\n"));
return(True);
#endif /* LARGE_SMB_OFF_T */
}
return(False);
}
/* everything went OK */
DEBUG(8,("Lock call successful\n"));
DEBUG(8,("fcntl_lock: Lock call successful\n"));
return(True);
#else
return(False);
#endif
}
/*******************************************************************

View File

@ -611,6 +611,124 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
return True;
}
/****************************************************************************
Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
****************************************************************************/
static uint32 map_lock_offset(uint32 high, uint32 low)
{
unsigned int i;
uint32 mask = 0;
uint32 highcopy = high;
/*
* Try and find out how many significant bits there are in high.
*/
for(i = 0; highcopy; i++)
highcopy >>= 1;
/*
* We use 31 bits not 32 here as POSIX
* lock offsets may not be negative.
*/
mask = (~0) << (31 - i);
if(low & mask)
return 0; /* Fail. */
high <<= (31 - i);
return (high|low);
}
/****************************************************************************
Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
broken NFS implementations.
****************************************************************************/
static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
int ret;
struct connection_struct *conn = fsp->conn;
#if defined(LARGE_SMB_OFF_T)
/*
* In the 64 bit locking case we store the original
* values in case we have to map to a 32 bit lock on
* a filesystem that doesn't support 64 bit locks.
*/
SMB_OFF_T orig_offset = offset;
SMB_OFF_T orig_count = count;
#endif /* LARGE_SMB_OFF_T */
DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type));
ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type);
if (!ret && (errno == EFBIG)) {
if( DEBUGLVL( 0 )) {
dbgtext("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
}
/* 32 bit NFS file system, retry with smaller offset */
errno = 0;
count &= 0x7fffffff;
ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type);
}
/* A lock query - just return. */
if (op == SMB_F_GETLK)
return ret;
/* A lock set or unset. */
if (!ret) {
DEBUG(3,("posix_fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
(double)offset,(double)count,op,type,strerror(errno)));
/* Perhaps it doesn't support this sort of locking ? */
if (errno == EINVAL) {
#if defined(LARGE_SMB_OFF_T)
{
/*
* Ok - if we get here then we have a 64 bit lock request
* that has returned EINVAL. Try and map to 31 bits for offset
* and length and try again. This may happen if a filesystem
* doesn't support 64 bit offsets (efs/ufs) although the underlying
* OS does.
*/
uint32 off_low = (orig_offset & 0xFFFFFFFF);
uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
count = (orig_count & 0x7FFFFFFF);
offset = (SMB_OFF_T)map_lock_offset(off_high, off_low);
ret = conn->vfs_ops.lock(fsp->fd,op,offset,count,type);
if (!ret) {
if (errno == EINVAL) {
DEBUG(3,("posix_fcntl_lock: locking not supported? returning True\n"));
return(True);
}
return False;
}
DEBUG(3,("posix_fcntl_lock: 64 -> 32 bit modified lock call successful\n"));
return True;
}
#else /* LARGE_SMB_OFF_T */
DEBUG(3,("locking not supported? returning True\n"));
return(True);
#endif /* LARGE_SMB_OFF_T */
}
return(False);
}
DEBUG(8,("posix_fcntl_lock: Lock call successful\n"));
return(True);
}
/****************************************************************************
POSIX function to see if a file region is locked. Returns True if the
region is locked, False otherwise.
@ -639,7 +757,7 @@ BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_co
* fd. So we don't need to use map_lock_type here.
*/
return fcntl_lock(fsp->fd,SMB_F_GETLK,offset,count,posix_lock_type);
return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type);
}
/****************************************************************************
@ -673,7 +791,7 @@ BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_cou
* below. JRA.
*/
ret = fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,posix_lock_type);
ret = posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type);
if (ret)
add_posix_lock_entry(fsp,offset,count,posix_lock_type);
@ -992,7 +1110,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
(double)offset, (double)count ));
if (!fcntl_lock(fsp->fd,SMB_F_SETLK,offset,count,F_UNLCK))
if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK))
ret = False;
}

View File

@ -305,3 +305,8 @@ int vfswrap_ftruncate(int fd, SMB_OFF_T offset)
result = sys_ftruncate(fd, offset);
return result;
}
BOOL vfswrap_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
return fcntl_lock(fd, op, offset, count,type);
}

View File

@ -65,7 +65,8 @@ struct vfs_ops default_vfs_ops = {
vfswrap_unlink,
vfswrap_chmod,
vfswrap_utime,
vfswrap_ftruncate
vfswrap_ftruncate,
vfswrap_lock
};
/****************************************************************************
@ -210,7 +211,11 @@ BOOL vfs_init_custom(connection_struct *conn)
}
if (conn->vfs_ops.ftruncate == NULL) {
conn->vfs_ops.ftruncate= default_vfs_ops.ftruncate;
conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate;
}
if (conn->vfs_ops.lock == NULL) {
conn->vfs_ops.lock = default_vfs_ops.lock;
}
return True;