From: Volker Lendecke Date: Wed, 3 May 2023 14:44:34 +0000 (+0200) Subject: libsmb: Retry the open with OPEN_REPARSE_POINT on IO_REPARSE_TAG_NOT_HANDLED X-Git-Tag: tdb-1.4.13~488 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=61259bf9aabfa1d207b3d4bfeac0860f54f5cd4d;p=thirdparty%2Fsamba.git libsmb: Retry the open with OPEN_REPARSE_POINT on IO_REPARSE_TAG_NOT_HANDLED If we get that error message, we want to look at the reparse point as such. This does not affect normal files, but soon we will need it in our tests. Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme --- diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index 95b4385bc9f..f9a82089709 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -204,7 +204,16 @@ static char *smb2_dfs_share_path(TALLOC_CTX *ctx, ***************************************************************/ struct cli_smb2_create_fnum_state { + struct tevent_context *ev; struct cli_state *cli; + char *fname; + struct cli_smb2_create_flags create_flags; + uint32_t impersonation_level; + uint32_t desired_access; + uint32_t file_attributes; + uint32_t share_access; + uint32_t create_disposition; + uint32_t create_options; struct smb2_create_blobs in_cblobs; struct smb2_create_blobs out_cblobs; struct smb_create_returns cr; @@ -243,17 +252,25 @@ struct tevent_req *cli_smb2_create_fnum_send( if (req == NULL) { return NULL; } + state->ev = ev; state->cli = cli; + state->create_flags = create_flags; + state->impersonation_level = impersonation_level; + state->desired_access = desired_access; + state->file_attributes = file_attributes; + state->share_access = share_access; + state->create_disposition = create_disposition; + + if (cli->backup_intent) { + create_options |= FILE_OPEN_FOR_BACKUP_INTENT; + } + state->create_options = create_options; fname = talloc_strdup(state, fname_in); if (tevent_req_nomem(fname, req)) { return tevent_req_post(req, ev); } - if (cli->backup_intent) { - create_options |= FILE_OPEN_FOR_BACKUP_INTENT; - } - if (cli->smb2.client_smb311_posix) { uint8_t modebuf[4] = { 0, @@ -316,15 +333,21 @@ struct tevent_req *cli_smb2_create_fnum_send( /* Or end in a '\' */ if (fname_len > 0 && fname[fname_len-1] == '\\') { - fname[fname_len-1] = '\0'; + fname_len -= 1; } - subreq = smb2cli_create_send(state, ev, + state->fname = talloc_strndup(state, fname, fname_len); + if (tevent_req_nomem(state->fname, req)) { + return tevent_req_post(req, ev); + } + + subreq = smb2cli_create_send(state, + ev, cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon, - fname, + state->fname, flags_to_smb2_oplock(create_flags), impersonation_level, desired_access, @@ -352,6 +375,7 @@ static void cli_smb2_create_fnum_done(struct tevent_req *subreq) req, struct cli_smb2_create_fnum_state); uint64_t fid_persistent, fid_volatile; struct smb2_create_blob *posix = NULL; + struct cli_state *cli = state->cli; NTSTATUS status; status = smb2cli_create_recv(subreq, @@ -362,6 +386,46 @@ static void cli_smb2_create_fnum_done(struct tevent_req *subreq) &state->out_cblobs, &state->symlink); TALLOC_FREE(subreq); + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED)) { + + if (state->create_options & FILE_OPEN_REPARSE_POINT) { + /* + * Should not happen, but you never know... + */ + tevent_req_nterror( + req, NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED); + return; + } + + state->create_options |= FILE_OPEN_REPARSE_POINT; + + subreq = smb2cli_create_send(state, + state->ev, + cli->conn, + cli->timeout, + cli->smb2.session, + cli->smb2.tcon, + state->fname, + flags_to_smb2_oplock( + state->create_flags), + state->impersonation_level, + state->desired_access, + state->file_attributes, + state->share_access, + state->create_disposition, + state->create_options, + &state->in_cblobs); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, + cli_smb2_create_fnum_done, + req); + state->subreq = subreq; + return; + } + if (tevent_req_nterror(req, status)) { return; }