Moved uglyness needed in fcntl locking (64->32 bit mapping, NFS
authorJeremy Allison <jra@samba.org>
Tue, 2 May 2000 03:20:47 +0000 (03:20 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 2 May 2000 03:20:47 +0000 (03:20 +0000)
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.

source/include/proto.h
source/include/vfs.h
source/lib/util.c
source/locking/posix.c
source/smbd/vfs-wrap.c
source/smbd/vfs.c

index d418ac426819029417c85eedc4437372bae458d4..11a8df31a4d89c4a93b25d03e4cadbb9ae24f8c5 100644 (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  */
 
index a09991a0e7368c2ca8bc0dbead561c583cc9249c..1b4e57f2ac14d98ee09adfce1057f4e4cb7e869e 100644 (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 {
index 8ac9223f2eb88e4c8b01f261dd494a21da14afc0..36373e984786c39dfec011a65346db814b6ec7e8 100644 (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
 }
 
 /*******************************************************************
index 7cada20ac3cb4a90ff16d12df9b382eb7eba7ef9..094cb87bc8f38c4fb4d7d9a59a5a579a5d180fb8 100644 (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;
        }
 
index a3dd7520236aadc2c7d09ace17a41ce73e3e8678..5db1689450027055620c0a2a410efb9aa04742ba 100644 (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);
+}
index d76d64684babc25d4acc3088f35da917b2223423..895d84d51cde405ced05d2a7aa5184a3bc154b33 100644 (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;