Makefile: Split definitions for SGI4,5,6.
[kai/samba.git] / source / smbd / server.c
index d7620a5804eb184d4969f253a5da721bc4cf6859..2b906a7641715d1c37bf5305e3ac703378eb65f0 100644 (file)
@@ -84,13 +84,11 @@ int chain_fnum = -1;
 /* number of open connections */
 static int num_connections_open = 0;
 
-#ifdef USE_OPLOCKS
 /* Oplock ipc UDP socket. */
 int oplock_sock = -1;
 uint16 oplock_port = 0;
 /* Current number of oplocks we have outstanding. */
 int32 global_oplocks_open = 0;
-#endif /* USE_OPLOCKS */
 
 BOOL global_oplock_break = False;
 
@@ -713,7 +711,15 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize)
                            dfree_retval : dfreeq_retval ;
           /* maybe dfree and dfreeq are calculated using different bsizes 
              so convert dfree from bsize into bsizeq */
-          *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+          /* avoid overflows due to multiplication, so do not:
+                *dfree = ((*dfree) * (*bsize)) / (bsizeq); 
+             bsize and bsizeq are powers of 2 so its better to
+             to divide them getting a multiplication or division factor
+             for dfree. Rene Nieuwenhuizen (07-10-1997) */
+          if (*bsize >= bsizeq) 
+            *dfree = *dfree * (*bsize / bsizeq);
+          else 
+            *dfree = *dfree / (bsizeq / *bsize);
           *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; 
           *bsize = bsizeq;
           *dsize = dsizeq;
@@ -803,7 +809,15 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
                        dfree_retval : dfreeq_retval ;
       /* maybe dfree and dfreeq are calculated using different bsizes 
          so convert dfree from bsize into bsizeq */
-      *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+      /* avoid overflows due to multiplication, so do not:
+              *dfree = ((*dfree) * (*bsize)) / (bsizeq); 
+       bsize and bsizeq are powers of 2 so its better to
+       to divide them getting a multiplication or division factor
+       for dfree. Rene Nieuwenhuizen (07-10-1997) */
+      if (*bsize >= bsizeq)
+        *dfree = *dfree * (*bsize / bsizeq);
+      else
+        *dfree = *dfree / (bsizeq / *bsize);
       *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
       *bsize = bsizeq;
       *dsize = dsizeq;
@@ -886,8 +900,7 @@ static void check_for_pipe(char *fname)
 /****************************************************************************
 fd support routines - attempt to do a sys_open
 ****************************************************************************/
