[CIFS] when not using unix extensions, check for and set ATTR_READONLY on create...
authorJeff Layton <jlayton@redhat.com>
Fri, 9 May 2008 22:28:02 +0000 (22:28 +0000)
committerSteve French <sfrench@us.ibm.com>
Sun, 11 May 2008 17:45:43 +0000 (17:45 +0000)
When creating a directory on a CIFS share without POSIX extensions,
and the given mode has no write bits set, set the ATTR_READONLY bit.

When creating a file, set ATTR_READONLY if the create mode has no write
bits set and we're not using unix extensions.

There are some comments about this being problematic due to the VFS
splitting creates into 2 parts. I'm not sure what that's actually
talking about, but I'm assuming that it has something to do with how
mknod is implemented. In the simple case where we have no unix
extensions and we're just creating a regular file, there's no reason
we can't set ATTR_READONLY.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/cifspdu.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c

index a0d26b540d4ea997971f221205f03928005379fa..c43bf4b7a5563e0bb63cb03768b35a434658d1bd 100644 (file)
 #define OPEN_NO_RECALL          0x00400000
 #define OPEN_FREE_SPACE_QUERY   0x00800000     /* should be zero */
 #define CREATE_OPTIONS_MASK     0x007FFFFF
+#define CREATE_OPTION_READONLY 0x10000000
 #define CREATE_OPTION_SPECIAL   0x20000000   /* system. NB not sent over wire */
 
 /* ImpersonationLevel flags */
index cfd9750852b3ec8af6add70690f819f1bcf06234..95fbba4ea7d47213fd9de11536fb02c6bb0c5bfa 100644 (file)
@@ -1224,11 +1224,8 @@ OldOpenRetry:
        else /* BB FIXME BB */
                pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
 
-       /* 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 */
+       if (create_options & CREATE_OPTION_READONLY)
+               pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
 
        /* BB FIXME BB */
 /*     pSMB->CreateOptions = cpu_to_le32(create_options &
@@ -1331,17 +1328,16 @@ openRetry:
                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 */
        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 */
+       if (create_options & CREATE_OPTION_READONLY)
+               pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+
        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
        pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
index 6ed775986be993379d4dd6cdcb8e2034eca5ea26..e4e0078a0526c90b9fed67f7a3c2128085902b57 100644 (file)
@@ -119,6 +119,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 {
        int rc = -ENOENT;
        int xid;
+       int create_options = CREATE_NOT_DIR;
        int oplock = 0;
        int desiredAccess = GENERIC_READ | GENERIC_WRITE;
        __u16 fileHandle;
@@ -176,9 +177,19 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                FreeXid(xid);
                return -ENOMEM;
        }
+
+       mode &= ~current->fs->umask;
+
+       /*
+        * if we're not using unix extensions, see if we need to set
+        * ATTR_READONLY on the create call
+        */
+       if (!pTcon->unix_ext && (mode & S_IWUGO) == 0)
+               create_options |= CREATE_OPTION_READONLY;
+
        if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
                rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
-                        desiredAccess, CREATE_NOT_DIR,
+                        desiredAccess, create_options,
                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        else
@@ -187,7 +198,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        if (rc == -EIO) {
                /* old server, retry the open legacy style */
                rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
-                       desiredAccess, CREATE_NOT_DIR,
+                       desiredAccess, create_options,
                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        }
@@ -197,7 +208,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                /* If Open reported that we actually created a file
                then we now have to set the mode if possible */
                if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
-                       mode &= ~current->fs->umask;
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                                CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
                                        (__u64)current->fsuid,
index d904a037c83386fe2fca290e1b163cae2094a0f9..fcbdbb6ad7bfb45f9ea5606d9f5c7f078980d467 100644 (file)
@@ -974,8 +974,8 @@ mkdir_get_info:
                  * failed to get it from the server or was set bogus */
                if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
                                direntry->d_inode->i_nlink = 2;
+               mode &= ~current->fs->umask;
                if (pTcon->unix_ext) {
-                       mode &= ~current->fs->umask;
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                                CIFSSMBUnixSetPerms(xid, pTcon, full_path,
                                                    mode,
@@ -994,9 +994,16 @@ mkdir_get_info:
                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
                        }
                } else {
-                       /* BB to be implemented via Windows secrty descriptors
-                          eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-                                                -1, -1, local_nls); */
+                       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
+                           (mode & S_IWUGO) == 0) {
+                               FILE_BASIC_INFO pInfo;
+                               memset(&pInfo, 0, sizeof(pInfo));
+                               pInfo.Attributes = cpu_to_le32(ATTR_READONLY);
+                               CIFSSMBSetTimes(xid, pTcon, full_path,
+                                               &pInfo, cifs_sb->local_nls,
+                                               cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+                       }
                        if (direntry->d_inode) {
                                direntry->d_inode->i_mode = mode;
                                direntry->d_inode->i_mode |= S_IFDIR;