s3: Plumb smb_filename around SMB_VFS_CHFLAGS
authorTim Prouty <tprouty@samba.org>
Mon, 6 Jul 2009 21:36:16 +0000 (14:36 -0700)
committerTim Prouty <tprouty@samba.org>
Mon, 6 Jul 2009 22:38:41 +0000 (15:38 -0700)
SMB_VFS_CHFLAGS isn't actually getting the smb_filename struct for now
since it only operates on the basefile.  This is the strategy for all
path-based operations that will never actually operate on a stream.

By clarifying the meaning of path based operations that don't take an
smb_filename struct, modules that implement streams such as vfs_onefs
no longer need to implement SMB_VFS_CHFLAGS to ensure it's only called
on the base_name.

source3/include/proto.h
source3/modules/onefs.h
source3/modules/onefs_streams.c
source3/modules/vfs_onefs.c
source3/smbd/dosmode.c
source3/smbd/fileio.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/reply.c
source3/smbd/trans2.c

index 17c3a5135a7079e5b970c215fd1a2bd8dda5e281..1e44823abc50cfe2ce86c45de5374e0568b0b921 100644 (file)
@@ -6238,10 +6238,8 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
 uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf);
 int dos_attributes_to_stat_dos_flags(uint32_t dosmode);
 uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf);
-int file_set_dosmode(connection_struct *conn, const char *fname,
-                    uint32 dosmode, SMB_STRUCT_STAT *st,
-                    const char *parent_dir,
-                    bool newfile);
+int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
+                    uint32 dosmode, const char *parent_dir, bool newfile);
 int file_ntimes(connection_struct *conn, const char *fname,
                struct smb_file_time *ft, const SMB_STRUCT_STAT *psbuf);
 bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
index 0c39a282d41ee75076cd73cb5e64482b73077214..88ba5a93f6afa4e88b632610696ac8e612b25cde 100644 (file)
@@ -74,9 +74,6 @@ int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname);
 
 int onefs_unlink(vfs_handle_struct *handle, const char *path);
 
-int onefs_chflags(vfs_handle_struct *handle, const char *path,
-                 unsigned int flags);
-
 NTSTATUS onefs_streaminfo(vfs_handle_struct *handle,
                          struct files_struct *fsp,
                          const char *fname,
index c22fc711a0e74093a31a652d6da1e3c1081dd6a3..2a31036862fef5f2e5cad0a8de72466d8e7802a7 100644 (file)
@@ -544,26 +544,6 @@ int onefs_vtimes_streams(vfs_handle_struct *handle, const char *fname,
        return ret;
 }
 
-int onefs_chflags(vfs_handle_struct *handle, const char *path,
-                 unsigned int flags)
-{
-       char *base = NULL;
-       char *stream = NULL;
-
-       if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
-                                                         &base, &stream))) {
-               DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
-               errno = ENOMEM;
-               return -1;
-       }
-
-       /*
-        * Only set the attributes on the base file.  ifs_createfile handles
-        * file creation attribute semantics.
-        */
-       return SMB_VFS_NEXT_CHFLAGS(handle, base, flags);
-}
-
 /*
  * Streaminfo enumeration functionality
  */
index c143fcf54b4bedc2e1aa483a4dd64054fbb734b0..8ca3795e27b07f7d36e32b08bac8069be849a450 100644 (file)
@@ -290,8 +290,6 @@ static vfs_op_tuple onefs_ops[] = {
         SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(onefs_ntimes), SMB_VFS_OP_NTIMES,
         SMB_VFS_LAYER_OPAQUE},