-
-int fd_attempt_open(char *fname, int flags, int mode)
+static int fd_attempt_open(char *fname, int flags, int mode)
 {
   int fd = sys_open(fname,flags,mode);
 
@@ -939,7 +952,7 @@ int fd_attempt_open(char *fname, int flags, int mode)
 fd support routines - attempt to find an already open file by dev
 and inode - increments the ref_count of the returned file_fd_struct *.
 ****************************************************************************/
-file_fd_struct *fd_get_already_open(struct stat *sbuf)
+static file_fd_struct *fd_get_already_open(struct stat *sbuf)
 {
   int i;
   file_fd_struct *fd_ptr;
@@ -966,7 +979,7 @@ file_fd_struct *fd_get_already_open(struct stat *sbuf)
 fd support routines - attempt to find a empty slot in the FileFd array.
 Increments the ref_count of the returned entry.
 ****************************************************************************/
-file_fd_struct *fd_get_new()
+static file_fd_struct *fd_get_new()
 {
   int i;
   file_fd_struct *fd_ptr;
@@ -999,8 +1012,7 @@ n"));
 fd support routines - attempt to re-open an already open fd as O_RDWR.
 Save the already open fd (we cannot close due to POSIX file locking braindamage.
 ****************************************************************************/
-
-void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
+static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
 {
   int fd = sys_open( fname, O_RDWR, mode);
 
@@ -1020,7 +1032,7 @@ void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
 fd support routines - attempt to close the file referenced by this fd.
 Decrements the ref_count and returns it.
 ****************************************************************************/
-int fd_attempt_close(file_fd_struct *fd_ptr)
+static int fd_attempt_close(file_fd_struct *fd_ptr)
 {
   DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
           fd_ptr - &FileFd[0],
@@ -1060,6 +1072,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
 
   fsp->open = False;
   fsp->fd_ptr = 0;
+  fsp->granted_oplock = False;
   errno = EPERM;
 
   pstrcpy(fname,fname1);
@@ -1488,7 +1501,6 @@ BOOL check_file_sharing(int cnum,char *fname)
       {
         min_share_mode_entry *share_entry = &old_shares[i];
 
-#ifdef USE_OPLOCKS
         /* 
          * Break oplocks before checking share modes. See comment in
          * open_file_shared for details. 
@@ -1514,7 +1526,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
           broke_oplock = True;
           break;
         }
-#endif /* USE_OPLOCKS */
 
         /* someone else has a share lock on it, check to see 
            if we can too */
@@ -1730,7 +1741,6 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
         {
           min_share_mode_entry *share_entry = &old_shares[i];
 
-#ifdef USE_OPLOCKS
           /* 
            * By observation of NetBench, oplocks are broken *before* share
            * modes are checked. This allows a file to be closed by the client
@@ -1760,7 +1770,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
             broke_oplock = True;
             break;
           }
-#endif /* USE_OPLOCKS */
 
           /* someone else has a share lock on it, check to see 
              if we can too */
@@ -1842,7 +1851,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
     if (lp_share_modes(SNUM(cnum)))
     {
       uint16 port = 0;
-#ifdef USE_OPLOCKS
       /* JRA. Currently this only services Exlcusive and batch
          oplocks (no other opens on this file). This needs to
          be extended to level II oplocks (multiple reader
@@ -1863,10 +1871,6 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode));
         port = 0;
         oplock_request = 0;
       }
-#else /* USE_OPLOCKS */
-      oplock_request = 0;
-      port = 0;
-#endif /* USE_OPLOCKS */
       set_share_mode(token, fnum, port, oplock_request);
     }
 
@@ -2138,20 +2142,6 @@ struct
   {0,0,0}
 };
 
-/* Mapping for old clients. */
-
-struct
-{
-  int new_smb_error;
-  int old_smb_error;
-  int protocol_level;
-  enum remote_arch_types valid_ra_type;
-} old_client_errmap[] =
-{
-  {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT},
-  {0,0,0}
-};
-
 /****************************************************************************
   create an error packet from errno
 ****************************************************************************/
@@ -2182,29 +2172,6 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int
       }
     }
 
-  /* Make sure we don't return error codes that old
-     clients don't understand. */
-
-  /* JRA - unfortunately, WinNT needs some error codes
-     for apps to work correctly, Win95 will break if
-     these error codes are returned. But they both
-     negotiate the *same* protocol. So we need to use
-     the revolting 'remote_arch' enum to tie break.
-
-     There must be a better way of doing this...
-  */
-
-  for(i = 0; old_client_errmap[i].new_smb_error != 0; i++)
-  {
-    if(((Protocol < old_client_errmap[i].protocol_level) ||
-       (old_client_errmap[i].valid_ra_type != get_remote_arch())) &&
-       (old_client_errmap[i].new_smb_error == ecode))
-    {
-      ecode = old_client_errmap[i].old_smb_error;
-      break;
-    }
-  }
-
   return(error_packet(inbuf,outbuf,eclass,ecode,line));
 }
 
@@ -2472,14 +2439,13 @@ static void process_smb(char *inbuf, char *outbuf)
   trans_num++;
 }
 
-#ifdef USE_OPLOCKS
 /****************************************************************************
   open the oplock IPC socket communication
 ****************************************************************************/
 static BOOL open_oplock_ipc()
 {
   struct sockaddr_in sock_name;
-  int name_len = sizeof(sock_name);
+  int len = sizeof(sock_name);
 
   DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
 
@@ -2494,7 +2460,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
   }
 
   /* Find out the transient UDP port we have been allocated. */
-  if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &name_len)<0)
+  if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0)
   {
     DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n",
             strerror(errno)));
@@ -2505,13 +2471,16 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
   }
   oplock_port = ntohs(sock_name.sin_port);
 
+  DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", 
+            getpid(), oplock_port));
+
   return True;
 }
 
 /****************************************************************************
   process an oplock break message.
 ****************************************************************************/
-static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size)
+static BOOL process_local_message(int sock, char *buffer, int buf_size)
 {
   int32 msg_len;
   int16 from_port;
@@ -2581,7 +2550,7 @@ oplocks. Returning success.\n"));
         toaddr.sin_port = htons(from_port);
         toaddr.sin_family = AF_INET;
 
-        if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
+        if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
                 (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) 
         {
           DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
@@ -2595,6 +2564,31 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid,
 
       }
       break;
+    /* 
+     * Keep this as a debug case - eventually we can remove it.
+     */
+    case 0x8001:
+      DEBUG(0,("process_local_message: Received unsolicited break \
+reply - dumping info.\n"));
+
+      if(msg_len != OPLOCK_BREAK_MSG_LEN)
+      {
+        DEBUG(0,("process_local_message: ubr: incorrect length for reply \
+(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
+        return False;
+      }
+
+      {
+        uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
+        uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
+        uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
+
+        DEBUG(0,("process_local_message: unsolicited oplock break reply from \
+pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
+
+       }
+       return False;
+
     default:
       DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n",
                 (unsigned int)SVAL(msg_start,0)));
@@ -2613,7 +2607,6 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
   static char *outbuf = NULL;
   files_struct *fsp = NULL;
   int fnum;
-  share_lock_token token;
   time_t start_time;
   BOOL shutdown_server = False;
 
@@ -2661,16 +2654,18 @@ allowing break to succeed.\n", dev, inode, fnum));
 
   /* Ensure we have an oplock on the file */
 
-  /* Question - can a client asynchronously break an oplock ? Would it
-     ever do so ? If so this test is invalid for external smbd oplock
-     breaks and we should return True in these cases (JRA).
+  /* There is a potential race condition in that an oplock could
+     have been broken due to another udp request, and yet there are
+     still oplock break messages being sent in the udp message
+     queue for this file. So return true if we don't have an oplock,
+     as we may have just freed it.
    */
 
   if(!fsp->granted_oplock)
   {
-    DEBUG(0,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock.\n",
-              fsp->name, fnum, dev, inode));
-    return False;
+    DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \
+Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode));
+    return True;
   }
 
   /* Now comes the horrid part. We must send an oplock break to the client,
@@ -2730,7 +2725,8 @@ inode = %x).\n", fsp->name, fnum, dev, inode));
     process_smb(inbuf, outbuf);
 
     /* We only need this in case a readraw crossed on the wire. */
