LCOV - code coverage report
Current view: top level - source3/smbd - smb2_query_directory.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 323 503 64.2 %
Date: 2024-05-31 13:13:24 Functions: 11 15 73.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "locking/share_mode_lock.h"
      23             : #include "smbd/smbd.h"
      24             : #include "smbd/globals.h"
      25             : #include "../libcli/smb/smb_common.h"
      26             : #include "trans2.h"
      27             : #include "../lib/util/tevent_ntstatus.h"
      28             : #include "system/filesys.h"
      29             : #include "lib/pthreadpool/pthreadpool_tevent.h"
      30             : #include "source3/smbd/dir.h"
      31             : 
      32             : #undef DBGC_CLASS
      33             : #define DBGC_CLASS DBGC_SMB2
      34             : 
      35             : static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
      36             :                                               struct tevent_context *ev,
      37             :                                               struct smbd_smb2_request *smb2req,
      38             :                                               struct files_struct *in_fsp,
      39             :                                               uint8_t in_file_info_class,
      40             :                                               uint8_t in_flags,
      41             :                                               uint32_t in_file_index,
      42             :                                               uint32_t in_output_buffer_length,
      43             :                                               const char *in_file_name);
      44             : static NTSTATUS smbd_smb2_query_directory_recv(struct tevent_req *req,
      45             :                                     TALLOC_CTX *mem_ctx,
      46             :                                     DATA_BLOB *out_output_buffer);
      47             : 
      48             : static void smbd_smb2_request_find_done(struct tevent_req *subreq);
      49       20584 : NTSTATUS smbd_smb2_request_process_query_directory(struct smbd_smb2_request *req)
      50             : {
      51           2 :         NTSTATUS status;
      52           2 :         const uint8_t *inbody;
      53           2 :         uint8_t in_file_info_class;
      54           2 :         uint8_t in_flags;
      55           2 :         uint32_t in_file_index;
      56           2 :         uint64_t in_file_id_persistent;
      57           2 :         uint64_t in_file_id_volatile;
      58           2 :         struct files_struct *in_fsp;
      59           2 :         uint16_t in_file_name_offset;
      60           2 :         uint16_t in_file_name_length;
      61           2 :         DATA_BLOB in_file_name_buffer;
      62           2 :         char *in_file_name_string;
      63           2 :         size_t in_file_name_string_size;
      64           2 :         uint32_t in_output_buffer_length;
      65           2 :         struct tevent_req *subreq;
      66           2 :         bool ok;
      67             : 
      68       20584 :         status = smbd_smb2_request_verify_sizes(req, 0x21);
      69       20584 :         if (!NT_STATUS_IS_OK(status)) {
      70           0 :                 return smbd_smb2_request_error(req, status);
      71             :         }
      72       20584 :         inbody = SMBD_SMB2_IN_BODY_PTR(req);
      73             : 
      74       20584 :         in_file_info_class              = CVAL(inbody, 0x02);
      75       20584 :         in_flags                        = CVAL(inbody, 0x03);
      76       20584 :         in_file_index                   = IVAL(inbody, 0x04);
      77       20584 :         in_file_id_persistent           = BVAL(inbody, 0x08);
      78       20584 :         in_file_id_volatile             = BVAL(inbody, 0x10);
      79       20584 :         in_file_name_offset             = SVAL(inbody, 0x18);
      80       20584 :         in_file_name_length             = SVAL(inbody, 0x1A);
      81       20584 :         in_output_buffer_length         = IVAL(inbody, 0x1C);
      82             : 
      83       20584 :         if (in_file_name_offset == 0 && in_file_name_length == 0) {
      84             :                 /* This is ok */
      85       20584 :         } else if (in_file_name_offset !=
      86       20584 :                    (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(req))) {
      87           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      88             :         }
      89             : 
      90       20584 :         if (in_file_name_length > SMBD_SMB2_IN_DYN_LEN(req)) {
      91           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      92             :         }
      93             : 
      94             :         /* The output header is 8 bytes. */
      95       20584 :         if (in_output_buffer_length <= 8) {
      96           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      97             :         }
      98             : 
      99       20584 :         DEBUG(10,("smbd_smb2_request_find_done: in_output_buffer_length = %u\n",
     100             :                 (unsigned int)in_output_buffer_length ));
     101             : 
     102             :         /* Take into account the output header. */
     103       20584 :         in_output_buffer_length -= 8;
     104             : 
     105       20584 :         in_file_name_buffer.data = SMBD_SMB2_IN_DYN_PTR(req);
     106       20584 :         in_file_name_buffer.length = in_file_name_length;
     107             : 
     108       20584 :         ok = convert_string_talloc(req, CH_UTF16, CH_UNIX,
     109       20582 :                                    in_file_name_buffer.data,
     110             :                                    in_file_name_buffer.length,
     111             :                                    &in_file_name_string,
     112             :                                    &in_file_name_string_size);
     113       20584 :         if (!ok) {
     114           0 :                 return smbd_smb2_request_error(req, NT_STATUS_ILLEGAL_CHARACTER);
     115             :         }
     116             : 
     117       20584 :         if (in_file_name_buffer.length == 0) {
     118           0 :                 in_file_name_string_size = 0;
     119             :         }
     120             : 
     121       20584 :         if (strlen(in_file_name_string) != in_file_name_string_size) {
     122           0 :                 return smbd_smb2_request_error(req, NT_STATUS_OBJECT_NAME_INVALID);
     123             :         }
     124             : 
     125       20584 :         in_fsp = file_fsp_smb2(req, in_file_id_persistent, in_file_id_volatile);
     126       20584 :         if (in_fsp == NULL) {
     127           0 :                 return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
     128             :         }
     129             : 
     130       20584 :         subreq = smbd_smb2_query_directory_send(req, req->sconn->ev_ctx,
     131             :                                      req, in_fsp,
     132             :                                      in_file_info_class,
     133             :                                      in_flags,
     134             :                                      in_file_index,
     135             :                                      in_output_buffer_length,
     136             :                                      in_file_name_string);
     137       20584 :         if (subreq == NULL) {
     138           0 :                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     139             :         }
     140       20584 :         tevent_req_set_callback(subreq, smbd_smb2_request_find_done, req);
     141             : 
     142       20584 :         return smbd_smb2_request_pending_queue(req, subreq, 500);
     143             : }
     144             : 
     145       20584 : static void smbd_smb2_request_find_done(struct tevent_req *subreq)
     146             : {
     147       20584 :         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
     148             :                                         struct smbd_smb2_request);
     149           2 :         DATA_BLOB outbody;
     150           2 :         DATA_BLOB outdyn;
     151           2 :         uint16_t out_output_buffer_offset;
     152       20584 :         DATA_BLOB out_output_buffer = data_blob_null;
     153           2 :         NTSTATUS status;
     154           2 :         NTSTATUS error; /* transport error */
     155             : 
     156       20584 :         status = smbd_smb2_query_directory_recv(subreq,
     157             :                                      req,
     158             :                                      &out_output_buffer);
     159       20584 :         TALLOC_FREE(subreq);
     160       20584 :         if (!NT_STATUS_IS_OK(status)) {
     161        9375 :                 error = smbd_smb2_request_error(req, status);
     162        9375 :                 if (!NT_STATUS_IS_OK(error)) {
     163           0 :                         smbd_server_connection_terminate(req->xconn,
     164             :                                                          nt_errstr(error));
     165        9375 :                         return;
     166             :                 }
     167        9375 :                 return;
     168             :         }
     169             : 
     170       11209 :         out_output_buffer_offset = SMB2_HDR_BODY + 0x08;
     171             : 
     172       11209 :         outbody = smbd_smb2_generate_outbody(req, 0x08);
     173       11209 :         if (outbody.data == NULL) {
     174           0 :                 error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     175           0 :                 if (!NT_STATUS_IS_OK(error)) {
     176           0 :                         smbd_server_connection_terminate(req->xconn,
     177             :                                                          nt_errstr(error));
     178           0 :                         return;
     179             :                 }
     180           0 :                 return;
     181             :         }
     182             : 
     183       11209 :         SSVAL(outbody.data, 0x00, 0x08 + 1);    /* struct size */
     184       11209 :         SSVAL(outbody.data, 0x02,
     185             :               out_output_buffer_offset);        /* output buffer offset */
     186       11209 :         SIVAL(outbody.data, 0x04,
     187             :               out_output_buffer.length);        /* output buffer length */
     188             : 
     189       11209 :         DEBUG(10,("smbd_smb2_request_find_done: out_output_buffer.length = %u\n",
     190             :                 (unsigned int)out_output_buffer.length ));
     191             : 
     192       11209 :         outdyn = out_output_buffer;
     193             : 
     194       11209 :         error = smbd_smb2_request_done(req, outbody, &outdyn);
     195       11209 :         if (!NT_STATUS_IS_OK(error)) {
     196           0 :                 smbd_server_connection_terminate(req->xconn,
     197             :                                                  nt_errstr(error));
     198           0 :                 return;
     199             :         }
     200             : }
     201             : 
     202             : static struct tevent_req *fetch_write_time_send(TALLOC_CTX *mem_ctx,
     203             :                                                 struct tevent_context *ev,
     204             :                                                 connection_struct *conn,
     205             :                                                 struct file_id id,
     206             :                                                 int info_level,
     207             :                                                 char *entry_marshall_buf,
     208             :                                                 bool *stop);
     209             : static NTSTATUS fetch_write_time_recv(struct tevent_req *req);
     210             : 
     211             : static struct tevent_req *fetch_dos_mode_send(
     212             :         TALLOC_CTX *mem_ctx,
     213             :         struct tevent_context *ev,
     214             :         struct files_struct *dir_fsp,
     215             :         struct smb_filename **smb_fname,
     216             :         uint32_t info_level,
     217             :         uint8_t *entry_marshall_buf);
     218             : 
     219             : static NTSTATUS fetch_dos_mode_recv(struct tevent_req *req);
     220             : 
     221             : struct smbd_smb2_query_directory_state {
     222             :         struct tevent_context *ev;
     223             :         struct smbd_smb2_request *smb2req;
     224             :         uint64_t async_sharemode_count;
     225             :         uint32_t find_async_delay_usec;
     226             :         DATA_BLOB out_output_buffer;
     227             :         struct smb_request *smbreq;
     228             :         int in_output_buffer_length;
     229             :         struct files_struct *dirfsp;
     230             :         const char *in_file_name;
     231             :         NTSTATUS empty_status;
     232             :         uint32_t info_level;
     233             :         uint32_t max_count;
     234             :         char *pdata;
     235             :         char *base_data;
     236             :         char *end_data;
     237             :         uint32_t num;
     238             :         uint32_t dirtype;
     239             :         bool dont_descend;
     240             :         bool ask_sharemode;
     241             :         bool async_dosmode;
     242             :         bool async_ask_sharemode;
     243             :         int last_entry_off;
     244             :         size_t max_async_dosmode_active;
     245             :         uint32_t async_dosmode_active;
     246             :         bool done;
     247             : };
     248             : 
     249             : static bool smb2_query_directory_next_entry(struct tevent_req *req);
     250             : static void smb2_query_directory_fetch_write_time_done(struct tevent_req *subreq);
     251             : static void smb2_query_directory_dos_mode_done(struct tevent_req *subreq);
     252             : static void smb2_query_directory_waited(struct tevent_req *subreq);
     253             : 
     254       20584 : static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
     255             :                                               struct tevent_context *ev,
     256             :                                               struct smbd_smb2_request *smb2req,
     257             :                                               struct files_struct *fsp,
     258             :                                               uint8_t in_file_info_class,
     259             :                                               uint8_t in_flags,
     260             :                                               uint32_t in_file_index,
     261             :                                               uint32_t in_output_buffer_length,
     262             :                                               const char *in_file_name)
     263             : {
     264       20584 :         struct smbXsrv_connection *xconn = smb2req->xconn;
     265           2 :         struct tevent_req *req;
     266           2 :         struct smbd_smb2_query_directory_state *state;
     267       20584 :         connection_struct *conn = smb2req->tcon->compat;
     268           2 :         const struct loadparm_substitution *lp_sub =
     269       20584 :                 loadparm_s3_global_substitution();
     270           2 :         NTSTATUS status;
     271       20584 :         bool wcard_has_wild = false;
     272       20584 :         struct tm tm = {};
     273           2 :         char *p;
     274       20584 :         bool stop = false;
     275           2 :         bool ok;
     276       20584 :         bool posix_dir_handle = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
     277             : 
     278       20584 :         req = tevent_req_create(mem_ctx, &state,
     279             :                                 struct smbd_smb2_query_directory_state);
     280       20584 :         if (req == NULL) {
     281           0 :                 return NULL;
     282             :         }
     283       20584 :         state->ev = ev;
     284       20584 :         state->dirfsp = fsp;
     285       20584 :         state->smb2req = smb2req;
     286       20584 :         state->in_output_buffer_length = in_output_buffer_length;
     287       20584 :         state->in_file_name = in_file_name;
     288       20584 :         state->out_output_buffer = data_blob_null;
     289       20584 :         state->dirtype = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY;
     290             : 
     291       20584 :         DEBUG(10,("smbd_smb2_query_directory_send: %s - %s\n",
     292             :                   fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
     293             : 
     294       20584 :         state->smbreq = smbd_smb2_fake_smb_request(smb2req, fsp);
     295       20584 :         if (tevent_req_nomem(state->smbreq, req)) {
     296           0 :                 return tevent_req_post(req, ev);
     297             :         }
     298             : 
     299       20584 :         if (!fsp->fsp_flags.is_directory) {
     300           0 :                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     301           0 :                 return tevent_req_post(req, ev);
     302             :         }
     303             : 
     304       20584 :         if (strcmp(state->in_file_name, "") == 0) {
     305           0 :                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
     306           0 :                 return tevent_req_post(req, ev);
     307             :         }
     308       20584 :         if (strchr_m(state->in_file_name, '\\') != NULL) {
     309           0 :                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
     310           0 :                 return tevent_req_post(req, ev);
     311             :         }
     312       20584 :         if (strchr_m(state->in_file_name, '/') != NULL) {
     313           0 :                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
     314           0 :                 return tevent_req_post(req, ev);
     315             :         }
     316             : 
     317       20584 :         p = strptime(state->in_file_name, GMT_FORMAT, &tm);
     318       20584 :         if ((p != NULL) && (*p =='\0')) {
     319             :                 /*
     320             :                  * Bogus find that asks for a shadow copy timestamp as a
     321             :                  * directory. The correct response is that it does not exist as
     322             :                  * a directory.
     323             :                  */
     324           0 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_FILE);
     325           0 :                 return tevent_req_post(req, ev);
     326             :         }
     327             : 
     328       20584 :         if (in_output_buffer_length > xconn->smb2.server.max_trans) {
     329           0 :                 DEBUG(2,("smbd_smb2_query_directory_send: "
     330             :                          "client ignored max trans:%s: 0x%08X: 0x%08X\n",
     331             :                          __location__, in_output_buffer_length,
     332             :                          xconn->smb2.server.max_trans));
     333           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     334           0 :                 return tevent_req_post(req, ev);
     335             :         }
     336             : 
     337       20584 :         status = smbd_smb2_request_verify_creditcharge(smb2req,
     338             :                                         in_output_buffer_length);
     339             : 
     340       20584 :         if (!NT_STATUS_IS_OK(status)) {
     341           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     342           0 :                 return tevent_req_post(req, ev);
     343             :         }
     344             : 
     345       20584 :         switch (in_file_info_class) {
     346         104 :         case SMB2_FIND_DIRECTORY_INFO:
     347         104 :                 state->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
     348         104 :                 break;
     349             : 
     350         880 :         case SMB2_FIND_FULL_DIRECTORY_INFO:
     351         880 :                 state->info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
     352         880 :                 break;
     353             : 
     354         780 :         case SMB2_FIND_BOTH_DIRECTORY_INFO:
     355         780 :                 state->info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
     356         780 :                 break;
     357             : 
     358        2409 :         case SMB2_FIND_NAME_INFO:
     359        2409 :                 state->info_level = SMB_FIND_FILE_NAMES_INFO;
     360        2409 :                 break;
     361             : 
     362       16367 :         case SMB2_FIND_ID_BOTH_DIRECTORY_INFO:
     363       16367 :                 state->info_level = SMB_FIND_ID_BOTH_DIRECTORY_INFO;
     364       16367 :                 break;
     365             : 
     366          32 :         case SMB2_FIND_ID_FULL_DIRECTORY_INFO:
     367          32 :                 state->info_level = SMB_FIND_ID_FULL_DIRECTORY_INFO;
     368          32 :                 break;
     369             : 
     370          12 :         case SMB2_FIND_POSIX_INFORMATION:
     371          12 :                 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
     372           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_LEVEL);
     373           0 :                         return tevent_req_post(req, ev);
     374             :                 }
     375          12 :                 state->info_level = SMB2_FILE_POSIX_INFORMATION;
     376          12 :                 break;
     377           0 :         default:
     378           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_INFO_CLASS);
     379           0 :                 return tevent_req_post(req, ev);
     380             :         }
     381             : 
     382       20584 :         if (in_flags & SMB2_CONTINUE_FLAG_REOPEN) {
     383          36 :                 struct vfs_open_how how = { .flags = O_RDONLY, };
     384             : 
     385          36 :                 status = fd_close(fsp);
     386          36 :                 if (tevent_req_nterror(req, status)) {
     387           0 :                         return tevent_req_post(req, ev);
     388             :                 }
     389             : 
     390             :                 /*
     391             :                  * fd_close() will close and invalidate the fsp's file
     392             :                  * descriptor. So we have to reopen it.
     393             :                  */
     394             : 
     395             : #ifdef O_DIRECTORY
     396          36 :                 how.flags |= O_DIRECTORY;
     397             : #endif
     398          36 :                 status = fd_openat(conn->cwd_fsp, fsp->fsp_name, fsp, &how);
     399          36 :                 if (tevent_req_nterror(req, status)) {
     400           0 :                         return tevent_req_post(req, ev);
     401             :                 }
     402             :         }
     403             : 
     404       20584 :         if (!state->smbreq->posix_pathnames) {
     405       20560 :                 wcard_has_wild = ms_has_wild(state->in_file_name);
     406             :         }
     407             : 
     408             :         /* Ensure we've canonicalized any search path if not a wildcard. */
     409       20584 :         if (!wcard_has_wild) {
     410             :                 /*
     411             :                  * We still need to do the case processing
     412             :                  * to save off the client-supplied last component.
     413             :                  * At least we know there's no @GMT normalization
     414             :                  * or MS-DFS paths to do in a directory mask.
     415             :                  */
     416        3786 :                 state->in_file_name = get_original_lcomp(state,
     417             :                                                 conn,
     418        1893 :                                                 state->in_file_name,
     419             :                                                 0);
     420        1893 :                 if (tevent_req_nomem(state->in_file_name, req)) {
     421           0 :                         return tevent_req_post(req, ev);
     422             :                 }
     423             :         }
     424             : 
     425       20584 :         if (fsp->dptr == NULL) {
     426       10218 :                 status = dptr_create(conn,
     427             :                                      NULL, /* req */
     428             :                                      fsp,
     429             :                                      false, /* old_handle */
     430       10214 :                                      state->in_file_name, /* wcard */
     431       10216 :                                      state->dirtype,
     432             :                                      &fsp->dptr);
     433       10216 :                 if (!NT_STATUS_IS_OK(status)) {
     434           0 :                         tevent_req_nterror(req, status);
     435           0 :                         return tevent_req_post(req, ev);
     436             :                 }
     437             : 
     438       10216 :                 state->empty_status = NT_STATUS_NO_SUCH_FILE;
     439             :         } else {
     440       10368 :                 state->empty_status = STATUS_NO_MORE_FILES;
     441             :         }
     442             : 
     443       20584 :         if (in_flags & SMB2_CONTINUE_FLAG_RESTART) {
     444         514 :                 dptr_RewindDir(fsp->dptr);
     445             :         }
     446             : 
     447       20584 :         if (in_flags & SMB2_CONTINUE_FLAG_SINGLE) {
     448         126 :                 state->max_count = 1;
     449             :         } else {
     450       20458 :                 state->max_count = UINT16_MAX;
     451             :         }
     452             : 
     453             : #define DIR_ENTRY_SAFETY_MARGIN 4096
     454             : 
     455       20584 :         state->out_output_buffer = data_blob_talloc(state, NULL,
     456             :                         in_output_buffer_length + DIR_ENTRY_SAFETY_MARGIN);
     457       20584 :         if (tevent_req_nomem(state->out_output_buffer.data, req)) {
     458           0 :                 return tevent_req_post(req, ev);
     459             :         }
     460             : 
     461       20584 :         state->out_output_buffer.length = 0;
     462       20584 :         state->pdata = (char *)state->out_output_buffer.data;
     463       20584 :         state->base_data = state->pdata;
     464             :         /*
     465             :          * end_data must include the safety margin as it's what is
     466             :          * used to determine if pushed strings have been truncated.
     467             :          */
     468       20584 :         state->end_data = state->pdata + in_output_buffer_length + DIR_ENTRY_SAFETY_MARGIN - 1;
     469             : 
     470       20584 :         DEBUG(8,("smbd_smb2_query_directory_send: dirpath=<%s> dontdescend=<%s>, "
     471             :                 "in_output_buffer_length = %u\n",
     472             :                  fsp->fsp_name->base_name, lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
     473             :                 (unsigned int)in_output_buffer_length ));
     474             : 
     475       20584 :         state->dont_descend = in_list(
     476       20584 :                 fsp->fsp_name->base_name,
     477       20584 :                 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
     478       20560 :                 posix_dir_handle ? true : conn->case_sensitive);
     479             : 
     480             :         /*
     481             :          * SMB_FIND_FILE_NAMES_INFO doesn't need stat information
     482             :          *
     483             :          * This may change when we try to improve the delete on close
     484             :          * handling in future.
     485             :          */
     486       20584 :         if (state->info_level != SMB_FIND_FILE_NAMES_INFO) {
     487       18175 :                 state->ask_sharemode = fsp_search_ask_sharemode(fsp);
     488             : 
     489       18175 :                 state->async_dosmode = lp_smbd_async_dosmode(SNUM(conn));
     490             :         }
     491             : 
     492       20584 :         if (state->ask_sharemode && lp_clustering()) {
     493           0 :                 state->ask_sharemode = false;
     494           0 :                 state->async_ask_sharemode = true;
     495             :         }
     496             : 
     497       20584 :         if (state->async_dosmode) {
     498           0 :                 size_t max_threads;
     499             : 
     500          34 :                 max_threads = pthreadpool_tevent_max_threads(conn->sconn->pool);
     501          34 :                 if (max_threads == 0 || !per_thread_cwd_supported()) {
     502           0 :                         state->async_dosmode = false;
     503             :                 }
     504             : 
     505          68 :                 state->max_async_dosmode_active = lp_smbd_max_async_dosmode(
     506          34 :                                                         SNUM(conn));
     507          34 :                 if (state->max_async_dosmode_active == 0) {
     508          34 :                         state->max_async_dosmode_active = max_threads * 2;
     509             :                 }
     510             :         }
     511             : 
     512       20584 :         if (state->async_dosmode || state->async_ask_sharemode) {
     513             :                 /*
     514             :                  * Should we only set async_internal
     515             :                  * if we're not the last request in
     516             :                  * a compound chain?
     517             :                  */
     518          34 :                 smb2_request_set_async_internal(smb2req, true);
     519             :         }
     520             : 
     521             :         /*
     522             :          * This gets set in autobuild for some tests
     523             :          */
     524       20584 :         state->find_async_delay_usec = lp_parm_ulong(SNUM(conn), "smbd",
     525             :                                                      "find async delay usec",
     526             :                                                      0);
     527             : 
     528      738054 :         while (!stop) {
     529      717470 :                 stop = smb2_query_directory_next_entry(req);
     530             :         }
     531             : 
     532       20584 :         if (!tevent_req_is_in_progress(req)) {
     533       20545 :                 return tevent_req_post(req, ev);
     534             :         }
     535             : 
     536          39 :         ok = aio_add_req_to_fsp(fsp, req);
     537          39 :         if (!ok) {
     538           0 :                 DBG_ERR("Could not add req to fsp\n");
     539           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     540           0 :                 return tevent_req_post(req, ev);
     541             :         }
     542             : 
     543          39 :         return req;
     544             : }
     545             : 
     546      717470 : static bool smb2_query_directory_next_entry(struct tevent_req *req)
     547             : {
     548      717470 :         struct smbd_smb2_query_directory_state *state = tevent_req_data(
     549             :                 req, struct smbd_smb2_query_directory_state);
     550      717470 :         struct smb_filename *smb_fname = NULL; /* relative to fsp !! */
     551      717470 :         int off = state->out_output_buffer.length;
     552      717470 :         int space_remaining = state->in_output_buffer_length - off;
     553           8 :         struct file_id file_id;
     554           8 :         NTSTATUS status;
     555      717470 :         bool get_dosmode = !state->async_dosmode;
     556      717470 :         bool stop = false;
     557             : 
     558      717470 :         SMB_ASSERT(space_remaining >= 0);
     559             : 
     560      717478 :         status = smbd_dirptr_lanman2_entry(state,
     561      717470 :                                            state->dirfsp->conn,
     562      717470 :                                            state->dirfsp->dptr,
     563      717470 :                                            state->smbreq->flags2,
     564             :                                            state->in_file_name,
     565             :                                            state->dirtype,
     566      717470 :                                            state->info_level,
     567             :                                            false, /* requires_resume_key */
     568      717470 :                                            state->dont_descend,
     569      717470 :                                            state->ask_sharemode,
     570             :                                            get_dosmode,
     571             :                                            8, /* align to 8 bytes */
     572             :                                            false, /* no padding */
     573             :                                            &state->pdata,
     574             :                                            state->base_data,
     575             :                                            state->end_data,
     576             :                                            space_remaining,
     577             :                                            &smb_fname,
     578             :                                            &state->last_entry_off,
     579             :                                            NULL,
     580             :                                            &file_id);
     581             : 
     582      717470 :         off = (int)PTR_DIFF(state->pdata, state->base_data);
     583             : 
     584      717470 :         if (!NT_STATUS_IS_OK(status)) {
     585       20506 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
     586             :                         /*
     587             :                          * Bad character conversion on name. Ignore this
     588             :                          * entry.
     589             :                          */
     590          28 :                         return false;
     591             :                 }
     592             : 
     593       20478 :                 if (state->num > 0) {
     594       11103 :                         goto last_entry_done;
     595             :                 }
     596             : 
     597        9375 :                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
     598           0 :                         tevent_req_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
     599           0 :                         return true;
     600             :                 }
     601             : 
     602        9375 :                 tevent_req_nterror(req, state->empty_status);
     603        9375 :                 return true;
     604             :         }
     605             : 
     606      696964 :         if (state->async_ask_sharemode &&
     607           0 :             !S_ISDIR(smb_fname->st.st_ex_mode))
     608             :         {
     609           0 :                 struct tevent_req *subreq = NULL;
     610           0 :                 char *buf = state->base_data + state->last_entry_off;
     611             : 
     612           0 :                 subreq = fetch_write_time_send(state,
     613             :                                                state->ev,
     614           0 :                                                state->dirfsp->conn,
     615             :                                                file_id,
     616           0 :                                                state->info_level,
     617             :                                                buf,
     618             :                                                &stop);
     619           0 :                 if (tevent_req_nomem(subreq, req)) {
     620           0 :                         return true;
     621             :                 }
     622           0 :                 tevent_req_set_callback(
     623             :                         subreq,
     624             :                         smb2_query_directory_fetch_write_time_done,
     625             :                         req);
     626           0 :                 state->async_sharemode_count++;
     627             :         }
     628             : 
     629      696964 :         if (state->async_dosmode) {
     630       20143 :                 struct tevent_req *subreq = NULL;
     631       20143 :                 uint8_t *buf = NULL;
     632           0 :                 size_t outstanding_aio;
     633             : 
     634       20143 :                 buf = (uint8_t *)state->base_data + state->last_entry_off;
     635             : 
     636       20143 :                 subreq = fetch_dos_mode_send(state,
     637             :                                              state->ev,
     638             :                                              state->dirfsp,
     639             :                                              &smb_fname,
     640             :                                              state->info_level,
     641             :                                              buf);
     642       20143 :                 if (tevent_req_nomem(subreq, req)) {
     643           0 :                         return true;
     644             :                 }
     645       20143 :                 tevent_req_set_callback(subreq,
     646             :                                         smb2_query_directory_dos_mode_done,
     647             :                                         req);
     648             : 
     649       20143 :                 state->async_dosmode_active++;
     650             : 
     651       20143 :                 outstanding_aio = pthreadpool_tevent_queued_jobs(
     652       20143 :                         state->dirfsp->conn->sconn->pool);
     653             : 
     654       20143 :                 if (outstanding_aio > state->max_async_dosmode_active) {
     655           0 :                         stop = true;
     656             :                 }
     657             :         }
     658             : 
     659      696964 :         TALLOC_FREE(smb_fname);
     660             : 
     661      696964 :         state->num++;
     662      696964 :         state->out_output_buffer.length = off;
     663             : 
     664      696964 :         if (!state->done && state->num < state->max_count) {
     665      696858 :                 return stop;
     666             :         }
     667             : 
     668         106 : last_entry_done:
     669       11209 :         SIVAL(state->out_output_buffer.data, state->last_entry_off, 0);
     670             : 
     671       11209 :         state->done = true;
     672             : 
     673       11209 :         if (state->async_sharemode_count > 0) {
     674           0 :                 DBG_DEBUG("Stopping after %"PRIu64" async mtime "
     675             :                           "updates\n", state->async_sharemode_count);
     676           0 :                 return true;
     677             :         }
     678             : 
     679       11209 :         if (state->async_dosmode_active > 0) {
     680          23 :                 return true;
     681             :         }
     682             : 
     683       11186 :         if (state->find_async_delay_usec > 0) {
     684           0 :                 struct timeval tv;
     685          16 :                 struct tevent_req *subreq = NULL;
     686             : 
     687             :                 /*
     688             :                  * Should we only set async_internal
     689             :                  * if we're not the last request in
     690             :                  * a compound chain?
     691             :                  */
     692          16 :                 smb2_request_set_async_internal(state->smb2req, true);
     693             : 
     694          16 :                 tv = timeval_current_ofs(0, state->find_async_delay_usec);
     695             : 
     696          16 :                 subreq = tevent_wakeup_send(state, state->ev, tv);
     697          16 :                 if (tevent_req_nomem(subreq, req)) {
     698           0 :                         return true;
     699             :                 }
     700          16 :                 tevent_req_set_callback(subreq,
     701             :                                         smb2_query_directory_waited,
     702             :                                         req);
     703          16 :                 return true;
     704             :         }
     705             : 
     706       11170 :         tevent_req_done(req);
     707       11170 :         return true;
     708             : }
     709             : 
     710             : static void smb2_query_directory_check_next_entry(struct tevent_req *req);
     711             : 
     712           0 : static void smb2_query_directory_fetch_write_time_done(struct tevent_req *subreq)
     713             : {
     714           0 :         struct tevent_req *req = tevent_req_callback_data(
     715             :                 subreq, struct tevent_req);
     716           0 :         struct smbd_smb2_query_directory_state *state = tevent_req_data(
     717             :                 req, struct smbd_smb2_query_directory_state);
     718           0 :         NTSTATUS status;
     719           0 :         bool ok;
     720             : 
     721             :         /*
     722             :          * Make sure we run as the user again
     723             :          */
     724           0 :         ok = change_to_user_and_service_by_fsp(state->dirfsp);
     725           0 :         SMB_ASSERT(ok);
     726             : 
     727           0 :         state->async_sharemode_count--;
     728             : 
     729           0 :         status = fetch_write_time_recv(subreq);
     730           0 :         TALLOC_FREE(subreq);
     731           0 :         if (tevent_req_nterror(req, status)) {
     732           0 :                 return;
     733             :         }
     734             : 
     735           0 :         smb2_query_directory_check_next_entry(req);
     736           0 :         return;
     737             : }
     738             : 
     739       20143 : static void smb2_query_directory_dos_mode_done(struct tevent_req *subreq)
     740             : {
     741           0 :         struct tevent_req *req =
     742       20143 :                 tevent_req_callback_data(subreq,
     743             :                 struct tevent_req);
     744           0 :         struct smbd_smb2_query_directory_state *state =
     745       20143 :                 tevent_req_data(req,
     746             :                 struct smbd_smb2_query_directory_state);
     747           0 :         NTSTATUS status;
     748           0 :         bool ok;
     749             : 
     750             :         /*
     751             :          * Make sure we run as the user again
     752             :          */
     753       20143 :         ok = change_to_user_and_service_by_fsp(state->dirfsp);
     754       20143 :         SMB_ASSERT(ok);
     755             : 
     756       20143 :         status = fetch_dos_mode_recv(subreq);
     757       20143 :         TALLOC_FREE(subreq);
     758       20143 :         if (tevent_req_nterror(req, status)) {
     759           0 :                 return;
     760             :         }
     761             : 
     762       20143 :         state->async_dosmode_active--;
     763             : 
     764       20143 :         smb2_query_directory_check_next_entry(req);
     765       20143 :         return;
     766             : }
     767             : 
     768       20143 : static void smb2_query_directory_check_next_entry(struct tevent_req *req)
     769             : {
     770       20143 :         struct smbd_smb2_query_directory_state *state = tevent_req_data(
     771             :                 req, struct smbd_smb2_query_directory_state);
     772       20143 :         bool stop = false;
     773             : 
     774       20143 :         if (!state->done) {
     775           0 :                 while (!stop) {
     776           0 :                         stop = smb2_query_directory_next_entry(req);
     777             :                 }
     778           0 :                 return;
     779             :         }
     780             : 
     781       20143 :         if (state->async_sharemode_count > 0 ||
     782       20143 :             state->async_dosmode_active > 0)
     783             :         {
     784       20120 :                 return;
     785             :         }
     786             : 
     787          23 :         if (state->find_async_delay_usec > 0) {
     788           0 :                 struct timeval tv;
     789           0 :                 struct tevent_req *subreq = NULL;
     790             : 
     791           0 :                 tv = timeval_current_ofs(0, state->find_async_delay_usec);
     792             : 
     793           0 :                 subreq = tevent_wakeup_send(state, state->ev, tv);
     794           0 :                 if (tevent_req_nomem(subreq, req)) {
     795           0 :                         tevent_req_post(req, state->ev);
     796           0 :                         return;
     797             :                 }
     798           0 :                 tevent_req_set_callback(subreq,
     799             :                                         smb2_query_directory_waited,
     800             :                                         req);
     801           0 :                 return;
     802             :         }
     803             : 
     804          23 :         tevent_req_done(req);
     805          23 :         return;
     806             : }
     807             : 
     808          16 : static void smb2_query_directory_waited(struct tevent_req *subreq)
     809             : {
     810          16 :         struct tevent_req *req = tevent_req_callback_data(
     811             :                 subreq, struct tevent_req);
     812           0 :         bool ok;
     813             : 
     814          16 :         ok = tevent_wakeup_recv(subreq);
     815          16 :         TALLOC_FREE(subreq);
     816          16 :         if (!ok) {
     817           0 :                 tevent_req_oom(req);
     818           0 :                 return;
     819             :         }
     820          16 :         tevent_req_done(req);
     821             : }
     822             : 
     823       20584 : static NTSTATUS smbd_smb2_query_directory_recv(struct tevent_req *req,
     824             :                                     TALLOC_CTX *mem_ctx,
     825             :                                     DATA_BLOB *out_output_buffer)
     826             : {
     827           2 :         NTSTATUS status;
     828       20584 :         struct smbd_smb2_query_directory_state *state = tevent_req_data(req,
     829             :                                              struct smbd_smb2_query_directory_state);
     830             : 
     831       20584 :         if (tevent_req_is_nterror(req, &status)) {
     832        9375 :                 tevent_req_received(req);
     833        9375 :                 return status;
     834             :         }
     835             : 
     836       11209 :         *out_output_buffer = state->out_output_buffer;
     837       11209 :         talloc_steal(mem_ctx, out_output_buffer->data);
     838             : 
     839       11209 :         tevent_req_received(req);
     840       11209 :         return NT_STATUS_OK;
     841             : }
     842             : 
     843             : struct fetch_write_time_state {
     844             :         connection_struct *conn;
     845             :         struct file_id id;
     846             :         int info_level;
     847             :         char *entry_marshall_buf;
     848             : };
     849             : 
     850             : static void fetch_write_time_done(struct tevent_req *subreq);
     851             : 
     852           0 : static struct tevent_req *fetch_write_time_send(TALLOC_CTX *mem_ctx,
     853             :                                                 struct tevent_context *ev,
     854             :                                                 connection_struct *conn,
     855             :                                                 struct file_id id,
     856             :                                                 int info_level,
     857             :                                                 char *entry_marshall_buf,
     858             :                                                 bool *stop)
     859             : {
     860           0 :         struct tevent_req *req = NULL;
     861           0 :         struct fetch_write_time_state *state = NULL;
     862           0 :         struct tevent_req *subreq = NULL;
     863           0 :         bool req_queued;
     864             : 
     865           0 :         *stop = false;
     866             : 
     867           0 :         req = tevent_req_create(mem_ctx, &state, struct fetch_write_time_state);
     868           0 :         if (req == NULL) {
     869           0 :                 return NULL;
     870             :         }
     871             : 
     872           0 :         *state = (struct fetch_write_time_state) {
     873             :                 .conn = conn,
     874             :                 .id = id,
     875             :                 .info_level = info_level,
     876             :                 .entry_marshall_buf = entry_marshall_buf,
     877             :         };
     878             : 
     879           0 :         subreq = fetch_share_mode_send(state, ev, id, &req_queued);
     880           0 :         if (tevent_req_nomem(subreq, req)) {
     881           0 :                 return tevent_req_post(req, ev);
     882             :         }
     883           0 :         tevent_req_set_callback(subreq, fetch_write_time_done, req);
     884             : 
     885           0 :         if (req_queued) {
     886           0 :                 *stop = true;
     887             :         }
     888           0 :         return req;
     889             : }
     890             : 
     891           0 : static void fetch_write_time_done(struct tevent_req *subreq)
     892             : {
     893           0 :         struct tevent_req *req = tevent_req_callback_data(
     894             :                 subreq, struct tevent_req);
     895           0 :         struct fetch_write_time_state *state = tevent_req_data(
     896             :                 req, struct fetch_write_time_state);
     897           0 :         struct timespec write_time;
     898           0 :         struct share_mode_lock *lck = NULL;
     899           0 :         NTSTATUS status;
     900           0 :         size_t off;
     901             : 
     902           0 :         status = fetch_share_mode_recv(subreq, state, &lck);
     903           0 :         TALLOC_FREE(subreq);
     904           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     905           0 :                 tevent_req_done(req);
     906           0 :                 return;
     907             :         }
     908           0 :         if (tevent_req_nterror(req, status)) {
     909           0 :                 return;
     910             :         }
     911             : 
     912           0 :         write_time = get_share_mode_write_time(lck);
     913           0 :         TALLOC_FREE(lck);
     914             : 
     915           0 :         if (is_omit_timespec(&write_time)) {
     916           0 :                 tevent_req_done(req);
     917           0 :                 return;
     918             :         }
     919             : 
     920           0 :         switch (state->info_level) {
     921           0 :         case SMB_FIND_FILE_DIRECTORY_INFO:
     922             :         case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
     923             :         case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
     924             :         case SMB_FIND_ID_FULL_DIRECTORY_INFO:
     925             :         case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
     926           0 :                 off = 24;
     927           0 :                 break;
     928             : 
     929           0 :         default:
     930           0 :                 DBG_ERR("Unsupported info_level [%d]\n", state->info_level);
     931           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_LEVEL);
     932           0 :                 return;
     933             :         }
     934             : 
     935           0 :         put_long_date_full_timespec(state->conn->ts_res,
     936           0 :                                state->entry_marshall_buf + off,
     937             :                                &write_time);
     938             : 
     939           0 :         tevent_req_done(req);
     940           0 :         return;
     941             : }
     942             : 
     943           0 : static NTSTATUS fetch_write_time_recv(struct tevent_req *req)
     944             : {
     945           0 :         NTSTATUS status;
     946             : 
     947           0 :         if (tevent_req_is_nterror(req, &status)) {
     948           0 :                 tevent_req_received(req);
     949           0 :                 return status;
     950             :         }
     951             : 
     952           0 :         tevent_req_received(req);
     953           0 :         return NT_STATUS_OK;
     954             : }
     955             : 
     956             : struct fetch_dos_mode_state {
     957             :         struct files_struct *dir_fsp;
     958             :         struct smb_filename *smb_fname;
     959             :         uint32_t info_level;
     960             :         uint8_t *entry_marshall_buf;
     961             : };
     962             : 
     963             : static void fetch_dos_mode_done(struct tevent_req *subreq);
     964             : 
     965       20143 : static struct tevent_req *fetch_dos_mode_send(
     966             :                         TALLOC_CTX *mem_ctx,
     967             :                         struct tevent_context *ev,
     968             :                         struct files_struct *dir_fsp,
     969             :                         struct smb_filename **smb_fname,
     970             :                         uint32_t info_level,
     971             :                         uint8_t *entry_marshall_buf)
     972             : {
     973       20143 :         struct tevent_req *req = NULL;
     974       20143 :         struct fetch_dos_mode_state *state = NULL;
     975       20143 :         struct tevent_req *subreq = NULL;
     976             : 
     977       20143 :         req = tevent_req_create(mem_ctx, &state, struct fetch_dos_mode_state);
     978       20143 :         if (req == NULL) {
     979           0 :                 return NULL;
     980             :         }
     981       20143 :         *state = (struct fetch_dos_mode_state) {
     982             :                 .dir_fsp = dir_fsp,
     983             :                 .info_level = info_level,
     984             :                 .entry_marshall_buf = entry_marshall_buf,
     985             :         };
     986             : 
     987       20143 :         state->smb_fname = talloc_move(state, smb_fname);
     988             : 
     989       20143 :         subreq = dos_mode_at_send(state, ev, dir_fsp, state->smb_fname);
     990       20143 :         if (tevent_req_nomem(subreq, req)) {
     991           0 :                 return tevent_req_post(req, ev);
     992             :         }
     993       20143 :         tevent_req_set_callback(subreq, fetch_dos_mode_done, req);
     994             : 
     995       20143 :         return req;
     996             : }
     997             : 
     998       20143 : static void fetch_dos_mode_done(struct tevent_req *subreq)
     999             : {
    1000           0 :         struct tevent_req *req =
    1001       20143 :                 tevent_req_callback_data(subreq,
    1002             :                 struct tevent_req);
    1003           0 :         struct fetch_dos_mode_state *state =
    1004       20143 :                 tevent_req_data(req,
    1005             :                 struct fetch_dos_mode_state);
    1006           0 :         uint32_t dfs_dosmode;
    1007           0 :         uint32_t dosmode;
    1008       20143 :         struct timespec btime_ts = {0};
    1009           0 :         off_t dosmode_off;
    1010           0 :         off_t btime_off;
    1011           0 :         NTSTATUS status;
    1012             : 
    1013       20143 :         status = dos_mode_at_recv(subreq, &dosmode);
    1014       20143 :         TALLOC_FREE(subreq);
    1015       20143 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
    1016           0 :                 tevent_req_done(req);
    1017           0 :                 return;
    1018             :         }
    1019       20143 :         if (tevent_req_nterror(req, status)) {
    1020           0 :                 return;
    1021             :         }
    1022             : 
    1023       20143 :         switch (state->info_level) {
    1024       20143 :         case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    1025             :         case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    1026             :         case SMB_FIND_FILE_DIRECTORY_INFO:
    1027             :         case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    1028             :         case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    1029       20143 :                 btime_off = 8;
    1030       20143 :                 dosmode_off = 56;
    1031       20143 :                 break;
    1032             : 
    1033           0 :         default:
    1034           0 :                 DBG_ERR("Unsupported info_level [%u]\n", state->info_level);
    1035           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_LEVEL);
    1036           0 :                 return;
    1037             :         }
    1038             : 
    1039             : 
    1040       20143 :         dfs_dosmode = IVAL(state->entry_marshall_buf, dosmode_off);
    1041       20143 :         if (dfs_dosmode == 0) {
    1042             :                 /*
    1043             :                  * DOS mode for a DFS link, only overwrite if still set to 0 and
    1044             :                  * not already populated by the lower layer for a DFS link in
    1045             :                  * smbd_dirptr_lanman2_mode_fn().
    1046             :                  */
    1047       20143 :                 SIVAL(state->entry_marshall_buf, dosmode_off, dosmode);
    1048             :         }
    1049             : 
    1050       20143 :         btime_ts = get_create_timespec(state->dir_fsp->conn,
    1051             :                                        NULL,
    1052       20143 :                                        state->smb_fname);
    1053       20143 :         if (lp_dos_filetime_resolution(SNUM(state->dir_fsp->conn))) {
    1054           0 :                 dos_filetime_timespec(&btime_ts);
    1055             :         }
    1056             : 
    1057       20143 :         put_long_date_full_timespec(state->dir_fsp->conn->ts_res,
    1058       20143 :                                (char *)state->entry_marshall_buf + btime_off,
    1059             :                                &btime_ts);
    1060             : 
    1061       20143 :         tevent_req_done(req);
    1062       20143 :         return;
    1063             : }
    1064             : 
    1065       20143 : static NTSTATUS fetch_dos_mode_recv(struct tevent_req *req)
    1066             : {
    1067           0 :         NTSTATUS status;
    1068             : 
    1069       20143 :         if (tevent_req_is_nterror(req, &status)) {
    1070           0 :                 tevent_req_received(req);
    1071           0 :                 return status;
    1072             :         }
    1073             : 
    1074       20143 :         tevent_req_received(req);
    1075       20143 :         return NT_STATUS_OK;
    1076             : }

Generated by: LCOV version 1.14