⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cifssmb.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 5 页
字号:
	OPEN_RSP *pSMBr = NULL;	int bytes_returned;	int name_len;	__u16 count;openRetry:	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,		      (void **) &pSMBr);	if (rc)		return rc;	pSMB->AndXCommand = 0xFF;	/* none */	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {		count = 1;	/* account for one byte pad to word boundary */		name_len =		    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),				     fileName, PATH_MAX, nls_codepage, remap);		name_len++;	/* trailing null */		name_len *= 2;		pSMB->NameLength = cpu_to_le16(name_len);	} else {		/* BB improve check for buffer overruns BB */		count = 0;	/* no pad */		name_len = strnlen(fileName, PATH_MAX);		name_len++;	/* trailing null */		pSMB->NameLength = cpu_to_le16(name_len);		strncpy(pSMB->fileName, fileName, name_len);	}	if (*pOplock & REQ_OPLOCK)		pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);	else if (*pOplock & REQ_BATCHOPLOCK)		pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);	pSMB->DesiredAccess = cpu_to_le32(access_flags);	pSMB->AllocationSize = 0;	/* set file as system file if special file such	   as fifo and server expecting SFU style and	   no Unix extensions */	if (create_options & CREATE_OPTION_SPECIAL)		pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);	else		pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);	/* XP does not handle ATTR_POSIX_SEMANTICS */	/* but it helps speed up case sensitive checks for other	servers such as Samba */	if (tcon->ses->capabilities & CAP_UNIX)		pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);	/* if ((omode & S_IWUGO) == 0)		pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/	/*  Above line causes problems due to vfs splitting create into two		pieces - need to set mode after file created not while it is		being created */	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);	pSMB->CreateDisposition = cpu_to_le32(openDisposition);	pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);	/* BB Expirement with various impersonation levels and verify */	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);	pSMB->SecurityFlags =	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;	count += name_len;	pSMB->hdr.smb_buf_length += count;	pSMB->ByteCount = cpu_to_le16(count);	/* long_op set to 1 to allow for oplock break timeouts */	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,			 (struct smb_hdr *) pSMBr, &bytes_returned, 1);	cifs_stats_inc(&tcon->num_opens);	if (rc) {		cFYI(1, ("Error in Open = %d", rc));	} else {		*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */		*netfid = pSMBr->Fid;	/* cifs fid stays in le */		/* Let caller know file was created so we can set the mode. */		/* Do we care about the CreateAction in any other cases? */		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)			*pOplock |= CIFS_CREATE_ACTION;		if (pfile_info) {		    memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,			36 /* CreationTime to Attributes */);		    /* the file_info buf is endian converted by caller */		    pfile_info->AllocationSize = pSMBr->AllocationSize;		    pfile_info->EndOfFile = pSMBr->EndOfFile;		    pfile_info->NumberOfLinks = cpu_to_le32(1);		}	}	cifs_buf_release(pSMB);	if (rc == -EAGAIN)		goto openRetry;	return rc;}intCIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,	    const unsigned int count, const __u64 lseek, unsigned int *nbytes,	    char **buf, int *pbuf_type){	int rc = -EACCES;	READ_REQ *pSMB = NULL;	READ_RSP *pSMBr = NULL;	char *pReadData = NULL;	int wct;	int resp_buf_type = 0;	struct kvec iov[1];	cFYI(1, ("Reading %d bytes on fid %d", count, netfid));	if (tcon->ses->capabilities & CAP_LARGE_FILES)		wct = 12;	else		wct = 10; /* old style read */	*nbytes = 0;	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);	if (rc)		return rc;	/* tcon and ses pointer are checked in smb_init */	if (tcon->ses->server == NULL)		return -ECONNABORTED;	pSMB->AndXCommand = 0xFF;       /* none */	pSMB->Fid = netfid;	pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);	if (wct == 12)		pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);	else if ((lseek >> 32) > 0) /* can not handle this big offset for old */		return -EIO;	pSMB->Remaining = 0;	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);	if (wct == 12)		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */	else {		/* old style read */		struct smb_com_readx_req *pSMBW =			(struct smb_com_readx_req *)pSMB;		pSMBW->ByteCount = 0;	}	iov[0].iov_base = (char *)pSMB;	iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;	rc = SendReceive2(xid, tcon->ses, iov,			  1 /* num iovecs */,			  &resp_buf_type, 0);	cifs_stats_inc(&tcon->num_reads);	pSMBr = (READ_RSP *)iov[0].iov_base;	if (rc) {		cERROR(1, ("Send error in read = %d", rc));	} else {		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);		data_length = data_length << 16;		data_length += le16_to_cpu(pSMBr->DataLength);		*nbytes = data_length;		/*check that DataLength would not go beyond end of SMB */		if ((data_length > CIFSMaxBufSize)				|| (data_length > count)) {			cFYI(1, ("bad length %d for count %d",				 data_length, count));			rc = -EIO;			*nbytes = 0;		} else {			pReadData = (char *) (&pSMBr->hdr.Protocol) +					le16_to_cpu(pSMBr->DataOffset);/*			if (rc = copy_to_user(buf, pReadData, data_length)) {				cERROR(1,("Faulting on read rc = %d",rc));				rc = -EFAULT;			}*/ /* can not use copy_to_user when using page cache*/			if (*buf)				memcpy(*buf, pReadData, data_length);		}	}/*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */	if (*buf) {		if (resp_buf_type == CIFS_SMALL_BUFFER)			cifs_small_buf_release(iov[0].iov_base);		else if (resp_buf_type == CIFS_LARGE_BUFFER)			cifs_buf_release(iov[0].iov_base);	} else if (resp_buf_type != CIFS_NO_BUFFER) {		/* return buffer to caller to free */		*buf = iov[0].iov_base;		if (resp_buf_type == CIFS_SMALL_BUFFER)			*pbuf_type = CIFS_SMALL_BUFFER;		else if (resp_buf_type == CIFS_LARGE_BUFFER)			*pbuf_type = CIFS_LARGE_BUFFER;	} /* else no valid buffer on return - leave as null */	/* Note: On -EAGAIN error only caller can retry on handle based calls		since file handle passed in no longer valid */	return rc;}intCIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,	     const int netfid, const unsigned int count,	     const __u64 offset, unsigned int *nbytes, const char *buf,	     const char __user *ubuf, const int long_op){	int rc = -EACCES;	WRITE_REQ *pSMB = NULL;	WRITE_RSP *pSMBr = NULL;	int bytes_returned, wct;	__u32 bytes_sent;	__u16 byte_count;	/* cFYI(1,("write at %lld %d bytes",offset,count));*/	if (tcon->ses == NULL)		return -ECONNABORTED;	if (tcon->ses->capabilities & CAP_LARGE_FILES)		wct = 14;	else		wct = 12;	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,		      (void **) &pSMBr);	if (rc)		return rc;	/* tcon and ses pointer are checked in smb_init */	if (tcon->ses->server == NULL)		return -ECONNABORTED;	pSMB->AndXCommand = 0xFF;	/* none */	pSMB->Fid = netfid;	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);	if (wct == 14)		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);	else if ((offset >> 32) > 0) /* can not handle big offset for old srv */		return -EIO;	pSMB->Reserved = 0xFFFFFFFF;	pSMB->WriteMode = 0;	pSMB->Remaining = 0;	/* Can increase buffer size if buffer is big enough in some cases ie we	can send more if LARGE_WRITE_X capability returned by the server and if	our buffer is big enough or if we convert to iovecs on socket writes	and eliminate the copy to the CIFS buffer */	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);	} else {		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)			 & ~0xFF;	}	if (bytes_sent > count)		bytes_sent = count;	pSMB->DataOffset =		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);	if (buf)	    memcpy(pSMB->Data, buf, bytes_sent);	else if (ubuf) {		if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {			cifs_buf_release(pSMB);			return -EFAULT;		}	} else if (count != 0) {		/* No buffer */		cifs_buf_release(pSMB);		return -EINVAL;	} /* else setting file size with write of zero bytes */	if (wct == 14)		byte_count = bytes_sent + 1; /* pad */	else /* wct == 12 */ {		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */	}	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);	pSMB->hdr.smb_buf_length += byte_count;	if (wct == 14)		pSMB->ByteCount = cpu_to_le16(byte_count);	else { /* old style write has byte count 4 bytes earlier		  so 4 bytes pad  */		struct smb_com_writex_req *pSMBW =			(struct smb_com_writex_req *)pSMB;		pSMBW->ByteCount = cpu_to_le16(byte_count);	}	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);	cifs_stats_inc(&tcon->num_writes);	if (rc) {		cFYI(1, ("Send error in write = %d", rc));		*nbytes = 0;	} else {		*nbytes = le16_to_cpu(pSMBr->CountHigh);		*nbytes = (*nbytes) << 16;		*nbytes += le16_to_cpu(pSMBr->Count);	}	cifs_buf_release(pSMB);	/* Note: On -EAGAIN error only caller can retry on handle based calls		since file handle passed in no longer valid */	return rc;}intCIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,	     const int netfid, const unsigned int count,	     const __u64 offset, unsigned int *nbytes, struct kvec *iov,	     int n_vec, const int long_op){	int rc = -EACCES;	WRITE_REQ *pSMB = NULL;	int wct;	int smb_hdr_len;	int resp_buf_type = 0;	cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));	if (tcon->ses->capabilities & CAP_LARGE_FILES)		wct = 14;	else		wct = 12;	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);	if (rc)		return rc;	/* tcon and ses pointer are checked in smb_init */	if (tcon->ses->server == NULL)		return -ECONNABORTED;	pSMB->AndXCommand = 0xFF;	/* none */	pSMB->Fid = netfid;	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);	if (wct == 14)		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);	else if ((offset >> 32) > 0) /* can not handle big offset for old srv */		return -EIO;	pSMB->Reserved = 0xFFFFFFFF;	pSMB->WriteMode = 0;	pSMB->Remaining = 0;	pSMB->DataOffset =	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);	smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */	if (wct == 14)		pSMB->hdr.smb_buf_length += count+1;	else /* wct == 12 */		pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */	if (wct == 14)		pSMB->ByteCount = cpu_to_le16(count + 1);	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {		struct smb_com_writex_req *pSMBW =				(struct smb_com_writex_req *)pSMB;		pSMBW->ByteCount = cpu_to_le16(count + 5);	}	iov[0].iov_base = pSMB;	if (wct == 14)		iov[0].iov_len = smb_hdr_len + 4;	else /* wct == 12 pad bigger by four bytes */		iov[0].iov_len = smb_hdr_len + 8;	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,			  long_op);	cifs_stats_inc(&tcon->num_writes);	if (rc) {		cFYI(1, ("Send error Write2 = %d", rc));		*nbytes = 0;	} else if (resp_buf_type == 0) {		/* presumably this can not happen, but best to be safe */		rc = -EIO;		*nbytes = 0;	} else {		WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;		*nbytes = le16_to_cpu(pSMBr->CountHigh);		*nbytes = (*nbytes) << 16;		*nbytes += le16_to_cpu(pSMBr->Count);	}/*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */	if (resp_buf_type == CIFS_SMALL_BUFFER)		cifs_small_buf_release(iov[0].iov_base);	else if (resp_buf_type == CIFS_LARGE_BUFFER)		cifs_buf_release(iov[0].iov_base);	/* Note: On -EAGAIN error only caller can retry on handle based calls		since file handle passed in no longer valid */	return rc;}intCIFSSMBLock(const int xid, struct cifsTconInfo *tcon,	    const __u16 smb_file_id, const __u64 len,	    const __u64 offset, const __u32 numUnlock,	    const __u32 numLock, const __u8 lockType, const int waitFlag){	int rc = 0;	LOCK_REQ *pSMB = NULL;	LOCK_RSP *pSMBr = NULL;	int bytes_returned;	int timeout = 0;	__u16 count;	cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);	if (rc)		return rc;	pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {		timeout = -1; /* no response expected */		pSMB->Timeout = 0;	} else if (waitFlag == TRUE) {		timeout = 3;  /* blocking operation, no timeout */		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */	} else {		pSMB->Timeout = 0;	}	pSMB->NumberOfLocks = cpu_to_le16(numLock);	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);	pSMB->LockType = lockType;	pSMB->AndXCommand = 0xFF;	/* none */	pSMB->Fid = smb_file_id; /* netfid stays le */	if ((numLock != 0) || (numUnlock != 0)) {		pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);		/* BB where to store pid high? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -