From eda3c029899cbf435d76fea43b7e1404439ccec9 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 21 Jul 2005 15:20:28 -0700 Subject: [PATCH] [CIFS] Add compat with SFU (part 2) Creating FIFOs to non-Unix servers (with cifs mounts for which sfu option was specified) now works. Signed-off-by: Steve French (sfrench@us.ibm.com) Thanks to Martin Koeppe for his assistance --- fs/cifs/cifspdu.h | 10 +++++++++- fs/cifs/cifssmb.c | 10 ++++++++-- fs/cifs/dir.c | 34 ++++++++++++++++++++++++++++++---- fs/cifs/inode.c | 10 ++++++++++ fs/cifs/readdir.c | 7 +++++++ 5 files changed, 64 insertions(+), 7 deletions(-) diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 84d37f8e986e..3cef57b7a34f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -268,10 +268,18 @@ /* CreateOptions */ #define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ #define CREATE_WRITE_THROUGH 0x00000002 -#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ +#define CREATE_SEQUENTIAL 0x00000004 +#define CREATE_SYNC_ALERT 0x00000010 +#define CREATE_ASYNC_ALERT 0x00000020 +#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ +#define CREATE_NO_EA_KNOWLEDGE 0x00000200 +#define CREATE_EIGHT_DOT_THREE 0x00000400 #define CREATE_RANDOM_ACCESS 0x00000800 #define CREATE_DELETE_ON_CLOSE 0x00001000 +#define CREATE_OPEN_BY_ID 0x00002000 #define OPEN_REPARSE_POINT 0x00200000 +#define CREATE_OPTIONS_MASK 0x007FFFFF +#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */ /* ImpersonationLevel flags */ #define SECURITY_ANONYMOUS 0 diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 56d79fd90679..fbe651858c88 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -738,7 +738,13 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, } pSMB->DesiredAccess = cpu_to_le32(access_flags); pSMB->AllocationSize = 0; - pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); + /* 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 */ @@ -752,7 +758,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, being created */ pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); pSMB->CreateDisposition = cpu_to_le32(openDisposition); - pSMB->CreateOptions = cpu_to_le32(create_options); + 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 = diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 0d5e27fec92b..c0f20fc09290 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -327,13 +327,39 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev d_instantiate(direntry, newinode); } } else { - if((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (special_file(mode))) { + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + int oplock = 0; + u16 fileHandle; + FILE_ALL_INFO * buf; cFYI(1,("sfu compat create special file")); - /* Attributes = cpu_to_le32(ATTR_SYSTEM); - rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, ...); */ + buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); + if(buf == NULL) { + kfree(full_path); + FreeXid(xid); + return -ENOMEM; + } + + rc = CIFSSMBOpen(xid, pTcon, full_path, + FILE_CREATE, /* fail if exists */ + GENERIC_WRITE /* BB would + WRITE_OWNER | WRITE_DAC be better? */, + /* Create a file and set the + file attribute to SYSTEM */ + CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, + &fileHandle, &oplock, buf, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + + if(!rc) { + /* BB Do not bother to decode buf since no + local inode yet to put timestamps in */ + CIFSSMBClose(xid, pTcon, fileHandle); + d_drop(direntry); + } + kfree(buf); /* add code here to set EAs */ } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 95354da606d6..628aa1a9fe64 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -320,6 +320,16 @@ int cifs_get_inode_info(struct inode **pinode, on dirs */ inode->i_mode = cifs_sb->mnt_dir_mode; inode->i_mode |= S_IFDIR; + } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && + (cifsInfo->cifsAttrs & ATTR_SYSTEM) && + /* No need to le64 convert size of zero */ + (pfindData->EndOfFile == 0)) { + inode->i_mode = cifs_sb->mnt_file_mode; + inode->i_mode |= S_IFIFO; +/* BB Finish for SFU style symlinks and devies */ +/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && + (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ + } else { inode->i_mode |= S_IFREG; /* treat the dos attribute of read-only as read-only diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 42310281871c..dec3c9dd04d7 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -148,6 +148,13 @@ static void fill_in_inode(struct inode *tmp_inode, tmp_inode->i_mode = cifs_sb->mnt_dir_mode; } tmp_inode->i_mode |= S_IFDIR; + } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && + (attr & ATTR_SYSTEM) && (end_of_file == 0)) { + *pobject_type = DT_FIFO; + tmp_inode->i_mode |= S_IFIFO; +/* BB Finish for SFU style symlinks and devies */ +/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && + (attr & ATTR_SYSTEM) && ) { */ /* we no longer mark these because we could not follow them */ /* } else if (attr & ATTR_REPARSE) { *pobject_type = DT_LNK; -- GitLab