smbd: make it possible to disable get_file_infos() on searches
[jra/samba/.git] / source3 / smbd / trans2.c
index fb845220cd761b054ec216c57e452a3ef573e64b..05e8375d05b5be7742e86d3b3112228def255a82 100644 (file)
@@ -1017,7 +1017,7 @@ static void call_trans2open(connection_struct *conn,
        }
 
        size = get_file_size(sbuf);
-       fattr = dos_mode(conn,fname,&sbuf);
+       fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
        mtime = sbuf.st_mtime;
        inode = sbuf.st_ino;
        if (fattr & aDIR) {
@@ -1054,7 +1054,7 @@ static void call_trans2open(connection_struct *conn,
        SIVAL(params,20,inode);
        SSVAL(params,24,0); /* Padding. */
        if (flags & 8) {
-               uint32 ea_size = estimate_ea_size(conn, fsp, fname);
+               uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
                SIVAL(params, 26, ea_size);
        } else {
                SIVAL(params, 26, 0);
@@ -1207,6 +1207,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                                int info_level,
                                int requires_resume_key,
                                bool dont_descend,
+                               bool ask_sharemode,
                                char **ppdata,
                                char *base_data,
                                char *end_data,
@@ -1397,6 +1398,17 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                        adate_ts = get_atimespec(&sbuf);
                        create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
 
+                       if (ask_sharemode) {
+                               struct timespec write_time_ts;
+                               struct file_id fileid;
+
+                               fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+                               get_file_infos(fileid, NULL, &write_time_ts);
+                               if (!null_timespec(write_time_ts)) {
+                                       mdate_ts = write_time_ts;
+                               }
+                       }
+
                        if (lp_dos_filetime_resolution(SNUM(conn))) {
                                dos_filetime_timespec(&create_date_ts);
                                dos_filetime_timespec(&mdate_ts);
@@ -1866,6 +1878,7 @@ static void call_trans2findfirst(connection_struct *conn,
        SMB_STRUCT_STAT sbuf;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
+       bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (total_params < 13) {
@@ -2062,6 +2075,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                        req->flags2,
                                        mask,dirtype,info_level,
                                        requires_resume_key,dont_descend,
+                                       ask_sharemode,
                                        &p,pdata,data_end,
                                        space_remaining, &out_of_space,
                                        &got_exact_match,
@@ -2198,6 +2212,7 @@ static void call_trans2findnext(connection_struct *conn,
        int space_remaining;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
+       bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
        TALLOC_CTX *ctx = talloc_tos();
 
        if (total_params < 13) {
@@ -2406,6 +2421,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                                req->flags2,
                                                mask,dirtype,info_level,
                                                requires_resume_key,dont_descend,
+                                               ask_sharemode,
                                                &p,pdata,data_end,
                                                space_remaining, &out_of_space,
                                                &got_exact_match,
@@ -2470,6 +2486,7 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info)
 #ifdef SAMBA_VERSION_REVISION
        extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
 #endif
+       extended_info->samba_subversion = 0;
 #ifdef SAMBA_VERSION_RC_RELEASE
        extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
 #else
@@ -2480,7 +2497,7 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info)
 #ifdef SAMBA_VERSION_VENDOR_PATCH
        extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
 #endif
-       /* FIXME: samba_gitcommitdate should contain the git commit date. */
+       extended_info->samba_gitcommitdate = 0;
 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
        unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
 #endif
@@ -3188,7 +3205,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                }
 
                                DEBUG( 4,("call_trans2setfsinfo: "
-                                       "request transport encrption.\n"));
+                                       "request transport encryption.\n"));
 
                                status = srv_request_encryption_setup(conn,
                                                                (unsigned char **)ppdata,
@@ -3783,6 +3800,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        int len;
        time_t create_time, mtime, atime;
        struct timespec create_time_ts, mtime_ts, atime_ts;
+       struct timespec write_time_ts;
        files_struct *fsp = NULL;
        struct file_id fileid;
        struct ea_list *ea_list = NULL;
@@ -3796,6 +3814,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        }
 
        ZERO_STRUCT(sbuf);
+       ZERO_STRUCT(write_time_ts);
 
        if (tran_call == TRANSACT2_QFILEINFO) {
                if (total_params < 4) {
@@ -3860,7 +3879,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
 
                        fileid = vfs_file_id_from_sbuf(conn, &sbuf);
-                       delete_pending = get_delete_on_close_flag(fileid);
+                       get_file_infos(fileid, &delete_pending, &write_time_ts);
                } else {
                        /*
                         * Original code - this is an open file.
@@ -3876,7 +3895,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        }
                        pos = fsp->fh->position_information;
                        fileid = vfs_file_id_from_sbuf(conn, &sbuf);
-                       delete_pending = get_delete_on_close_flag(fileid);
+                       get_file_infos(fileid, &delete_pending, &write_time_ts);
                        access_mask = fsp->access_mask;
                }
 
@@ -3947,7 +3966,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                }
 
                fileid = vfs_file_id_from_sbuf(conn, &sbuf);
-               delete_pending = get_delete_on_close_flag(fileid);
+               get_file_infos(fileid, &delete_pending, &write_time_ts);
                if (delete_pending) {
                        reply_nterror(req, NT_STATUS_DELETE_PENDING);
                        return;
@@ -4072,25 +4091,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        allocation_size = get_allocation_size(conn,fsp,&sbuf);
 
-       if (fsp) {
-               if (!null_timespec(fsp->pending_modtime)) {
-                       /* the pending modtime overrides the current modtime */
-                       mtime_ts = fsp->pending_modtime;
-               }
-       } else {
-               files_struct *fsp1;
+       if (!fsp) {
                /* Do we have this path open ? */
+               files_struct *fsp1;
                fileid = vfs_file_id_from_sbuf(conn, &sbuf);
                fsp1 = file_find_di_first(fileid);
-               if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
-                       /* the pending modtime overrides the current modtime */
-                       mtime_ts = fsp1->pending_modtime;
-               }
                if (fsp1 && fsp1->initial_allocation_size) {
                        allocation_size = get_allocation_size(conn, fsp1, &sbuf);
                }
        }
 
+       if (!null_timespec(write_time_ts)) {
+               mtime_ts = write_time_ts;
+       }
+
        if (lp_dos_filetime_resolution(SNUM(conn))) {
                dos_filetime_timespec(&create_time_ts);
                dos_filetime_timespec(&mtime_ts);
@@ -4780,12 +4794,12 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
  Deal with setting the time from any of the setfilepathinfo functions.
 ****************************************************************************/
 
-static NTSTATUS smb_set_file_time(connection_struct *conn,
-                               files_struct *fsp,
-                               const char *fname,
-                               const SMB_STRUCT_STAT *psbuf,
-                               struct timespec ts[2],
-                               bool setting_write_time)
+NTSTATUS smb_set_file_time(connection_struct *conn,
+                          files_struct *fsp,
+                          const char *fname,
+                          const SMB_STRUCT_STAT *psbuf,
+                          struct timespec ts[2],
+                          bool setting_write_time)
 {
        uint32 action =
                FILE_NOTIFY_CHANGE_LAST_ACCESS
@@ -4827,7 +4841,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                }
        }
 
-       if(fsp != NULL) {
+       if (setting_write_time) {
                /*
                 * This was a setfileinfo on an open file.
                 * NT does this a lot. We also need to 
@@ -4838,13 +4852,18 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                 * away and will set it on file close and after a write. JRA.
                 */
 
-               if (!null_timespec(ts[1])) {
-                       DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
-                               time_to_asc(convert_timespec_to_time_t(ts[1])) ));
-                       fsp_set_pending_modtime(fsp, ts[1]);
-               }
+               DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
+                         time_to_asc(convert_timespec_to_time_t(ts[1])) ));
 
+               if (fsp != NULL) {
+                       set_write_time_fsp(fsp, ts[1], true);
+               } else {
+                       set_write_time_path(conn, fname,
+                                           vfs_file_id_from_sbuf(conn, psbuf),
+                                           ts[1], true);
+               }
        }
