permission upgrade during O_TRUNC

steve at griffin.sio2.nl steve at griffin.sio2.nl
Tue Jan 7 09:59:00 GMT 2003


Hey there, I posted a quick fix for a problem I found with all samba's up
to 2.2.7a on the general samba list, which describes the following
problem:

In Windows, if you create a file with NORMAL attributes and ALWAYS_CREATE,
close the file and then re-create it with, say, HIDDEN and ALWAYS_CREATE,
the file *should* be upgraded to HIDDEN. The other way around, ie.
starting with HIDDEN and re-creating with NORMAL should keep the file as
HIDDEN. Currently, samba always keep the original attributes. This causes
windows to incorrectly store hidden and system files from in a roaming
profile which gets you that stupid popping-up Desktop.ini in new profiles
after the second login (because the files are not hidden on the profile
directory). Why windows opens the files as non-hidden first is unknown to
me :) Anyways, here is a patch that fixes it. I have tried my best to make
it as clean as possible but as I know little of samba internals it may be
wrong ...

This works for me, and stops Desktop.ini appearing all over the place. I
haven't found any problems with it yet.

--- samba-2.2.7a/source/smbd/open.c	Tue Dec 10 15:58:17 2002
+++ samba-2.2.7a-truncfix/source/smbd/open.c	Tue Jan  7 11:49:13 2003
@@ -685,6 +685,43 @@
 	return num_share_modes;
 }
 
+int open_upgrade_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode)
+{
+	uint32 old_dos_mode, new_dos_mode;
+	SMB_STRUCT_STAT sbuf;
+	files_struct *fsp;
+	int ret;
+
+	ZERO_STRUCT(sbuf);
+
+	sbuf.st_mode = existing_mode;
+	old_dos_mode = dos_mode(conn, path, &sbuf);
+
+	sbuf.st_mode = new_mode ;
+	new_dos_mode = old_dos_mode | (dos_mode(conn, path, &sbuf) & (FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN));
+	
+	if(new_dos_mode != old_dos_mode) {
+		DEBUG(5,("upgrading attributes for file %s from %d to %d during truncate\n",path,old_dos_mode, new_dos_mode));
+	
+		if (vfs_stat(conn,path,&sbuf))
+			return -1;
+
+		fsp = open_file_fchmod(conn,path,&sbuf);
+		if (!fsp)
+			return -1;
+		become_root();
+		ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unix_mode(conn, new_dos_mode, path));
+		unbecome_root();
+		close_file_fchmod(fsp);
+	
+		return ret;
+	}
+	
+	return 0;
+}	
+
+	
+
 static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode)
 {
 	uint32 old_dos_mode, new_dos_mode;
@@ -829,6 +866,10 @@
 			errno = EACCES;
 			return NULL;
 		}
+		/* Upgrade attributes if the truncate specified more attributes
+		 * than the old file
+		 */
+		open_upgrade_attributes(conn,fname, psbuf->st_mode, mode);
 	}
 
 	if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)




More information about the samba-technical mailing list