summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/client/client.c118
-rw-r--r--source3/client/client_proto.h2
-rw-r--r--source3/client/clitar.c4
3 files changed, 119 insertions, 5 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 47d44705d2..ed95fdf160 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -301,6 +301,118 @@ static void send_message(const char *username)
}
/****************************************************************************
+ Wrapper function around cli_open() that does an NtCreateX open by preference.
+****************************************************************************/
+
+NTSTATUS smbclient_cli_open(struct cli_state *cli, const char *fname, int flags,
+ int share_mode_in, uint16_t *pfnum)
+{
+ NTSTATUS status;
+ unsigned int openfn = 0;
+ unsigned int dos_deny = 0;
+ uint32_t access_mask, share_mode, create_disposition, create_options;
+
+ /* Do the initial mapping into OpenX parameters. */
+ if (flags & O_CREAT) {
+ openfn |= (1<<4);
+ }
+ if (!(flags & O_EXCL)) {
+ if (flags & O_TRUNC)
+ openfn |= (1<<1);
+ else
+ openfn |= (1<<0);
+ }
+
+ dos_deny = (share_mode_in<<4);
+
+ if ((flags & O_ACCMODE) == O_RDWR) {
+ dos_deny |= 2;
+ } else if ((flags & O_ACCMODE) == O_WRONLY) {
+ dos_deny |= 1;
+ }
+
+#if defined(O_SYNC)
+ if ((flags & O_SYNC) == O_SYNC) {
+ dos_deny |= (1<<14);
+ }
+#endif /* O_SYNC */
+
+ if (share_mode_in == DENY_FCB) {
+ dos_deny = 0xFF;
+ }
+
+#if 0
+ /* Hmmm. This is what I think the above code
+ should look like if it's using the constants
+ we #define. JRA. */
+
+ if (flags & O_CREAT) {
+ openfn |= OPENX_FILE_CREATE_IF_NOT_EXIST;
+ }
+ if (!(flags & O_EXCL)) {
+ if (flags & O_TRUNC)
+ openfn |= OPENX_FILE_EXISTS_TRUNCATE;
+ else
+ openfn |= OPENX_FILE_EXISTS_OPEN;
+ }
+
+ dos_deny = SET_DENY_MODE(share_mode_in);
+
+ if ((flags & O_ACCMODE) == O_RDWR) {
+ dos_deny |= DOS_OPEN_RDWR;
+ } else if ((flags & O_ACCMODE) == O_WRONLY) {
+ dos_deny |= DOS_OPEN_WRONLY;
+ }
+
+#if defined(O_SYNC)
+ if ((flags & O_SYNC) == O_SYNC) {
+ dos_deny |= FILE_SYNC_OPENMODE;
+ }
+#endif /* O_SYNC */
+
+ if (share_mode_in == DENY_FCB) {
+ dos_deny = 0xFF;
+ }
+#endif
+
+ if (!map_open_params_to_ntcreate(fname, dos_deny,
+ openfn, &access_mask,
+ &share_mode, &create_disposition,
+ &create_options, NULL)) {
+ goto try_openx;
+ }
+
+ status = cli_ntcreate(cli,
+ fname,
+ 0,
+ access_mask,
+ 0,
+ share_mode,
+ create_disposition,
+ create_options,
+ 0,
+ pfnum);
+
+ /* Try and cope will all varients of "we don't do this call"
+ and fall back to openX. */
+
+ if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
+ goto try_openx;
+ }
+
+ return status;
+
+ try_openx:
+
+ return cli_open(cli, fname, flags, share_mode_in, pfnum);
+}
+
+/****************************************************************************
Check the space on a device.
****************************************************************************/
@@ -1097,7 +1209,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
clock_gettime_mono(&tp_start);
- status = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE, &fnum);
+ status = smbclient_cli_open(targetcli, targetname, O_RDONLY, DENY_NONE, &fnum);
if (!NT_STATUS_IS_OK(status)) {
d_printf("%s opening remote file %s\n", nt_errstr(status),
rname);
@@ -1856,7 +1968,7 @@ static int do_put(const char *rname, const char *lname, bool reput)
clock_gettime_mono(&tp_start);
if (reput) {
- status = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
+ status = smbclient_cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
if (NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_IS_OK(status = cli_qfileinfo_basic(
targetcli, fnum, NULL,
@@ -1871,7 +1983,7 @@ static int do_put(const char *rname, const char *lname, bool reput)
}
}
} else {
- status = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
+ status = smbclient_cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
}
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/client/client_proto.h b/source3/client/client_proto.h
index d119014abd..3032e5b7ae 100644
--- a/source3/client/client_proto.h
+++ b/source3/client/client_proto.h
@@ -30,6 +30,8 @@ struct file_info;
const char *client_get_cur_dir(void);
const char *client_set_cur_dir(const char *newdir);
+NTSTATUS smbclient_cli_open(struct cli_state *cli, const char *fname, int flags,
+ int share_mode_in, uint16_t *pfnum);
NTSTATUS do_list(const char *mask,
uint16 attribute,
NTSTATUS (*fn)(struct cli_state *cli_state, struct file_info *,
diff --git a/source3/client/clitar.c b/source3/client/clitar.c
index 594392672a..d8890eae3b 100644
--- a/source3/client/clitar.c
+++ b/source3/client/clitar.c
@@ -655,7 +655,7 @@ static NTSTATUS do_atar(const char *rname_in, char *lname,
goto cleanup;
}
- status = cli_open(cli, rname, O_RDONLY, DENY_NONE, &fnum);
+ status = smbclient_cli_open(cli, rname, O_RDONLY, DENY_NONE, &fnum);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("%s opening remote file %s (%s)\n",
nt_errstr(status),rname, client_get_cur_dir()));
@@ -1016,7 +1016,7 @@ static int get_file(file_info2 finfo)
return False;
}
- status = cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
+ status = smbclient_cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("abandoning restore\n"));
return False;