-       {SMB_VFS_OP(onefs_chflags), SMB_VFS_OP_CHFLAGS,
-        SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(onefs_file_id_create), SMB_VFS_OP_FILE_ID_CREATE,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_streaminfo), SMB_VFS_OP_STREAMINFO,
index 03ac0897efbb82f5567f6806bf49fc906602afa1..2006b75d527850598e8a83a53dcd9a0ba523e7c6 100644 (file)
@@ -429,15 +429,14 @@ static bool get_stat_dos_flags(connection_struct *conn,
 ****************************************************************************/
 
 static bool set_stat_dos_flags(connection_struct *conn,
-                               const char *fname,
-                               SMB_STRUCT_STAT *sbuf,
-                               uint32_t dosmode,
-                               bool *attributes_changed)
+                              const struct smb_filename *smb_fname,
+                              uint32_t dosmode,
+                              bool *attributes_changed)
 {
        uint32_t new_flags = 0;
        int error = 0;
 
-       SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
+       SMB_ASSERT(VALID_STAT(smb_fname->st));
        SMB_ASSERT(attributes_changed);
 
        *attributes_changed = false;
@@ -446,23 +445,25 @@ static bool set_stat_dos_flags(connection_struct *conn,
                return false;
        }
 
-       DEBUG(5, ("Setting stat dos attributes for %s.\n", fname));
+       DEBUG(5, ("Setting stat dos attributes for %s.\n",
+                 smb_fname_str_dbg(smb_fname)));
 
-       new_flags = (sbuf->st_ex_flags & ~UF_DOS_FLAGS) |
+       new_flags = (smb_fname->st.st_ex_flags & ~UF_DOS_FLAGS) |
                     dos_attributes_to_stat_dos_flags(dosmode);
 
        /* Return early if no flags changed. */
-       if (new_flags == sbuf->st_ex_flags)
+       if (new_flags == smb_fname->st.st_ex_flags)
                return true;
 
        DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
-                 sbuf->st_ex_flags));
+                 smb_fname->st.st_ex_flags));
 
        /* Set new flags with chflags. */
-       error = SMB_VFS_CHFLAGS(conn, fname, new_flags);
+       error = SMB_VFS_CHFLAGS(conn, smb_fname->base_name, new_flags);
        if (error) {
                DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
-                         "file %s! errno=%d\n", new_flags, fname, errno));
+                         "file %s! errno=%d\n", new_flags,
+                         smb_fname_str_dbg(smb_fname), errno));
                return false;
        }
 
@@ -545,52 +546,56 @@ uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT
  chmod a file - but preserve some bits.
 ********************************************************************/
 
-int file_set_dosmode(connection_struct *conn, const char *fname,
-                    uint32 dosmode, SMB_STRUCT_STAT *st,
-                    const char *parent_dir,
-                    bool newfile)
+int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
+                    uint32 dosmode, const char *parent_dir, bool newfile)
 {
-       SMB_STRUCT_STAT st1;
        int mask=0;
        mode_t tmp;
        mode_t unixmode;
        int ret = -1, lret = -1;
        uint32_t old_mode;
+       char *fname = NULL;
+       NTSTATUS status;
 
        /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
        dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
 
-       DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
+       DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n",
+                 dosmode, smb_fname_str_dbg(smb_fname)));
 
-       if (st == NULL) {
-               SET_STAT_INVALID(st1);
-               st = &st1;
-       }
-
-       if (!VALID_STAT(*st)) {
-               if (vfs_stat_smb_fname(conn,fname,st))
+       if (!VALID_STAT(smb_fname->st)) {
+               if (SMB_VFS_STAT(conn, smb_fname))
                        return(-1);
        }
 
-       unixmode = st->st_ex_mode;
+       unixmode = smb_fname->st.st_ex_mode;
 
-       get_acl_group_bits(conn, fname, &st->st_ex_mode);
+       get_acl_group_bits(conn, smb_fname->base_name,
+                          &smb_fname->st.st_ex_mode);
 
-       if (S_ISDIR(st->st_ex_mode))
+       if (S_ISDIR(smb_fname->st.st_ex_mode))
                dosmode |= aDIR;
        else
                dosmode &= ~aDIR;
 
-       old_mode = dos_mode(conn,fname,st);
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return -1;
+       }
+
+       old_mode = dos_mode(conn, fname, &smb_fname->st);
 
        if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
                if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
                        lret = SMB_VFS_SET_OFFLINE(conn, fname);
                        if (lret == -1) {
-                               DEBUG(0, ("set_dos_mode: client has asked to set "
-                                         "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
-                                         "an error while setting it or it is not supported.\n",
-                                         parent_dir, fname));
+                               DEBUG(0, ("set_dos_mode: client has asked to "
+                                         "set FILE_ATTRIBUTE_OFFLINE to "
+                                         "%s/%s but there was an error while "
+                                         "setting it or it is not "
+                                         "supported.\n", parent_dir,
+                                         smb_fname_str_dbg(smb_fname)));
                        }
                }
        }
