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
------------
Fixes for large file copy, signal handling, socket retry, buffer
......
......@@ -774,6 +774,7 @@ exit_cifs(void)
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
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_exit(exit_cifs)
......@@ -93,4 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, 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 */
#define OPLOCK_BATCH 2
#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 {
struct smb_hdr hdr; /* wct = 34 BB */
__u8 AndXCommand;
......
......@@ -446,8 +446,8 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
/* find define for this maxpathcomponent */
, nls_codepage);
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
......@@ -594,7 +594,10 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
} else {
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
*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) {
memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
36 /* CreationTime to Attributes */);
......
......@@ -256,7 +256,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
/* Ony read pdu_length after below checks for too short (due
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;
if (length > 3) {
......@@ -974,6 +974,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
DEFAULT_CIFS_CALLED_NAME,16);
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)) {
rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
netbios_name,16);
......@@ -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.scope2 = 0;
/* BB fixme ensure calling space padded w/null terminate*/
smb_buf = (struct smb_hdr *)ses_init_buf;
/* sizeof RFC1002_SESSION_REQUEST with no scope */
smb_buf->smb_buf_length = 0x81000044;
......
......@@ -179,14 +179,31 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc));
} else {
/* BB for case of overwriting existing file can we use the inode that was
passed in rather than creating new one?? */
/* If Open reported that we actually created a file
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)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb);
else
inode->i_sb);
else {
rc = cifs_get_inode_info(&newinode, full_path,
buf, inode->i_sb);
if(newinode)
newinode->i_mode = mode;
}
if (rc != 0) {
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,
if((nd->flags & LOOKUP_OPEN) == FALSE) {
/* mknod case - do not leave file open */
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) {
newinode->i_mode = mode;
pCifsFile = (struct cifsFileInfo *)
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
......@@ -231,26 +234,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsInode = CIFS_I(newinode);
if(pCifsInode) {
list_add(&pCifsFile->flist,&pCifsInode->openFileList);
if(oplock == OPLOCK_EXCLUSIVE) {
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",newinode));
} else if(oplock == OPLOCK_READ)
} else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
}
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)
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
/* set mode ?? */
if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
/* mode set in cifs_create */
pCifsFile->pfile = file; /* needed for writepage */
file->private_data = pCifsFile;
break;
......@@ -205,17 +205,17 @@ cifs_open(struct inode *inode, struct file *file)
rc = cifs_get_inode_info(&file->f_dentry->d_inode,
full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) {
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
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;
} else {
write_unlock(&GlobalSMBSeslock);
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
to problems creating new read-only files */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
......@@ -336,11 +336,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
rc = cifs_get_inode_info(&inode,
full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) {
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
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->clientCanCacheAll = FALSE;
} else {
......@@ -1872,15 +1872,18 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
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 */
/* BB also should check to make sure that pointer is not beyond the end of the SMB */
pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
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 */
if (findNextParms.EndofSearch != 0) {
cifsFile->endOfSearch = TRUE;
}
} else {
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 */
......
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