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:
parent
693ffb8466
commit
ba020b0612
@ -335,7 +335,6 @@ char *readdirname(DIR *p);
|
|||||||
BOOL is_in_path(char *name, name_compare_entry *namelist);
|
BOOL is_in_path(char *name, name_compare_entry *namelist);
|
||||||
void set_namearray(name_compare_entry **ppname_array, char *namelist);
|
void set_namearray(name_compare_entry **ppname_array, char *namelist);
|
||||||
void free_namearray(name_compare_entry *name_array);
|
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 fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
|
||||||
BOOL is_myname(char *s);
|
BOOL is_myname(char *s);
|
||||||
void set_remote_arch(enum remote_arch_types type);
|
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_chmod(char *path, mode_t mode);
|
||||||
int vfswrap_utime(char *path, struct utimbuf *times);
|
int vfswrap_utime(char *path, struct utimbuf *times);
|
||||||
int vfswrap_ftruncate(int fd, SMB_OFF_T offset);
|
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 */
|
/*The following definitions come from smbd/vfs.c */
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ struct vfs_ops {
|
|||||||
int (*chmod)(char *path, mode_t mode);
|
int (*chmod)(char *path, mode_t mode);
|
||||||
int (*utime)(char *path, struct utimbuf *times);
|
int (*utime)(char *path, struct utimbuf *times);
|
||||||
int (*ftruncate)(int fd, SMB_OFF_T offset);
|
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 {
|
struct vfs_options {
|
||||||
|
@ -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 :-).
|
Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
|
||||||
****************************************************************************/
|
is dealt with in posix.c
|
||||||
|
|
||||||
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
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
|
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;
|
SMB_STRUCT_FLOCK lock;
|
||||||
int ret;
|
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));
|
DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
|
||||||
|
|
||||||
lock.l_type = 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;
|
errno = 0;
|
||||||
|
|
||||||
ret = fcntl(fd,op,&lock);
|
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)
|
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 */
|
/* a lock query */
|
||||||
if (op == SMB_F_GETLK)
|
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 != 0) &&
|
||||||
(lock.l_pid != sys_getpid()))
|
(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);
|
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 */
|
/* a lock set or unset */
|
||||||
if (ret == -1)
|
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)));
|
(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);
|
return(False);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* everything went OK */
|
/* everything went OK */
|
||||||
DEBUG(8,("Lock call successful\n"));
|
DEBUG(8,("fcntl_lock: Lock call successful\n"));
|
||||||
|
|
||||||
return(True);
|
return(True);
|
||||||
#else
|
|
||||||
return(False);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
@ -611,6 +611,124 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
|
|||||||
return True;
|
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
|
POSIX function to see if a file region is locked. Returns True if the
|
||||||
region is locked, False otherwise.
|
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.
|
* 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.
|
* 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)
|
if (ret)
|
||||||
add_posix_lock_entry(fsp,offset,count,posix_lock_type);
|
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",
|
DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",
|
||||||
(double)offset, (double)count ));
|
(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;
|
ret = False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,3 +305,8 @@ int vfswrap_ftruncate(int fd, SMB_OFF_T offset)
|
|||||||
result = sys_ftruncate(fd, offset);
|
result = sys_ftruncate(fd, offset);
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
@ -65,7 +65,8 @@ struct vfs_ops default_vfs_ops = {
|
|||||||
vfswrap_unlink,
|
vfswrap_unlink,
|
||||||
vfswrap_chmod,
|
vfswrap_chmod,
|
||||||
vfswrap_utime,
|
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) {
|
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;
|
return True;
|
||||||
|
Loading…
Reference in New Issue
Block a user