@@ -599,7 +604,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
 
        if (old_mode == dosmode) {
-               st->st_ex_mode = unixmode;
+               smb_fname->st.st_ex_mode = unixmode;
                return(0);
        }
 
@@ -607,26 +612,26 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        {
                bool attributes_changed;
 
-               if (set_stat_dos_flags(conn, fname, st, dosmode,
+               if (set_stat_dos_flags(conn, smb_fname, dosmode,
                                       &attributes_changed))
                {
                        if (!newfile && attributes_changed) {
                                notify_fname(conn, NOTIFY_ACTION_MODIFIED,
                                    FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
                        }
-                       st->st_ex_mode = unixmode;
+                       smb_fname->st.st_ex_mode = unixmode;
                        return 0;
                }
        }
 #endif
 
        /* Store the DOS attributes in an EA by preference. */
-       if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
+       if (set_ea_dos_attribute(conn, fname, &smb_fname->st, dosmode)) {
                if (!newfile) {
                        notify_fname(conn, NOTIFY_ACTION_MODIFIED,
                                FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
                }
-               st->st_ex_mode = unixmode;
+               smb_fname->st.st_ex_mode = unixmode;
                return 0;
        }
 
@@ -648,10 +653,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        if (!MAP_HIDDEN(conn))
                mask |= S_IXOTH;
 
-       unixmode |= (st->st_ex_mode & mask);
+       unixmode |= (smb_fname->st.st_ex_mode & mask);
 
        /* if we previously had any r bits set then leave them alone */
-       if ((tmp = st->st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
+       if ((tmp = smb_fname->st.st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
                unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
                unixmode |= tmp;
        }
@@ -659,7 +664,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
        /* if we previously had any w bits set then leave them alone 
                whilst adding in the new w bits, if the new mode is not rdonly */
        if (!IS_DOS_READONLY(dosmode)) {
-               unixmode |= (st->st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
+               unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
        }
 
        ret = SMB_VFS_CHMOD(conn, fname, unixmode);
@@ -668,7 +673,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
                        notify_fname(conn, NOTIFY_ACTION_MODIFIED,
                                     FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
                }
-               st->st_ex_mode = unixmode;
+               smb_fname->st.st_ex_mode = unixmode;
                return 0;
        }
 
@@ -693,8 +698,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
                 * break batch oplocks open by others. JRA.
                 */
                files_struct *fsp;
-               if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, st,
-                                                     &fsp)))
+               if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname,
+                                    &smb_fname->st, &fsp)))
                        return -1;
                become_root();
                ret = SMB_VFS_FCHMOD(fsp, unixmode);
@@ -705,7 +710,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
                                FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
                }
                if (ret == 0) {
-                       st->st_ex_mode = unixmode;
+                       smb_fname->st.st_ex_mode = unixmode;
                }
        }
 
index 5cc3d4b88b0ae187d7dddd82c1528e088e869229..caaebf6217b50e7407a38139044a35b5b399e43f 100644 (file)
@@ -294,10 +294,22 @@ ssize_t write_file(struct smb_request *req,
                        if ((lp_store_dos_attributes(SNUM(fsp->conn)) ||
                                        MAP_ARCHIVE(fsp->conn)) &&
                                        !IS_DOS_ARCHIVE(dosmode)) {
-                               file_set_dosmode(fsp->conn,fsp->fsp_name,
-                                               dosmode | aARCH,&st,
-                                               NULL,
-                                               false);
+                               struct smb_filename *smb_fname = NULL;
+                               NTSTATUS status;
+
+                               status = create_synthetic_smb_fname_split(
+                                           talloc_tos(), fsp->fsp_name, &st,
+                                           &smb_fname);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       errno =
+                                           map_errno_from_nt_status(status);
+                                       return -1;
+                               }
+
+                               file_set_dosmode(fsp->conn, smb_fname,
+                                               dosmode | aARCH, NULL, false);
+                               st = smb_fname->st;
+                               TALLOC_FREE(smb_fname);
                        }
 
                        /*
index add0b40f2efaa8956ba0cfd3aebfb27a766473fd..b970ffc05e70f7ccab709091b63e6d39a068fea9 100644 (file)
@@ -1219,7 +1219,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
                                uint32 attrs)
 {
        char *oldname = NULL;
-       char *newname = NULL;
        files_struct *fsp1,*fsp2;
        uint32 fattr;
        int info;
@@ -1328,20 +1327,15 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
 
        status = close_file(NULL, fsp2, NORMAL_CLOSE);
 
-       status = get_full_smb_filename(ctx, smb_fname_dst, &newname);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
-
        /* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
           creates the file. This isn't the correct thing to do in the copy
           case. JRA */
