예제 #1
0
파일: blocking.c 프로젝트: hajuuk/R7000
static BOOL process_lock(blocking_lock_record *blr)
{
	char *outbuf = OutBuffer;
	char *inbuf = blr->inbuf;
	int outsize;
	SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
	NTSTATUS status;
	connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
	files_struct *fsp = blr->fsp;
	BOOL my_lock_ctx = False;

	count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
	offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);

	errno = 0;
	status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
	if (NT_STATUS_IS_ERR(status)) {
		if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
			!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
			/*
			 * We have other than a "can't get lock"
			 * error. Send an error.
			 * Return True so we get dequeued.
			 */
			
			blocking_lock_reply_error(blr, status);
			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 offset=%.0f count=%.0f\n",
		 fsp->fsp_name, fsp->fnum, (double)offset, (double)count));
	
	construct_reply_common(inbuf, outbuf);
	outsize = set_message(outbuf,0,0,True);
	send_blocking_reply(outbuf,outsize);
	return True;
}
예제 #2
0
파일: blocking.c 프로젝트: hajuuk/R7000
static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status)
{
	char *outbuf = OutBuffer;
	char *inbuf = blr->inbuf;
	construct_reply_common(inbuf, outbuf);

	/* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
	   FILE_LOCK_CONFLICT! (tridge) */
	if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
		status = NT_STATUS_FILE_LOCK_CONFLICT;
	}

	ERROR_NT(status);
	if (!send_smb(smbd_server_fd(),outbuf))
		exit_server("generic_blocking_lock_error: send_smb failed.");
}
/****************************************************************************
  construct a reply to the incoming packet
****************************************************************************/
static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize,
							 int ProcSockID, int threadid)
{
  int type = CVAL(inbuf,smb_com);
  int outsize = 0;
  int msg_type = CVAL(inbuf,0);

  chain_size[threadid] = 0;

  if (msg_type != 0)
    return(reply_special(inbuf,outbuf));  

  construct_reply_common(inbuf, outbuf);

  outsize = switch_message(type,inbuf,outbuf,size,bufsize, ProcSockID, threadid);

  outsize += chain_size[threadid];

  if(outsize > 4)
    smb_setlen(outbuf,outsize - 4);
  return(outsize);
}
예제 #4
0
파일: blocking.c 프로젝트: hajuuk/R7000
static void reply_lockingX_success(blocking_lock_record *blr)
{
	char *outbuf = OutBuffer;
	int bufsize = BUFFER_SIZE;
	char *inbuf = blr->inbuf;
	int outsize = 0;

	construct_reply_common(inbuf, outbuf);
	set_message(outbuf,2,0,True);

	/*
	 * As this message is a lockingX call we must handle
	 * any following chained message correctly.
	 * This is normally handled in construct_reply(),
	 * but as that calls switch_message, we can't use
	 * that here and must set up the chain info manually.
	 */

	outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);

	outsize += chain_size;

	send_blocking_reply(outbuf,outsize);
}
예제 #5
0
파일: blocking.c 프로젝트: hajuuk/R7000
static BOOL process_lockread(blocking_lock_record *blr)
{
	char *outbuf = OutBuffer;
	char *inbuf = blr->inbuf;
	ssize_t nread = -1;
	char *data, *p;
	int outsize = 0;
	SMB_BIG_UINT startpos;
	size_t numtoread;
	NTSTATUS status;
	connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
	files_struct *fsp = blr->fsp;
	BOOL my_lock_ctx = False;

	numtoread = SVAL(inbuf,smb_vwv1);
	startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2);
	
	numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
	data = smb_buf(outbuf) + 3;
 
	status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx);
	if (NT_STATUS_V(status)) {
		if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
			!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
			/*
			 * We have other than a "can't get lock"
			 * error. Send an error.
			 * Return True so we get dequeued.
			 */
			generic_blocking_lock_error(blr, status);
			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,NT_STATUS_ACCESS_DENIED);
		return True;
	}
	
	construct_reply_common(inbuf, outbuf);
	outsize = set_message(outbuf,5,0,True);
	
	outsize += nread;
	SSVAL(outbuf,smb_vwv0,nread);
	SSVAL(outbuf,smb_vwv5,nread+3);
	p = smb_buf(outbuf);
	*p++ = 1;
	SSVAL(p,0,nread); p += 2;
	set_message_end(outbuf, p+nread);
	
	DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n",
		   fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) );
	
	send_blocking_reply(outbuf,outsize);
	return True;
}
/****************************************************************************
  construct a chained reply and add it to the already made reply
  **************************************************************************/
int chain_reply(char *inbuf,char *outbuf,int size,int bufsize, int ProcSockID
					,int threadid)
{
  static char *orig_inbuf[NUM_SMBTHREAD];
  static char *orig_outbuf[NUM_SMBTHREAD];

  int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
  unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
  char *inbuf2, *outbuf2;
  int outsize2;
  char inbuf_saved[smb_wct];
  char outbuf_saved[smb_wct];
  int wct = CVAL(outbuf,smb_wct);
  int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);

  /* maybe its not chained */
  if (smb_com2 == 0xFF) {
    CVAL(outbuf,smb_vwv0) = 0xFF;
    return outsize;
  }

  if (chain_size[threadid] == 0) {
    /* this is the first part of the chain */
    orig_inbuf[threadid] = inbuf;
    orig_outbuf[threadid] = outbuf;
  }

  /*
   * The original Win95 redirector dies on a reply to
   * a lockingX and read chain unless the chain reply is
   * 4 byte aligned. JRA.
   */

  outsize = (outsize + 3) & ~3;

  /* we need to tell the client where the next part of the reply will be */
//0706  SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
  SSVAL(outbuf,smb_vwv1,(PTR_DIFF(outbuf+outsize,outbuf+4) 
  					+ chain_size[threadid])); //smb_offset(p,buf)
  CVAL(outbuf,smb_vwv0) = smb_com2;

  /* remember how much the caller added to the chain, only counting stuff
     after the parameter words */
  chain_size[threadid] += outsize - smb_wct;

  /* work out pointers into the original packets. The
     headers on these need to be filled in */
  inbuf2 = orig_inbuf[threadid] + smb_off2 + 4 - smb_wct;
  outbuf2 = orig_outbuf[threadid] + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;

  /* remember the original command type */
  smb_com1 = CVAL(orig_inbuf[threadid],smb_com);

  /* save the data which will be overwritten by the new headers */
  memcpy(inbuf_saved,inbuf2,smb_wct);
  memcpy(outbuf_saved,outbuf2,smb_wct);

  /* give the new packet the same header as the last part of the SMB */
  memmove(inbuf2,inbuf,smb_wct);

  /* create the in buffer */
  CVAL(inbuf2,smb_com) = smb_com2;

  /* create the out buffer */
  construct_reply_common(inbuf2, outbuf2);

//  DEBUG(3,("Chained message\n"));
//0123  show_msg(inbuf2);

  /* process the request */
  outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size[threadid],
			    bufsize-chain_size[threadid], ProcSockID, threadid);

  /* copy the new reply and request headers over the old ones, but
     preserve the smb_com field */
  memmove(orig_outbuf[threadid],outbuf2,smb_wct);
  CVAL(orig_outbuf[threadid],smb_com) = smb_com1;

  /* restore the saved data, being careful not to overwrite any
   data from the reply header */
  memcpy(inbuf2,inbuf_saved,smb_wct);
  {
    int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf[threadid]);
    if (ofs < 0) ofs = 0;
    memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);

  }
  return outsize2;
}