summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifspdu.h10
-rw-r--r--fs/cifs/cifssmb.c10
-rw-r--r--fs/cifs/dir.c34
-rw-r--r--fs/cifs/inode.c10
-rw-r--r--fs/cifs/readdir.c7
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 @@ openRetry:
}
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 @@ openRetry:
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;