-       if (!parent_dirname(talloc_tos(), newname, &parent, NULL)) {
+       if (!parent_dirname(talloc_tos(), smb_fname_dst->base_name, &parent,
+                           NULL)) {
                status = NT_STATUS_NO_MEMORY;
                goto out;
        }
-       file_set_dosmode(conn, newname, fattr, &smb_fname_dst->st, parent,
-                        false);
+       file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
        TALLOC_FREE(parent);
 
        if (ret < (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
@@ -1356,8 +1350,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
        }
 
        TALLOC_FREE(oldname);
-       TALLOC_FREE(newname);
-
        return status;
 }
 
index df31365675d7e64af35684cf96b3c9755fcf915b..926c0ecaa7350fd07ba1ee2c46b36bf314106c08 100644 (file)
@@ -2195,14 +2195,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                if (lp_map_archive(SNUM(conn)) ||
                    lp_store_dos_attributes(SNUM(conn))) {
                        if (!posix_open) {
-                               SMB_STRUCT_STAT tmp_sbuf;
-                               SET_STAT_INVALID(tmp_sbuf);
-                               if (file_set_dosmode(
-                                           conn, fname,
+                               if (file_set_dosmode(conn, smb_fname,
                                            new_dos_attributes | aARCH,
-                                           &tmp_sbuf, parent_dir,
-                                           true) == 0) {
-                                       unx_mode = tmp_sbuf.st_ex_mode;
+                                           parent_dir, true) == 0) {
+                                       unx_mode = smb_fname->st.st_ex_mode;
                                }
                        }
                }
@@ -2338,9 +2334,8 @@ NTSTATUS close_file_fchmod(struct smb_request *req, files_struct *fsp)
 }
 
 static NTSTATUS mkdir_internal(connection_struct *conn,
-                               const char *name,
-                               uint32 file_attributes,
-                               SMB_STRUCT_STAT *psbuf)
+                              struct smb_filename *smb_dname,
+                              uint32 file_attributes)
 {
        mode_t mode;
        char *parent_dir;
@@ -2353,12 +2348,13 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       status = check_name(conn, name);
+       status = check_name(conn, smb_dname->base_name);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       if (!parent_dirname(talloc_tos(), name, &parent_dir, NULL)) {
+       if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir,
+                           NULL)) {
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -2366,39 +2362,39 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                posix_open = true;
                mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
        } else {
-               mode = unix_mode(conn, aDIR, name, parent_dir);
+               mode = unix_mode(conn, aDIR, smb_dname->base_name, parent_dir);
        }
 
-       if (SMB_VFS_MKDIR(conn, name, mode) != 0) {
+       if (SMB_VFS_MKDIR(conn, smb_dname->base_name, mode) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
        /* Ensure we're checking for a symlink here.... */
        /* We don't want to get caught by a symlink racer. */
 
-       if (vfs_lstat_smb_fname(conn, name, psbuf) == -1) {
+       if (SMB_VFS_LSTAT(conn, smb_dname) == -1) {
                DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
-                         name, strerror(errno)));
+                         smb_fname_str_dbg(smb_dname), strerror(errno)));
                return map_nt_error_from_unix(errno);
        }
 
-       if (!S_ISDIR(psbuf->st_ex_mode)) {
+       if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
                DEBUG(0, ("Directory just '%s' created is not a directory\n",
-                         name));
+                         smb_fname_str_dbg(smb_dname)));
                return NT_STATUS_ACCESS_DENIED;
        }
 
        if (lp_store_dos_attributes(SNUM(conn))) {
                if (!posix_open) {
-                       file_set_dosmode(conn, name,
-                                file_attributes | aDIR, NULL,
-                                parent_dir,
-                                true);
+                       file_set_dosmode(conn, smb_dname,
+                                        file_attributes | aDIR,
+                                        parent_dir, true);
                }
        }
 
        if (lp_inherit_perms(SNUM(conn))) {
-               inherit_access_posix_acl(conn, parent_dir, name, mode);
+               inherit_access_posix_acl(conn, parent_dir,
+                                        smb_dname->base_name, mode);
        }
 
        if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
