mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
s3: Add a fallback for missing open&x support in OS/X Lion
Autobuild-User: Volker Lendecke <vlendec@samba.org> Autobuild-Date: Fri Jul 29 17:55:20 CEST 2011 on sn-devel-104
This commit is contained in:
parent
190b5432f0
commit
fac5c654e2
@ -2110,12 +2110,19 @@ NTSTATUS cli_nttrans_create(struct cli_state *cli,
|
||||
****************************************************************************/
|
||||
|
||||
struct cli_open_state {
|
||||
struct tevent_context *ev;
|
||||
struct cli_state *cli;
|
||||
const char *fname;
|
||||
uint16_t vwv[15];
|
||||
uint16_t fnum;
|
||||
unsigned openfn;
|
||||
unsigned dos_deny;
|
||||
uint8_t additional_flags;
|
||||
struct iovec bytes;
|
||||
};
|
||||
|
||||
static void cli_open_done(struct tevent_req *subreq);
|
||||
static void cli_open_ntcreate_done(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
|
||||
struct event_context *ev,
|
||||
@ -2125,64 +2132,61 @@ struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
struct tevent_req *req, *subreq;
|
||||
struct cli_open_state *state;
|
||||
unsigned openfn;
|
||||
unsigned accessmode;
|
||||
uint8_t additional_flags;
|
||||
uint8_t *bytes;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->ev = ev;
|
||||
state->cli = cli;
|
||||
state->fname = fname;
|
||||
|
||||
openfn = 0;
|
||||
if (flags & O_CREAT) {
|
||||
openfn |= (1<<4);
|
||||
state->openfn |= (1<<4);
|
||||
}
|
||||
if (!(flags & O_EXCL)) {
|
||||
if (flags & O_TRUNC)
|
||||
openfn |= (1<<1);
|
||||
state->openfn |= (1<<1);
|
||||
else
|
||||
openfn |= (1<<0);
|
||||
state->openfn |= (1<<0);
|
||||
}
|
||||
|
||||
accessmode = (share_mode<<4);
|
||||
state->dos_deny = (share_mode<<4);
|
||||
|
||||
if ((flags & O_ACCMODE) == O_RDWR) {
|
||||
accessmode |= 2;
|
||||
state->dos_deny |= 2;
|
||||
} else if ((flags & O_ACCMODE) == O_WRONLY) {
|
||||
accessmode |= 1;
|
||||
state->dos_deny |= 1;
|
||||
}
|
||||
|
||||
#if defined(O_SYNC)
|
||||
if ((flags & O_SYNC) == O_SYNC) {
|
||||
accessmode |= (1<<14);
|
||||
state->dos_deny |= (1<<14);
|
||||
}
|
||||
#endif /* O_SYNC */
|
||||
|
||||
if (share_mode == DENY_FCB) {
|
||||
accessmode = 0xFF;
|
||||
state->dos_deny = 0xFF;
|
||||
}
|
||||
|
||||
SCVAL(state->vwv + 0, 0, 0xFF);
|
||||
SCVAL(state->vwv + 0, 1, 0);
|
||||
SSVAL(state->vwv + 1, 0, 0);
|
||||
SSVAL(state->vwv + 2, 0, 0); /* no additional info */
|
||||
SSVAL(state->vwv + 3, 0, accessmode);
|
||||
SSVAL(state->vwv + 3, 0, state->dos_deny);
|
||||
SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
|
||||
SSVAL(state->vwv + 5, 0, 0);
|
||||
SIVAL(state->vwv + 6, 0, 0);
|
||||
SSVAL(state->vwv + 8, 0, openfn);
|
||||
SSVAL(state->vwv + 8, 0, state->openfn);
|
||||
SIVAL(state->vwv + 9, 0, 0);
|
||||
SIVAL(state->vwv + 11, 0, 0);
|
||||
SIVAL(state->vwv + 13, 0, 0);
|
||||
|
||||
additional_flags = 0;
|
||||
|
||||
if (cli->use_oplocks) {
|
||||
/* if using oplocks then ask for a batch oplock via
|
||||
core and extended methods */
|
||||
additional_flags =
|
||||
state->additional_flags =
|
||||
FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
|
||||
SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
|
||||
}
|
||||
@ -2198,7 +2202,8 @@ struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
|
||||
state->bytes.iov_base = (void *)bytes;
|
||||
state->bytes.iov_len = talloc_get_size(bytes);
|
||||
|
||||
subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
|
||||
subreq = cli_smb_req_create(state, ev, cli, SMBopenX,
|
||||
state->additional_flags,
|
||||
15, state->vwv, 1, &state->bytes);
|
||||
if (subreq == NULL) {
|
||||
TALLOC_FREE(req);
|
||||
@ -2239,14 +2244,58 @@ static void cli_open_done(struct tevent_req *subreq)
|
||||
uint16_t *vwv;
|
||||
uint8_t *inbuf;
|
||||
NTSTATUS status;
|
||||
uint32_t access_mask, share_mode, create_disposition, create_options;
|
||||
|
||||
status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv, NULL,
|
||||
NULL);
|
||||
TALLOC_FREE(subreq);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
state->fnum = SVAL(vwv+2, 0);
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the new shiny OS/X Lion SMB server, try a ntcreate
|
||||
* fallback.
|
||||
*/
|
||||
|
||||
if (!map_open_params_to_ntcreate(state->fname, state->dos_deny,
|
||||
state->openfn, &access_mask,
|
||||
&share_mode, &create_disposition,
|
||||
&create_options, NULL)) {
|
||||
tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
subreq = cli_ntcreate_send(state, state->ev, state->cli,
|
||||
state->fname, 0, access_mask,
|
||||
0, share_mode, create_disposition,
|
||||
create_options, 0);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq, cli_open_ntcreate_done, req);
|
||||
}
|
||||
|
||||
static void cli_open_ntcreate_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct cli_open_state *state = tevent_req_data(
|
||||
req, struct cli_open_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = cli_ntcreate_recv(subreq, &state->fnum);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
state->fnum = SVAL(vwv+2, 0);
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user