/* 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;
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;
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;
/****************************************************************************
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);
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;
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;
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);
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],
fsp->open = False;
fsp->fd_ptr = 0;
+ fsp->granted_oplock = False;
errno = EPERM;
pstrcpy(fname,fname1);
{
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.
broke_oplock = True;
break;
}
-#endif /* USE_OPLOCKS */
/* someone else has a share lock on it, check to see
if we can too */
{
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
broke_oplock = True;
break;
}
-#endif /* USE_OPLOCKS */
/* someone else has a share lock on it, check to see
if we can too */
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
port = 0;
oplock_request = 0;
}
-#else /* USE_OPLOCKS */
- oplock_request = 0;
- port = 0;
-#endif /* USE_OPLOCKS */
set_share_mode(token, fnum, port, oplock_request);
}
{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
****************************************************************************/
}
}
- /* 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));
}
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"));
}
/* 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)));
}
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;
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",
}
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)));
static char *outbuf = NULL;
files_struct *fsp = NULL;
int fnum;
- share_lock_token token;
time_t start_time;
BOOL shutdown_server = False;
/* 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,
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.
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--;
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;
}
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;
return True;
}
-#endif /* USE_OPLOCKS */
-
/****************************************************************************
check if a snum is in use
****************************************************************************/
}
/* 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));
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;
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;
}
}
-#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 */
}
}
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();