+
        DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
 
        if(file_ntimes(conn, fname, ts)!=0) {
@@ -4929,7 +4948,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
        }
 
        status = open_file_ntcreate(conn, req, fname, psbuf,
-                               FILE_WRITE_DATA,
+                               FILE_WRITE_ATTRIBUTES,
                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                FILE_OPEN,
                                0,
@@ -5321,7 +5340,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
                        fname, base_name ));
                status = rename_internals(ctx, conn, req, fname, base_name, 0,
-                                         overwrite, False, dest_has_wcard);
+                                       overwrite, False, dest_has_wcard,
+                                       FILE_WRITE_ATTRIBUTES);
        }
 
        return status;
@@ -5668,14 +5688,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                        }
                }
                /* But always update the time. */
-               if (null_timespec(fsp->pending_modtime)) {
-                       /*
-                        * This is equivalent to a write. Ensure it's seen immediately
-                        * if there are no pending writes.
-                        */
-                       set_filetime(fsp->conn, fsp->fsp_name,
-                                       timespec_current());
-               }
+               /*
+                * This is equivalent to a write. Ensure it's seen immediately
+                * if there are no pending writes.
+                */
+               trigger_write_time_update(fsp);
                return NT_STATUS_OK;
        }
 
@@ -5705,10 +5722,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
        }
 
        /* Changing the allocation size should set the last mod time. */
-       /* Don't need to call set_filetime as this will be flushed on
-        * close. */
-
-       fsp_set_pending_modtime(new_fsp, timespec_current());
+       /*
+        * This is equivalent to a write. Ensure it's seen immediately
+        * if there are no pending writes.
+        */
+       trigger_write_time_update(new_fsp);
 
        close_file(new_fsp,NORMAL_CLOSE);
        return NT_STATUS_OK;
@@ -6429,7 +6447,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
         * non-POSIX opens return SHARING_VIOLATION.
         */
 
-       lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+       lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+                                 NULL);
        if (lck == NULL) {
                DEBUG(0, ("smb_posix_unlink: Could not get share mode "
                        "lock for file %s\n", fsp->fsp_name));
@@ -6655,11 +6674,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 
        SSVAL(params,0,0);
 
-       if (fsp && !null_timespec(fsp->pending_modtime)) {
-               /* the pending modtime overrides the current modtime */
-               set_mtimespec(&sbuf, fsp->pending_modtime);
-       }
-
        switch (info_level) {
 
                case SMB_INFO_STANDARD: