📄 cifssmb.c
字号:
} else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(fileName, 530); name_len++; /* trailing null */ strncpy(pSMB->fileName, fileName, name_len); } pSMB->SearchAttributes = cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); pSMB->BufferFormat = 0x04; pSMB->hdr.smb_buf_length += name_len + 1; pSMB->ByteCount = cpu_to_le16(name_len + 1); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Error in RMFile = %d", rc)); } #ifdef CONFIG_CIFS_STATS else { atomic_inc(&tcon->num_deletes); }#endif if (pSMB) cifs_buf_release(pSMB); if (rc == -EAGAIN) goto DelFileRetry; return rc;}intCIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, const struct nls_table *nls_codepage){ DELETE_DIRECTORY_REQ *pSMB = NULL; DELETE_DIRECTORY_RSP *pSMBr = NULL; int rc = 0; int bytes_returned; int name_len; cFYI(1, ("In CIFSSMBRmDir"));RmDirRetry: rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530 /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(dirName, 530); name_len++; /* trailing null */ strncpy(pSMB->DirName, dirName, name_len); } pSMB->BufferFormat = 0x04; pSMB->hdr.smb_buf_length += name_len + 1; pSMB->ByteCount = cpu_to_le16(name_len + 1); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Error in RMDir = %d", rc)); }#ifdef CONFIG_CIFS_STATS else { atomic_inc(&tcon->num_rmdirs); }#endif if (pSMB) cifs_buf_release(pSMB); if (rc == -EAGAIN) goto RmDirRetry; return rc;}intCIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, const char *name, const struct nls_table *nls_codepage){ int rc = 0; CREATE_DIRECTORY_REQ *pSMB = NULL; CREATE_DIRECTORY_RSP *pSMBr = NULL; int bytes_returned; int name_len; cFYI(1, ("In CIFSSMBMkDir"));MkDirRetry: rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530 /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(name, 530); name_len++; /* trailing null */ strncpy(pSMB->DirName, name, name_len); } pSMB->BufferFormat = 0x04; pSMB->hdr.smb_buf_length += name_len + 1; pSMB->ByteCount = cpu_to_le16(name_len + 1); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Error in Mkdir = %d", rc)); }#ifdef CONFIG_CIFS_STATS else { atomic_inc(&tcon->num_mkdirs); }#endif if (pSMB) cifs_buf_release(pSMB); if (rc == -EAGAIN) goto MkDirRetry; return rc;}intCIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, const char *fileName, const int openDisposition, const int access_flags, const int create_options, __u16 * netfid, int *pOplock, FILE_ALL_INFO * pfile_info, const struct nls_table *nls_codepage){ int rc = -EACCES; OPEN_REQ *pSMB = NULL; 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 = cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1), fileName, 530 /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; pSMB->NameLength = cpu_to_le16(name_len); } else { /* BB improve the check for buffer overruns BB */ count = 0; /* no pad */ name_len = strnlen(fileName, 530); 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; 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); pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ 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); if (rc) { cFYI(1, ("Error in Open = %d", rc)); } else { *pOplock = pSMBr->OplockLevel; /* one 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); }#ifdef CONFIG_CIFS_STATS atomic_inc(&tcon->num_opens);#endif } if (pSMB) cifs_buf_release(pSMB); if (rc == -EAGAIN) goto openRetry; return rc;}/* If no buffer passed in, then caller wants to do the copy as in the case of readpages so the SMB buffer must be freed by the caller */intCIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 lseek, unsigned int *nbytes, char **buf){ int rc = -EACCES; READ_REQ *pSMB = NULL; READ_RSP *pSMBr = NULL; char *pReadData = NULL; int bytes_returned; *nbytes = 0; rc = smb_init(SMB_COM_READ_ANDX, 12, 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(lseek & 0xFFFFFFFF); pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); pSMB->Remaining = 0; pSMB->MaxCount = cpu_to_le16(count); pSMB->MaxCountHigh = 0; pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cERROR(1, ("Send error in read = %d", rc)); } else { __u16 data_length = le16_to_cpu(pSMBr->DataLength); *nbytes = data_length; /*check that DataLength would not go beyond end of SMB */ if ((data_length > CIFS_MAX_MSGSIZE) || (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); } } if (pSMB) { if(*buf) cifs_buf_release(pSMB); else *buf = (char *)pSMB; } /* 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 int long_op){ int rc = -EACCES; WRITE_REQ *pSMB = NULL; WRITE_RSP *pSMBr = NULL; int bytes_returned; unsigned bytes_sent; __u16 byte_count; rc = smb_init(SMB_COM_WRITE_ANDX, 14, 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); pSMB->OffsetHigh = cpu_to_le32(offset >> 32); pSMB->Remaining = 0; bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; if (bytes_sent > count) bytes_sent = count; pSMB->DataLengthHigh = 0; pSMB->DataOffset = cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); memcpy(pSMB->Data,buf,bytes_sent); byte_count = bytes_sent + 1 /* pad */ ; pSMB->DataLengthLow = cpu_to_le16(bytes_sent); pSMB->DataLengthHigh = 0; pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, long_op); if (rc) { cFYI(1, ("Send error in write = %d", rc)); *nbytes = 0; } else *nbytes = le16_to_cpu(pSMBr->Count); if (pSMB) 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;}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 = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; 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? */ pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len); pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32)); pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset); pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32)); count = sizeof(LOCKING_ANDX_RANGE); } else { /* oplock break */ count = 0; } pSMB->hdr.smb_buf_length += count; pSMB->ByteCount = cpu_to_le16(count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, timeout); if (rc) { cFYI(1, ("Send error in Lock = %d", rc)); } if (pSMB) 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;}intCIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id){ int rc = 0; CLOSE_REQ *pSMB = NULL; CLOSE_RSP *pSMBr = NULL; int bytes_returned; cFYI(1, ("In CIFSSMBClose"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -