Port 2135dfe91bf1ae114a18c15286b535662200677d from 3.2.
authorJeremy Allison <jra@samba.org>
Fri, 28 Dec 2007 23:38:42 +0000 (15:38 -0800)
committerJeremy Allison <jra@samba.org>
Fri, 28 Dec 2007 23:38:42 +0000 (15:38 -0800)
From Volker :

    Fix setting the initial permission bits

    This fixes a make test failure on Solaris. When creating a new file,
    file_set_dosmode() called from open_file_ntcreate calculates a new permission
    mask, very likely different from what had been calculated in
    open_file_ntcreate. Further down we overwrote the newly calculated value with
    SMB_FCHMOD_ACL, ignoring what file_set_dosmode had calculated.

    Why did Linux not see this? fchmod_acl on a newly created file without acls
    would not retrieve an acl at all, whereas under Solaris acl(2) returns
    something even for files with just posix permissions returns something.

    Jeremy, given that we have very similar code in 3.0.28 this might also explain
    some of the bug reports that people have concerning ACLs on new files.

    Volker

    P.S: This one took a while to find...

source/smbd/dosmode.c
source/smbd/open.c

index 71d4fa179d4949fc72028c7fea89207994bc93af..28d8a77a9621466e9e688a4b86585842086171ea 100644 (file)
@@ -438,12 +438,19 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        dosmode &= SAMBA_ATTRIBUTES_MASK;
 
        DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
-       if (!st || (st && !VALID_STAT(*st))) {
+
+       if (st == NULL) {
+               SET_STAT_INVALID(st1);
                st = &st1;
+       }
+
+       if (!VALID_STAT(*st)) {
                if (SMB_VFS_STAT(conn,fname,st))
                        return(-1);
        }
 
+       unixmode = st->st_mode;
+
        get_acl_group_bits(conn, fname, &st->st_mode);
 
        if (S_ISDIR(st->st_mode))
@@ -451,11 +458,14 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        else
                dosmode &= ~aDIR;
 
-       if (dos_mode(conn,fname,st) == dosmode)
+       if (dos_mode(conn,fname,st) == dosmode) {
+               st->st_mode = unixmode;
                return(0);
+       }
 
        /* Store the DOS attributes in an EA by preference. */
        if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
+               st->st_mode = unixmode;
                return 0;
        }
 
@@ -494,6 +504,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) {
                notify_fname(conn, NOTIFY_ACTION_MODIFIED,
                             FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+               st->st_mode = unixmode;
                return 0;
        }
 
@@ -526,6 +537,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
                close_file_fchmod(fsp);
                notify_fname(conn, NOTIFY_ACTION_MODIFIED,
                             FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+               if (ret == 0) {
+                       st->st_mode = unixmode;
+               }
        }
 
        return( ret );
index 0fa11a56c817921c76fdfcf1aac63002dcdd11e7..351b72e834dbba9612da64e43648f23a09c22464 100644 (file)
@@ -1818,9 +1818,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
                if (lp_map_archive(SNUM(conn)) ||
                    lp_store_dos_attributes(SNUM(conn))) {
                        if (!posix_open) {
-                               file_set_dosmode(conn, fname,
-                                        new_dos_attributes | aARCH, NULL,
-                                        parent_dir);
+                               SMB_STRUCT_STAT tmp_sbuf;
+                               SET_STAT_INVALID(tmp_sbuf);
+                               if (file_set_dosmode(
+                                               conn, fname,
+                                               new_dos_attributes | aARCH,
+                                               &tmp_sbuf,
+                                               parent_dir) == 0) {
+                                       unx_mode = tmp_sbuf.st_mode;
+                               }
                        }
                }
        }