Commit ff50da43 authored by Steve French's avatar Steve French Committed by Steve French

even if O_CREAT specified do not reset mode when file not actually created

parent dc3d70e8
Version 1.13
------------
Fix open of files in which O_CREATE can cause the mode to change in
some cases. Fix case in which retry of write overlaps file close.
Fix PPC64 build error.
Version 1.12 Version 1.12
------------ ------------
Fixes for large file copy, signal handling, socket retry, buffer Fixes for large file copy, signal handling, socket retry, buffer
......
...@@ -774,6 +774,7 @@ exit_cifs(void) ...@@ -774,6 +774,7 @@ exit_cifs(void)
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
MODULE_DESCRIPTION MODULE_DESCRIPTION
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows Revision: 1.11"); ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
MODULE_VERSION(CIFS_VERSION);
module_init(init_cifs) module_init(init_cifs)
module_exit(exit_cifs) module_exit(exit_cifs)
...@@ -93,4 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -93,4 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#endif /* _CIFSSMB_H */ #define CIFS_VERSION "1.13"
#endif /* _CIFSFS_H */
...@@ -641,6 +641,9 @@ typedef struct smb_com_open_req { /* also handles create */ ...@@ -641,6 +641,9 @@ typedef struct smb_com_open_req { /* also handles create */
#define OPLOCK_BATCH 2 #define OPLOCK_BATCH 2
#define OPLOCK_READ 3 /* level 2 oplock */ #define OPLOCK_READ 3 /* level 2 oplock */
/* open response for CreateAction shifted left */
#define CIFS_CREATE_ACTION 0x20000 /* file created */
typedef struct smb_com_open_rsp { typedef struct smb_com_open_rsp {
struct smb_hdr hdr; /* wct = 34 BB */ struct smb_hdr hdr; /* wct = 34 BB */
__u8 AndXCommand; __u8 AndXCommand;
......
...@@ -446,8 +446,8 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, ...@@ -446,8 +446,8 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
/* find define for this maxpathcomponent */ /* find define for this maxpathcomponent */
, nls_codepage); , nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
...@@ -594,7 +594,10 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -594,7 +594,10 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
} else { } else {
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */ *netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Do we care about the CreateAction in any cases? */ /* 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) { if(pfile_info) {
memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime, memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
36 /* CreationTime to Attributes */); 36 /* CreationTime to Attributes */);
......
...@@ -256,7 +256,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -256,7 +256,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
pdu_length = 4 + ntohl(smb_buffer->smb_buf_length); pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
/* Ony read pdu_length after below checks for too short (due /* Ony read pdu_length after below checks for too short (due
to e.g. int overflow) and too long ie beyond end of buf */ to e.g. int overflow) and too long ie beyond end of buf */
cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length)); cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
temp = (char *) smb_buffer; temp = (char *) smb_buffer;
if (length > 3) { if (length > 3) {
...@@ -974,6 +974,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -974,6 +974,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
rfc1002mangle(ses_init_buf->trailer.session_req.called_name, rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
DEFAULT_CIFS_CALLED_NAME,16); DEFAULT_CIFS_CALLED_NAME,16);
ses_init_buf->trailer.session_req.calling_len = 32; ses_init_buf->trailer.session_req.calling_len = 32;
/* calling name ends in null (byte 16) from old smb
convention. */
if(netbios_name && (netbios_name[0] !=0)) { if(netbios_name && (netbios_name[0] !=0)) {
rfc1002mangle(ses_init_buf->trailer.session_req.calling_name, rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
netbios_name,16); netbios_name,16);
...@@ -983,7 +985,6 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -983,7 +985,6 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
} }
ses_init_buf->trailer.session_req.scope1 = 0; ses_init_buf->trailer.session_req.scope1 = 0;
ses_init_buf->trailer.session_req.scope2 = 0; ses_init_buf->trailer.session_req.scope2 = 0;
/* BB fixme ensure calling space padded w/null terminate*/
smb_buf = (struct smb_hdr *)ses_init_buf; smb_buf = (struct smb_hdr *)ses_init_buf;
/* sizeof RFC1002_SESSION_REQUEST with no scope */ /* sizeof RFC1002_SESSION_REQUEST with no scope */
smb_buf->smb_buf_length = 0x81000044; smb_buf->smb_buf_length = 0x81000044;
......
...@@ -179,14 +179,31 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -179,14 +179,31 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (rc) { if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc)); cFYI(1, ("cifs_create returned 0x%x ", rc));
} else { } else {
/* BB for case of overwriting existing file can we use the inode that was /* If Open reported that we actually created a file
passed in rather than creating new one?? */ then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(oplock & CIFS_CREATE_ACTION))
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else {
/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* could set r/o dos attribute if mode & 0222 == 0 */
}
/* BB server might mask mode so we have to query for Unix case*/
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb); inode->i_sb);
else else {
rc = cifs_get_inode_info(&newinode, full_path, rc = cifs_get_inode_info(&newinode, full_path,
buf, inode->i_sb); buf, inode->i_sb);
if(newinode)
newinode->i_mode = mode;
}
if (rc != 0) { if (rc != 0) {
cFYI(1,("Create worked but get_inode_info failed with rc = %d", cFYI(1,("Create worked but get_inode_info failed with rc = %d",
...@@ -198,21 +215,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -198,21 +215,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if((nd->flags & LOOKUP_OPEN) == FALSE) { if((nd->flags & LOOKUP_OPEN) == FALSE) {
/* mknod case - do not leave file open */ /* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle); CIFSSMBClose(xid, pTcon, fileHandle);
if(newinode)
newinode->i_mode = mode;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else { /* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
} else if(newinode) { } else if(newinode) {
newinode->i_mode = mode;
pCifsFile = (struct cifsFileInfo *) pCifsFile = (struct cifsFileInfo *)
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
...@@ -231,26 +234,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -231,26 +234,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if(pCifsInode) { if(pCifsInode) {
list_add(&pCifsFile->flist,&pCifsInode->openFileList); list_add(&pCifsFile->flist,&pCifsInode->openFileList);
if(oplock == OPLOCK_EXCLUSIVE) { if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",newinode)); cFYI(1,("Exclusive Oplock granted on inode %p",newinode));
} else if(oplock == OPLOCK_READ) } else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
} }
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) }
CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else { /* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
}
} }
} }
......
...@@ -62,8 +62,8 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -62,8 +62,8 @@ cifs_open(struct inode *inode, struct file *file)
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) { list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp,struct cifsFileInfo, flist); pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){ if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
/* set mode ?? */ /* mode set in cifs_create */
pCifsFile->pfile = file; /* needed for writepage */ pCifsFile->pfile = file; /* needed for writepage */
file->private_data = pCifsFile; file->private_data = pCifsFile;
break; break;
...@@ -205,17 +205,17 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -205,17 +205,17 @@ cifs_open(struct inode *inode, struct file *file)
rc = cifs_get_inode_info(&file->f_dentry->d_inode, rc = cifs_get_inode_info(&file->f_dentry->d_inode,
full_path, buf, inode->i_sb); full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) { if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode)); cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
} else if(oplock == OPLOCK_READ) } else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
} else { } else {
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
write_unlock(&file->f_owner.lock); write_unlock(&file->f_owner.lock);
} }
if(file->f_flags & O_CREAT) { if(oplock & CIFS_CREATE_ACTION) {
/* time to set mode which we can not set earlier due /* time to set mode which we can not set earlier due
to problems creating new read-only files */ to problems creating new read-only files */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
...@@ -336,11 +336,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file) ...@@ -336,11 +336,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
rc = cifs_get_inode_info(&inode, rc = cifs_get_inode_info(&inode,
full_path, buf, inode->i_sb); full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) { if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode)); cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
} else if(oplock == OPLOCK_READ) { } else if((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
pCifsInode->clientCanCacheAll = FALSE; pCifsInode->clientCanCacheAll = FALSE;
} else { } else {
...@@ -1872,15 +1872,18 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1872,15 +1872,18 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
file->f_pos++; file->f_pos++;
} }
} }
pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since this is the first field of both */ pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
/* BB also should check to make sure that pointer is not beyond the end of the SMB */ le32_to_cpu(pfindData->NextEntryOffset));
/* works also for Unix find struct since first field of both */
/* BB also should check to ensure pointer not beyond end of SMB */
} /* end for loop */ } /* end for loop */
if (findNextParms.EndofSearch != 0) { if (findNextParms.EndofSearch != 0) {
cifsFile->endOfSearch = TRUE; cifsFile->endOfSearch = TRUE;
} }
} else { } else {
cifsFile->endOfSearch = TRUE; cifsFile->endOfSearch = TRUE;
rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */ rc = 0; /* unless parent directory disappeared - do not
return error here (eg Access Denied or no more files) */
} }
} }
} /* end switch */ } /* end switch */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment