smbd: Use has_other_nonposix_opens in smb_posix_unlink
[kai/samba-autobuild/.git] / source3 / smbd / trans2.c
index af7a0d7248420929cd1272816ebc65f42ae7e275..0003c3682e3cce33866d30dbc94159ed130c755d 100644 (file)
@@ -32,7 +32,6 @@
 #include "../libcli/auth/libcli_auth.h"
 #include "../librpc/gen_ndr/xattr.h"
 #include "../librpc/gen_ndr/ndr_security.h"
-#include "../librpc/gen_ndr/open_files.h"
 #include "libcli/security/security.h"
 #include "trans2.h"
 #include "auth.h"
@@ -41,6 +40,7 @@
 #include "printing.h"
 #include "lib/util_ea.h"
 #include "lib/readdir_attr.h"
+#include "messages.h"
 
 #define DIR_ENTRY_SAFETY_MARGIN 4096
 
@@ -1708,6 +1708,7 @@ static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
                                        void *private_data,
                                        struct smb_filename *smb_fname,
+                                       bool get_dosmode,
                                        uint32_t *_mode)
 {
        struct smbd_dirptr_lanman2_state *state =
@@ -1741,7 +1742,7 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
 
        if (ms_dfs_link) {
                mode = dos_mode_msdfs(state->conn, smb_fname);
-       } else {
+       } else if (get_dosmode) {
                mode = dos_mode(state->conn, smb_fname);
        }
 
@@ -2450,12 +2451,14 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                               int requires_resume_key,
                               bool dont_descend,
                               bool ask_sharemode,
+                              bool get_dosmode,
                               uint8_t align,
                               bool do_pad,
                               char **ppdata,
                               char *base_data,
                               char *end_data,
                               int space_remaining,
+                              struct smb_filename **_smb_fname,
                               bool *got_exact_match,
                               int *_last_entry_off,
                               struct ea_list *name_list,
@@ -2504,6 +2507,7 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                                   dirtype,
                                   dont_descend,
                                   ask_sharemode,
+                                  get_dosmode,
                                   smbd_dirptr_lanman2_match_fn,
                                   smbd_dirptr_lanman2_mode_fn,
                                   &state,
@@ -2545,15 +2549,33 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
                *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
        }
 
-       TALLOC_FREE(fname);
+       if (!NT_STATUS_IS_OK(status) &&
+           !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
+       {
+               TALLOC_FREE(smb_fname);
+               TALLOC_FREE(fname);
+               return status;
+       }
+
+       if (_smb_fname != NULL) {
+               struct smb_filename *name = NULL;
+
+               name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
+               if (name == NULL) {
+                       TALLOC_FREE(smb_fname);
+                       TALLOC_FREE(fname);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               *_smb_fname = name;
+       }
+
        TALLOC_FREE(smb_fname);
+       TALLOC_FREE(fname);
+
        if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
                dptr_SeekDir(dirptr, prev_dirpos);
                return status;
        }
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
 
        *_last_entry_off = last_entry_off;
        return NT_STATUS_OK;
@@ -2588,9 +2610,10 @@ static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
        return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
                                         path_mask, dirtype, info_level,
                                         requires_resume_key, dont_descend, ask_sharemode,
-                                        align, do_pad,
+                                        true, align, do_pad,
                                         ppdata, base_data, end_data,
                                         space_remaining,
+                                        NULL,
                                         got_exact_match,
                                         last_entry_off, name_list, NULL);
 }
@@ -3452,7 +3475,8 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
        ZERO_STRUCT(smb_fname);
        smb_fname.base_name = discard_const_p(char, filename);
 
-       if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
+       if(info_level != SMB_FS_QUOTA_INFORMATION
+          && SMB_VFS_STAT(conn, &smb_fname) != 0) {
                DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
                return map_nt_error_from_unix(errno);
        }
@@ -6331,7 +6355,9 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
+       DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
+                (uint64_t)size,
+                get_file_size_stat(psbuf));
 
        if (size == get_file_size_stat(psbuf)) {
                return NT_STATUS_OK;
@@ -8283,14 +8309,15 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                                int total_data,
                                struct smb_filename *smb_fname)
 {
+       struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp = NULL;
        uint16_t flags = 0;
        char del = 1;
        int info = 0;
        int create_options = 0;
-       int i;
        struct share_mode_lock *lck = NULL;
+       bool other_nonposix_opens;
 
        if (total_data < 2) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -8353,25 +8380,12 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /*
-        * See if others still have the file open. If this is the case, then
-        * don't delete. If all opens are POSIX delete we can set the delete
-        * on close disposition.
-        */
-       for (i=0; i<lck->data->num_share_modes; i++) {
-               struct share_mode_entry *e = &lck->data->share_modes[i];
-               if (is_valid_share_mode_entry(e)) {
-                       if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
-                               continue;
-                       }
-                       if (share_mode_stale_pid(lck->data, i)) {
-                               continue;
-                       }
-                       /* Fail with sharing violation. */
-                       TALLOC_FREE(lck);
-                       close_file(req, fsp, NORMAL_CLOSE);
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
+       other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
+       if (other_nonposix_opens) {
+               /* Fail with sharing violation. */
+               TALLOC_FREE(lck);
+               close_file(req, fsp, NORMAL_CLOSE);
+               return NT_STATUS_SHARING_VIOLATION;
        }
 
        /*