Jelajahi Sumber

[CIFS] Allow reset of file to ATTR_NORMAL when archive bit not set

When a file had a dos attribute of 0x1 (readonly - but dos attribute
of archive was not set) - doing chmod 0777 or equivalent would
try to set a dos attribute of 0 (which some servers ignore)
rather than ATTR_NORMAL (0x20) which most servers accept.
Does not affect servers which support the CIFS Unix Extensions.

Acked-by: Prasad Potluri <pvp@us.ibm.com>
Acked-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Steve French 18 tahun lalu
induk
melakukan
066fcb06d3
2 mengubah file dengan 16 tambahan dan 4 penghapusan
  1. 4 1
      fs/cifs/CHANGES
  2. 12 3
      fs/cifs/inode.c

+ 4 - 1
fs/cifs/CHANGES

@@ -6,7 +6,10 @@ on smp system corrupts sequence number. Do not reread unnecessarily partial page
 (which we are about to overwrite anyway) when writing out file opened rw.
 (which we are about to overwrite anyway) when writing out file opened rw.
 When DOS attribute of file on non-Unix server's file changes on the server side
 When DOS attribute of file on non-Unix server's file changes on the server side
 from read-only back to read-write, reflect this change in default file mode
 from read-only back to read-write, reflect this change in default file mode
-(we had been leaving a file's mode read-only until the inode were reloaded)
+(we had been leaving a file's mode read-only until the inode were reloaded).
+Allow setting of attribute back to ATTR_NORMAL (removing readonly dos attribute
+when archive dos attribute not set and we are changing mode back to writeable
+on server which does not support the Unix Extensions).
 
 
 Version 1.47
 Version 1.47
 ------------
 ------------

+ 12 - 3
fs/cifs/inode.c

@@ -1196,6 +1196,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 	struct cifsFileInfo *open_file = NULL;
 	struct cifsFileInfo *open_file = NULL;
 	FILE_BASIC_INFO time_buf;
 	FILE_BASIC_INFO time_buf;
 	int set_time = FALSE;
 	int set_time = FALSE;
+	int set_dosattr = FALSE;
 	__u64 mode = 0xFFFFFFFFFFFFFFFFULL;
 	__u64 mode = 0xFFFFFFFFFFFFFFFFULL;
 	__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
 	__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
 	__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
 	__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
@@ -1332,15 +1333,23 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 	else if (attrs->ia_valid & ATTR_MODE) {
 	else if (attrs->ia_valid & ATTR_MODE) {
 		rc = 0;
 		rc = 0;
 		if ((mode & S_IWUGO) == 0) /* not writeable */ {
 		if ((mode & S_IWUGO) == 0) /* not writeable */ {
-			if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
+			if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
+				set_dosattr = TRUE;
 				time_buf.Attributes =
 				time_buf.Attributes =
 					cpu_to_le32(cifsInode->cifsAttrs |
 					cpu_to_le32(cifsInode->cifsAttrs |
 						    ATTR_READONLY);
 						    ATTR_READONLY);
+			}
 		} else if ((mode & S_IWUGO) == S_IWUGO) {
 		} else if ((mode & S_IWUGO) == S_IWUGO) {
-			if (cifsInode->cifsAttrs & ATTR_READONLY)
+			if (cifsInode->cifsAttrs & ATTR_READONLY) {
+				set_dosattr = TRUE;
 				time_buf.Attributes =
 				time_buf.Attributes =
 					cpu_to_le32(cifsInode->cifsAttrs &
 					cpu_to_le32(cifsInode->cifsAttrs &
 						    (~ATTR_READONLY));
 						    (~ATTR_READONLY));
+				/* Windows ignores set to zero */
+				if(time_buf.Attributes == 0)
+					time_buf.Attributes |= 
+						cpu_to_le32(ATTR_NORMAL);
+			}
 		}
 		}
 		/* BB to be implemented -
 		/* BB to be implemented -
 		   via Windows security descriptors or streams */
 		   via Windows security descriptors or streams */
@@ -1378,7 +1387,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 	} else
 	} else
 		time_buf.ChangeTime = 0;
 		time_buf.ChangeTime = 0;
 
 
-	if (set_time || time_buf.Attributes) {
+	if (set_time || set_dosattr) {
 		time_buf.CreationTime = 0;	/* do not change */
 		time_buf.CreationTime = 0;	/* do not change */
 		/* In the future we should experiment - try setting timestamps
 		/* In the future we should experiment - try setting timestamps
 		   via Handle (SetFileInfo) instead of by path */
 		   via Handle (SetFileInfo) instead of by path */