Convert smbclient to using NtCreateX by preference, fall back to openX on
authorJeremy Allison <jra@samba.org>
Fri, 2 Dec 2011 18:11:17 +0000 (10:11 -0800)
committerJeremy Allison <jra@samba.org>
Fri, 2 Dec 2011 19:41:02 +0000 (20:41 +0100)
'not implemented' or similar error.

source3/client/client.c
source3/client/client_proto.h
source3/client/clitar.c

index 47d44705d2d80d9758703168e68fad53af9e2727..ed95fdf16083559cfdb6db78304de9e85e992ab3 100644 (file)
@@ -300,6 +300,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)) {
index d119014abdc79372232fa6ff47fa2269513b5a0b..3032e5b7aef699e1add41bb3a3ac0a1fd01d3e2c 100644 (file)
@@ -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 *,
index 594392672a6f876b417ec0390c622684725e2c01..d8890eae3bbedc3c477be523ac228b2ef9cbb742 100644 (file)
@@ -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;