-    global_oplock_break = False;
+    if(global_oplock_break)
+      global_oplock_break = False;
 
     /*
      * Die if we go over the time limit.
@@ -2761,16 +2757,10 @@ inode = %x).\n", fsp->name, fnum, dev, inode));
 
   if(OPEN_FNUM(fnum))
   {
-    /* Remove the oplock flag from the sharemode. */
-    lock_share_entry(fsp->cnum, dev, inode, &token);
-    if(remove_share_oplock( fnum, token)==False)
-    {
-      DEBUG(0,("oplock_break: failed to remove share oplock for fnum %d, \
-dev = %x, inode = %x\n", fnum, dev, inode));
-      unlock_share_entry(fsp->cnum, dev, inode, token);
-      return False;
-    }
-    unlock_share_entry(fsp->cnum, dev, inode, token);
+    /* The lockingX reply will have removed the oplock flag 
+       from the sharemode. */
+    /* Paranoia.... */
+    fsp->granted_oplock = False;
   }
 
   global_oplocks_open--;
@@ -2783,8 +2773,8 @@ dev = %x, inode = %x\n", fnum, dev, inode));
     abort();
   }
 
-  DEBUG(5,("oplock_break: returning success for dev = %x, inode = %x. Current \
-global_oplocks_open = %d\n", dev, inode, global_oplocks_open));
+  DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \
+global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open));
 
   return True;
 }
@@ -2914,6 +2904,7 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
              share_entry->pid, share_entry->op_port, dev, inode));
       if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False)
         return False;
+      continue;
     }
 
     break;
@@ -2924,8 +2915,6 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
   return True;
 }
 
-#endif /* USE_OPLOCKS */
-
 /****************************************************************************
 check if a snum is in use
 ****************************************************************************/
@@ -3194,8 +3183,17 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
   }
 
   /* admin user check */
-  if (user_in_list(user,lp_admin_users(snum)) &&
-      !pcon->read_only)
+
+  /* JRA - original code denied admin user if the share was
+     marked read_only. Changed as I don't think this is needed,
+     but old code left in case there is a problem here.
+   */
+  if (user_in_list(user,lp_admin_users(snum)) 
+#if 0
+      && !pcon->read_only)
+#else
+      )
+#endif
     {
       pcon->admin_user = True;
       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
@@ -4630,9 +4628,7 @@ static void process(void)
     int counter;
     int last_keepalive=0;
     int service_load_counter = 0;
-#ifdef USE_OPLOCKS
     BOOL got_smb = False;
-#endif /* USE_OPLOCKS */
 
     if (deadtime <= 0)
       deadtime = DEFAULT_SMBD_TIMEOUT;
@@ -4643,12 +4639,8 @@ static void process(void)
     errno = 0;      
 
     for (counter=SMBD_SELECT_LOOP; 
-#ifdef USE_OPLOCKS
           !receive_message_or_smb(Client,oplock_sock,
                       InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); 
-#else /* USE_OPLOCKS */
-          !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
-#endif /* USE_OPLOCKS */
           counter += SMBD_SELECT_LOOP)
     {
       int i;
@@ -4731,14 +4723,10 @@ static void process(void)
       }
     }
 
-#ifdef USE_OPLOCKS
     if(got_smb)
-#endif /* USE_OPLOCKS */
       process_smb(InBuffer, OutBuffer);
-#ifdef USE_OPLOCKS
     else
       process_local_message(oplock_sock, InBuffer, BUFFER_SIZE);
-#endif /* USE_OPLOCKS */
   }
 }
 
@@ -5018,11 +5006,9 @@ static void usage(char *pname)
        DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
     }
 
-#ifdef USE_OPLOCKS
   /* Setup the oplock IPC socket. */
   if(!open_oplock_ipc())
     exit(1);
-#endif /* USE_OPLOCKS */
 
   process();
   close_sockets();