@@ -2408,19 +2404,23 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                 * Consider bits automagically set by UNIX, i.e. SGID bit from parent
                 * dir.
                 */
-               if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_ex_mode)) {
-                       SMB_VFS_CHMOD(conn, name,
-                                     psbuf->st_ex_mode | (mode & ~psbuf->st_ex_mode));
+               if ((mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) &&
+                   (mode & ~smb_dname->st.st_ex_mode)) {
+                       SMB_VFS_CHMOD(conn, smb_dname->base_name,
+                                     (smb_dname->st.st_ex_mode |
+                                         (mode & ~smb_dname->st.st_ex_mode)));
                }
        }
 
        /* Change the owner if required. */
        if (lp_inherit_owner(SNUM(conn))) {
-               change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
+               change_dir_owner_to_parent(conn, parent_dir,
+                                          smb_dname->base_name,
+                                          &smb_dname->st);
        }
 
        notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME,
-                    name);
+                    smb_dname->base_name);
 
        return NT_STATUS_OK;
 }
@@ -2503,10 +2503,8 @@ static NTSTATUS open_directory(connection_struct *conn,
                        /* If directory exists error. If directory doesn't
                         * exist create. */
 
-                       status = mkdir_internal(conn,
-                                               smb_dname->base_name,
-                                               file_attributes,
-                                               &smb_dname->st);
+                       status = mkdir_internal(conn, smb_dname,
+                                               file_attributes);
 
                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(2, ("open_directory: unable to create "
@@ -2525,10 +2523,8 @@ static NTSTATUS open_directory(connection_struct *conn,
                         * exist create.
                         */
 
-                       status = mkdir_internal(conn,
-                                               smb_dname->base_name,
-                                               file_attributes,
-                                               &smb_dname->st);
+                       status = mkdir_internal(conn, smb_dname,
+                                               file_attributes);
 
                        if (NT_STATUS_IS_OK(status)) {
                                info = FILE_WAS_CREATED;
index e37cdcb6b4b81083b02a6e7d855e3df700220c9f..4a5610e5e1331f9eefc9a407deb904bad51ed405 100644 (file)
@@ -1216,7 +1216,7 @@ void reply_setatr(struct smb_request *req)
                else
                        mode &= ~aDIR;
 
-               if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
+               if (file_set_dosmode(conn, smb_fname, mode, NULL,
                                     false) != 0) {
                        reply_unixerror(req, ERRDOS, ERRnoaccess);
                        goto out;
index dfb682ee2120de68f5373e8780fcabe487cee370..2c74c8f49e3785cd746d1919a9d8244b8336a8b0 100644 (file)
@@ -5063,15 +5063,26 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
 
        /* check the mode isn't different, before changing it */
        if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
+               struct smb_filename *smb_fname = NULL;
+               NTSTATUS status;
+
+               status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+                                                         psbuf, &smb_fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
 
                DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
                                        fname, (unsigned int)dosmode ));
 
-               if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
+               if(file_set_dosmode(conn, smb_fname, dosmode, NULL, false)) {
                        DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
                                                fname, strerror(errno)));
+                       TALLOC_FREE(smb_fname);
                        return map_nt_error_from_unix(errno);
                }
+               *psbuf = smb_fname->st;
+               TALLOC_FREE(smb_fname);
        }
        return NT_STATUS_OK;
 }
@@ -6320,7 +6331,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                return status;
        }
 
-       id = vfs_file_id_from_sbuf(conn, psbuf);
+       id = vfs_file_id_from_sbuf(conn, &sbuf);
        for(all_fsps = file_find_di_first(id); all_fsps;
                        all_fsps = file_find_di_next(all_fsps)) {
                /*
@@ -6349,7 +6360,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                                false);
        if (modify_mtime) {
                notify_fname(conn, NOTIFY_ACTION_MODIFIED,
-                       FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+                       FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
        }
        return status;
 }