From dc76502cd8a950f6aff84ce4eedfd9d2b30d3dcc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 20 Aug 1998 19:28:37 +0000 Subject: Turning on blocking locking code. NB. Blocking lock requests that are not the head of an SMB request (ie. are part of a chain) will not be queued - this will be fixed when we move to the new chain code. In practice, this doesn't seem to cause much of a problem (in my admittedly limited testing) bug a debug level zero message will be placed in the log when this happens to help determine how real the problem is. smbd/locking.c: New debug messages. smbd/blocking.c: New blocking code - handles SMBlock, SMBlockread and SMBlockingX smbd/chgpasswd.c: Fix for master fd leak. smbd/files.c: Tidyup comment. smbd/nttrans.c: Added fnum to debug message. smbd/process.c: Made chain_reply() use construct_reply_common(). Added blocking lock queue processing into idle loop. smbd/reply.c: Added queue pushes for SMBlock, SMBlockread and SMBlockingX. Jeremy. (This used to be commit e1dd03ecda0bc6d7eaa31070c83774bb5679fd1b) --- source3/include/proto.h | 6 +- source3/locking/locking.c | 6 + source3/smbd/blocking.c | 284 ++++++++++++++++++++++++++++++++++++++++------ source3/smbd/chgpasswd.c | 4 + source3/smbd/files.c | 4 +- source3/smbd/nttrans.c | 2 +- source3/smbd/process.c | 72 +++++------- source3/smbd/reply.c | 36 ++++-- 8 files changed, 325 insertions(+), 89 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 9b7267658d..a4cac1c2f8 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2134,8 +2134,8 @@ void invalidate_read_prediction(int fd); BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout); void process_smb(char *inbuf, char *outbuf); char *smb_fn_name(int type); -int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); void construct_reply_common(char *inbuf,char *outbuf); +int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); int construct_reply(char *inbuf,char *outbuf,int size,int bufsize); void smbd_process(void); @@ -2171,7 +2171,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsiz); +int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz); int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); @@ -2187,7 +2187,7 @@ int reply_close(connection_struct *conn, int reply_writeclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); int reply_lock(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize); + char *inbuf,char *outbuf, int length, int dum_buffsize); int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); int reply_tdis(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index f5e27317b5..4f2c9ab345 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -109,6 +109,9 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, return False; } + DEBUG(10,("do_lock: lock type %d start=%d len=%d requested for file %s\n", + lock_type, (int)offset, (int)count, fsp->fsp_name )); + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count, map_lock_type(fsp,lock_type)); @@ -133,6 +136,9 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, if (!lp_locking(SNUM(conn))) return(True); + DEBUG(10,("do_unlock: unlock start=%d len=%d requested for file %s\n", + (int)offset, (int)count, fsp->fsp_name )); + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 294dafc405..1aa80b2797 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -22,6 +22,8 @@ #include "includes.h" extern int DEBUGLEVEL; extern int Client; +extern int chain_size; +extern char *OutBuffer; /**************************************************************************** This is the structure to queue to implement blocking locks. @@ -30,6 +32,7 @@ extern int Client; typedef struct { ubi_slNode msg_next; + int com_type; time_t expire_time; int lock_num; char *inbuf; @@ -49,10 +52,16 @@ static void free_blocking_lock_record(blocking_lock_record *blr) } /**************************************************************************** - Function to push a blocking lockingX request onto the lock queue. - NB. We can only get away with this as the CIFS spec only includes - SMB_COM_LOCKING_ANDX as a head SMB, ie. it is not one that is ever - generated as part of a chain. + Determine if this is a secondary element of a chained SMB. + **************************************************************************/ + +static BOOL in_chained_smb(void) +{ + return (chain_size != 0); +} + +/**************************************************************************** + Function to push a blocking lock request onto the lock queue. ****************************************************************************/ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) @@ -60,6 +69,11 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int blocking_lock_record *blr; files_struct *fsp = file_fsp(inbuf,smb_vwv2); + if(in_chained_smb() ) { + DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); + return False; + } + /* * Now queue an entry on the blocking lock queue. We setup * the expiration time here. @@ -76,27 +90,38 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int return False; } + blr->com_type = CVAL(inbuf,smb_com); + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + blr->lock_num = lock_num; memcpy(blr->inbuf, inbuf, length); blr->length = length; - blr->lock_num = lock_num; - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; ubi_slAddTail(&blocking_lock_queue, blr); - DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \ -for fnum = %d, name = %s\n", (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d \ +for fnum = %d, name = %s\n", length, (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); return True; } /**************************************************************************** - Return a blocking lock success SMB. + Return a smd with a given size. +*****************************************************************************/ + +static void send_blocking_reply(char *outbuf, int outsize) +{ + if(outsize > 4) + smb_setlen(outbuf,outsize - 4); + + send_smb(Client,outbuf); +} + +/**************************************************************************** + Return a lockingX success SMB. *****************************************************************************/ -static void blocking_lock_reply_success(blocking_lock_record *blr) +static void reply_lockingX_success(blocking_lock_record *blr) { - extern int chain_size; - extern char *OutBuffer; char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; @@ -113,26 +138,37 @@ static void blocking_lock_reply_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - chain_size = 0; - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); outsize += chain_size; - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); + send_blocking_reply(outbuf,outsize); +} + +/**************************************************************************** + Return a generic lock fail error blocking call. +*****************************************************************************/ + +static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, int32 ecode) +{ + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + construct_reply_common(inbuf, outbuf); + + if(eclass == 0) /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + ERROR(eclass,ecode); send_smb(Client,outbuf); } /**************************************************************************** - Return a lock fail error. Undo all the locks we have obtained first. + Return a lock fail error for a lockingX call. Undo all the locks we have + obtained first. *****************************************************************************/ -static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ecode) { - extern char *OutBuffer; - char *outbuf = OutBuffer; char *inbuf = blr->inbuf; files_struct *fsp = file_fsp(inbuf,smb_vwv2); connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); @@ -156,21 +192,159 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } + generic_blocking_lock_error(blr, eclass, ecode); +} + +/**************************************************************************** + Return a lock fail error. +*****************************************************************************/ + +static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode) +{ + switch(blr->com_type) { + case SMBlock: + generic_blocking_lock_error(blr, eclass, ecode); + break; + case SMBlockread: + generic_blocking_lock_error(blr, eclass, ecode); + break; + case SMBlockingX: + reply_lockingX_error(blr, eclass, ecode); + break; + default: + DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } +} + +/**************************************************************************** + Attempt to finish off getting all pending blocking locks for a lockread call. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL process_lockread(blocking_lock_record *blr) +{ + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + int nread = -1; + char *data; + int outsize = 0; + uint32 startpos, numtoread; + int eclass; + uint32 ecode; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + + numtoread = SVAL(inbuf,smb_vwv1); + startpos = IVAL(inbuf,smb_vwv2); + + numtoread = MIN(BUFFER_SIZE-outsize,numtoread); + data = smb_buf(outbuf) + 3; + + if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { + if((errno != EACCES) && (errno != EAGAIN)) { + /* + * We have other than a "can't get lock" POSIX + * error. Send an error. + * Return True so we get dequeued. + */ + + generic_blocking_lock_error(blr, eclass, ecode); + return True; + } + + /* + * Still waiting for lock.... + */ + + DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n", + fsp->fsp_name)); + return False; + } + + nread = read_file(fsp,data,startpos,numtoread); + + if (nread < 0) { + generic_blocking_lock_error(blr,ERRDOS,ERRnoaccess); + return True; + } + construct_reply_common(inbuf, outbuf); + outsize = set_message(outbuf,5,3,True); - if(eclass == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + outsize += nread; + SSVAL(outbuf,smb_vwv0,nread); + SSVAL(outbuf,smb_vwv5,nread+3); + SSVAL(smb_buf(outbuf),1,nread); - ERROR(eclass,ecode); - send_smb(Client,outbuf); + DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", + fsp->fsp_name, fsp->fnum, numtoread, nread ) ); + + send_blocking_reply(outbuf,outsize); + return True; } /**************************************************************************** - Attempt to finish off getting all pending blocking locks. + Attempt to finish off getting all pending blocking locks for a lock call. Returns True if we want to be removed from the list. *****************************************************************************/ -static BOOL blocking_lock_record_process(blocking_lock_record *blr) +static BOOL process_lock(blocking_lock_record *blr) +{ + char *outbuf = OutBuffer; + char *inbuf = blr->inbuf; + int outsize; + uint32 count,offset; + int eclass; + uint32 ecode; + connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + + count = IVAL(inbuf,smb_vwv1); + offset = IVAL(inbuf,smb_vwv3); + + errno = 0; + if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { + if((errno != EACCES) && (errno != EAGAIN)) { + + /* + * We have other than a "can't get lock" POSIX + * error. Send an error. + * Return True so we get dequeued. + */ + + blocking_lock_reply_error(blr, eclass, ecode); + return True; + } + + /* + * Still can't get the lock - keep waiting. + */ + + DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n", + fsp->fsp_name)); + return False; + } + + /* + * Success - we got the lock. + */ + + DEBUG(3,("process_lock : file=%s fnum=%d ofs=%d cnt=%d\n", + fsp->fsp_name, fsp->fnum, (int)offset, (int)count)); + + construct_reply_common(inbuf, outbuf); + outsize = set_message(outbuf,0,0,True); + send_blocking_reply(outbuf,outsize); + return True; +} + +/**************************************************************************** + Attempt to finish off getting all pending blocking locks for a lockingX call. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL process_lockingX(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); @@ -193,6 +367,7 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) for(; blr->lock_num < num_locks; blr->lock_num++) { count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num)); offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num)); + errno = 0; if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) break; @@ -204,10 +379,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) * Success - we got all the locks. */ - DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n", - fsp->fnum, (unsigned int)locktype, num_locks) ); + DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", + fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); - blocking_lock_reply_success(blr); + reply_lockingX_success(blr); return True; } else if((errno != EACCES) && (errno != EAGAIN)) { @@ -226,12 +401,52 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) * Still can't get all the locks - keep waiting. */ - DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \ -Waiting....\n", blr->lock_num, num_locks, fsp->fnum)); + DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ +Waiting....\n", blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); return False; } +/**************************************************************************** + Process a blocking lock SMB. + Returns True if we want to be removed from the list. +*****************************************************************************/ + +static BOOL blocking_lock_record_process(blocking_lock_record *blr) +{ + switch(blr->com_type) { + case SMBlock: + return process_lock(blr); + case SMBlockread: + return process_lockread(blr); + case SMBlockingX: + return process_lockingX(blr); + default: + DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return False; /* Keep compiler happy. */ +} + +/**************************************************************************** + Get the files_struct given a particular queued SMB. +*****************************************************************************/ + +static files_struct *get_fsp_from_blr(blocking_lock_record *blr) +{ + switch(blr->com_type) { + case SMBlock: + case SMBlockread: + return file_fsp(blr->inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(blr->inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_blr: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ +} + /**************************************************************************** Delete entries by fnum from the blocking lock pending queue. *****************************************************************************/ @@ -242,7 +457,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) blocking_lock_record *prev = NULL; while(blr != NULL) { - files_struct *req_fsp = file_fsp(blr->inbuf,smb_vwv2); + files_struct *req_fsp = get_fsp_from_blr(blr); if(req_fsp == fsp) { free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); @@ -294,18 +509,18 @@ void process_blocking_lock_queue(time_t t) */ while(blr != NULL) { - files_struct *fsp = NULL; connection_struct *conn = NULL; uint16 vuid; + files_struct *fsp = get_fsp_from_blr(blr); /* * Ensure we don't have any old chain_fnum values * sitting around.... */ + chain_size = 0; file_chain_reset(); conn = conn_find(SVAL(blr->inbuf,smb_tid)); - fsp = file_fsp(blr->inbuf,smb_vwv2); vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(blr->inbuf,smb_uid); @@ -372,4 +587,3 @@ void process_blocking_lock_queue(time_t t) blr = (blocking_lock_record *)ubi_slNext(blr); } } - diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index bd7d28b11f..ee6a2d14f4 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -308,6 +308,7 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL if ((pid = fork()) < 0) { DEBUG(3,("Cannot fork() child for password change: %s",name)); + close(master); return(False); } @@ -317,6 +318,9 @@ BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL DEBUG(3,("Child failed to change password: %s\n",name)); kill(pid, SIGKILL); /* be sure to end this process */ } + + close(master); + if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); return(False); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 4f87802119..00de8dfffa 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -380,10 +380,10 @@ files_struct *file_fsp(char *buf, int where) return NULL; } - /**************************************************************************** -reset the chained fsp - done at the start of a packet reply + Reset the chained fsp - done at the start of a packet reply ****************************************************************************/ + void file_chain_reset(void) { chain_fsp = NULL; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9a9fc51d36..236f1e2d30 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -668,7 +668,7 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 12; SCVAL(p,0,fsp->is_directory ? 1 : 0); - DEBUG(5,("reply_ntcreate_and_X: open name = %s\n", fsp->fsp_name)); + DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); return chain_reply(inbuf,outbuf,length,bufsize); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 756e010d9e..5bf8cdb2b1 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -29,7 +29,6 @@ char *InBuffer = NULL; char *OutBuffer = NULL; char *last_inbuf = NULL; - /* * Size of data we can send to client. Set * by the client for all protocols above CORE. @@ -485,6 +484,29 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize return(outsize); } +/**************************************************************************** + Helper function for contruct_reply. +****************************************************************************/ + +void construct_reply_common(char *inbuf,char *outbuf) +{ + bzero(outbuf,smb_size); + + set_message(outbuf,0,0,True); + CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); + + memcpy(outbuf+4,inbuf+4,4); + CVAL(outbuf,smb_rcls) = SMB_SUCCESS; + CVAL(outbuf,smb_reh) = 0; + CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set + means a reply */ + SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ + SSVAL(outbuf,smb_err,SMB_SUCCESS); + SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); + SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); + SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); + SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); +} /**************************************************************************** construct a chained reply and add it to the already made reply @@ -542,21 +564,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) CVAL(inbuf2,smb_com) = smb_com2; /* create the out buffer */ - bzero(outbuf2,smb_size); - set_message(outbuf2,0,0,True); - CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); - - memcpy(outbuf2+4,inbuf2+4,4); - CVAL(outbuf2,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf2,smb_reh) = 0; - CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf2,smb_err,SMB_SUCCESS); - SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); - SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); - SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); - SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid)); + construct_reply_common(inbuf2, outbuf2); DEBUG(3,("Chained message\n")); show_msg(inbuf2); @@ -582,34 +590,10 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) return outsize2; } - -/**************************************************************************** - Helper function for contruct_reply. -****************************************************************************/ - -void construct_reply_common(char *inbuf,char *outbuf) -{ - bzero(outbuf,smb_size); - - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - set_message(outbuf,0,0,True); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SMB_SUCCESS; - CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SMB_SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); -} - /**************************************************************************** construct a reply to the incoming packet ****************************************************************************/ + int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) { int type = CVAL(inbuf,smb_com); @@ -816,6 +800,12 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); global_machine_pasword_needs_changing = False; } + /* + * Check to see if we have any blocking locks + * outstanding on the queue. + */ + process_blocking_lock_queue(t); + /* * Check to see if we have any change notifies * outstanding on the queue. diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 28fed8bc04..3e59e7dbd0 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1861,7 +1861,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s /**************************************************************************** reply to a lockread (core+ protocol) ****************************************************************************/ -int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsiz) +int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz) { int nread = -1; char *data; @@ -1882,8 +1882,18 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int dum_si numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; - if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) + if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) { + if(ecode == ERRlock) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) + return -1; + } return (ERROR(eclass,ecode)); + } nread = read_file(fsp,data,startpos,numtoread); @@ -2449,7 +2459,7 @@ int reply_writeclose(connection_struct *conn, reply to a lock ****************************************************************************/ int reply_lock(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) + char *inbuf,char *outbuf, int length, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); uint32 count,offset; @@ -2466,8 +2476,18 @@ int reply_lock(connection_struct *conn, DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n", fsp->fd_ptr->fd, fsp->fnum, offset, count)); - if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) - return (ERROR(eclass,ecode)); + if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) { + if(ecode == ERRlock) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(inbuf, length, -1, 0)) + return -1; + } + return (ERROR(eclass,ecode)); + } return(outsize); } @@ -3564,6 +3584,8 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_ulocks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + DEBUG(10,("reply_lockingX: unlock start=%d, len=%d for file %s\n", + (int)offset, (int)count, fsp->fsp_name )); if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode)) return ERROR(eclass,ecode); } @@ -3578,9 +3600,10 @@ dev = %x, inode = %x\n", for(i = 0; i < (int)num_locks; i++) { count = IVAL(data,SMB_LKLEN_OFFSET(i)); offset = IVAL(data,SMB_LKOFF_OFFSET(i)); + DEBUG(10,("reply_lockingX: lock start=%d, len=%d for file %s\n", + (int)offset, (int)count, fsp->fsp_name )); if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) { -#if 0 /* JRATEST */ if((ecode == ERRlock) && (lock_timeout != 0)) { /* * A blocking lock was requested. Package up @@ -3590,7 +3613,6 @@ dev = %x, inode = %x\n", if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) return -1; } -#endif /* JRATEST */ break; } } -- cgit