2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Simo Sorce 2001-2002
6 Copyright (C) Jelmer Vernooij 2003
7 Copyright (C) Gerald (Jerry) Carter 2004
8 Copyright (C) Jeremy Allison 1994-2007
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "system/filesys.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "client/client_proto.h"
28 #include "client/clitar_proto.h"
29 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
30 #include "../lib/util/select.h"
31 #include "system/readline.h"
32 #include "../libcli/smbreadline/smbreadline.h"
33 #include "../libcli/security/security.h"
34 #include "system/select.h"
35 #include "libsmb/libsmb.h"
36 #include "libsmb/clirap.h"
38 #include "libsmb/nmblib.h"
39 #include "include/ntioctl.h"
40 #include "../libcli/smb/smbXcli_base.h"
41 #include "lib/util/time_basic.h"
42 #include "lib/util/string_wrappers.h"
43 #include "lib/cmdline/cmdline.h"
49 extern int do_smb_browse(void); /* mDNS browsing */
53 static char *desthost
;
54 static bool grepable
= false;
55 static bool quiet
= false;
56 static char *cmdstr
= NULL
;
57 const char *cmd_ptr
= NULL
;
59 static int io_bufsize
= 0; /* we use the default size */
60 static int io_timeout
= (CLIENT_TIMEOUT
/1000); /* Per operation timeout (in seconds). */
62 static int name_type
= 0x20;
64 static int process_tok(char *tok
);
65 static int cmd_help(void);
67 /* value for unused fid field in trans2 secondary request */
68 #define FID_UNUSED (0xFFFF)
70 time_t newer_than
= 0;
71 static int archive_level
= 0;
73 static bool translation
= false;
76 static bool prompt
= true;
78 static bool recurse
= false;
79 static bool showacls
= false;
80 bool lowercase
= false;
81 static bool backup_intent
= false;
83 static struct sockaddr_storage dest_ss
;
84 static char dest_ss_str
[INET6_ADDRSTRLEN
];
86 #define SEPARATORS " \t\n\r"
89 uint64_t get_total_size
= 0;
90 unsigned int get_total_time_ms
= 0;
91 static uint64_t put_total_size
= 0;
92 static unsigned int put_total_time_ms
= 0;
95 static double dir_total
;
97 /* root cli_state connection */
99 struct cli_state
*cli
;
101 static char CLI_DIRSEP_CHAR
= '\\';
102 static char CLI_DIRSEP_STR
[] = { '\\', '\0' };
104 /* Accessor functions for directory paths. */
105 static char *fileselection
;
106 static const char *client_get_fileselection(void)
109 return fileselection
;
114 static const char *client_set_fileselection(const char *new_fs
)
116 SAFE_FREE(fileselection
);
118 fileselection
= SMB_STRDUP(new_fs
);
120 return client_get_fileselection();
124 static const char *client_get_cwd(void)
129 return CLI_DIRSEP_STR
;
132 static const char *client_set_cwd(const char *new_cwd
)
136 cwd
= SMB_STRDUP(new_cwd
);
138 return client_get_cwd();
141 static char *cur_dir
;
142 const char *client_get_cur_dir(void)
147 return CLI_DIRSEP_STR
;
150 const char *client_set_cur_dir(const char *newdir
)
154 cur_dir
= SMB_STRDUP(newdir
);
156 return client_get_cur_dir();
159 /****************************************************************************
160 Put up a yes/no prompt.
161 ****************************************************************************/
163 static bool yesno(const char *p
)
168 if (!fgets(ans
,sizeof(ans
)-1,stdin
))
171 if (*ans
== 'y' || *ans
== 'Y')
177 /****************************************************************************
178 Write to a local file with CR/LF->LF translation if appropriate. Return the
179 number taken from the buffer. This may not equal the number written.
180 ****************************************************************************/
182 static ssize_t
writefile(int f
, char *b
, size_t n
)
196 if (*b
== '\r' && (i
<(n
-1)) && *(b
+1) == '\n') {
199 if (write(f
, b
, 1) != 1) {
209 /****************************************************************************
210 Read from a file with LF->CR/LF translation if appropriate. Return the
211 number read. read approx n bytes.
212 ****************************************************************************/
214 static int readfile(uint8_t *b
, int n
, FILE *f
)
220 return fread(b
,1,n
,f
);
223 while (i
< (n
- 1)) {
224 if ((c
= getc(f
)) == EOF
) {
228 if (c
== '\n') { /* change all LFs to CR/LF */
243 static size_t push_source(uint8_t *buf
, size_t n
, void *priv
)
245 struct push_state
*state
= (struct push_state
*)priv
;
248 if (feof(state
->f
)) {
252 result
= readfile(buf
, n
, state
->f
);
253 state
->nread
+= result
;
257 /****************************************************************************
259 ****************************************************************************/
261 static void send_message(const char *username
)
267 d_printf("Type your message, ending it with a Control-D\n");
270 while (i
<sizeof(buf
)-2) {
271 int c
= fgetc(stdin
);
282 status
= cli_message(cli
, desthost
, username
, buf
);
283 if (!NT_STATUS_IS_OK(status
)) {
284 d_fprintf(stderr
, "cli_message returned %s\n",
289 /****************************************************************************
290 Check the space on a device.
291 ****************************************************************************/
293 static int do_dskattr(void)
295 uint64_t total
, bsize
, avail
;
296 struct cli_state
*targetcli
= NULL
;
297 char *targetpath
= NULL
;
298 TALLOC_CTX
*ctx
= talloc_tos();
299 struct cli_credentials
*creds
= samba_cmdline_get_creds();
302 status
= cli_resolve_path(ctx
,
306 client_get_cur_dir(), &targetcli
,
308 if (!NT_STATUS_IS_OK(status
)) {
309 d_printf("Error in dskattr: %s\n", nt_errstr(status
));
313 status
= cli_disk_size(targetcli
, targetpath
, &bsize
, &total
, &avail
);
314 if (!NT_STATUS_IS_OK(status
)) {
315 d_printf("Error in dskattr: %s\n", nt_errstr(status
));
319 d_printf("\n\t\t%" PRIu64
320 " blocks of size %" PRIu64
321 ". %" PRIu64
" blocks available\n",
322 total
, bsize
, avail
);
327 /****************************************************************************
329 ****************************************************************************/
331 static int cmd_pwd(void)
333 d_printf("Current directory is %s",service
);
334 d_printf("%s\n",client_get_cur_dir());
338 /****************************************************************************
339 Ensure name has correct directory separators.
340 ****************************************************************************/
342 static void normalize_name(char *newdir
)
344 if (!(cli
->requested_posix_capabilities
& CIFS_UNIX_POSIX_PATHNAMES_CAP
)) {
345 string_replace(newdir
,'/','\\');
349 /****************************************************************************
350 Local name cleanup before sending to server. SMB1 allows relative pathnames,
351 but SMB2 does not, so we need to resolve them locally.
352 ****************************************************************************/
354 char *client_clean_name(TALLOC_CTX
*ctx
, const char *name
)
356 char *newname
= NULL
;
361 /* First ensure any path separators are correct. */
362 newname
= talloc_strdup(ctx
, name
);
363 if (newname
== NULL
) {
366 normalize_name(newname
);
368 /* Now remove any relative (..) path components. */
369 if (cli
->requested_posix_capabilities
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
370 newname
= unix_clean_name(ctx
, newname
);
372 newname
= clean_name(ctx
, newname
);
374 if (newname
== NULL
) {
380 /****************************************************************************
381 Change directory - inner section.
382 ****************************************************************************/
384 static int do_cd(const char *new_dir
)
387 char *saved_dir
= NULL
;
389 char *targetpath
= NULL
;
390 struct cli_state
*targetcli
= NULL
;
392 TALLOC_CTX
*ctx
= talloc_stackframe();
393 struct cli_credentials
*creds
= samba_cmdline_get_creds();
396 newdir
= talloc_strdup(ctx
, new_dir
);
402 normalize_name(newdir
);
404 /* Save the current directory in case the new directory is invalid */
406 saved_dir
= talloc_strdup(ctx
, client_get_cur_dir());
412 if (*newdir
== CLI_DIRSEP_CHAR
) {
413 client_set_cur_dir(newdir
);
416 new_cd
= talloc_asprintf(ctx
, "%s%s",
417 client_get_cur_dir(),
424 /* Ensure cur_dir ends in a DIRSEP */
425 if ((new_cd
[0] != '\0') && (*(new_cd
+strlen(new_cd
)-1) != CLI_DIRSEP_CHAR
)) {
426 new_cd
= talloc_asprintf_append(new_cd
, "%s", CLI_DIRSEP_STR
);
431 client_set_cur_dir(new_cd
);
433 new_cd
= client_clean_name(ctx
, new_cd
);
434 client_set_cur_dir(new_cd
);
436 status
= cli_resolve_path(ctx
, "",
438 cli
, new_cd
, &targetcli
, &targetpath
);
439 if (!NT_STATUS_IS_OK(status
)) {
440 d_printf("cd %s: %s\n", new_cd
, nt_errstr(status
));
441 client_set_cur_dir(saved_dir
);
445 if (strequal(targetpath
,CLI_DIRSEP_STR
)) {
451 targetpath
= talloc_asprintf(
452 ctx
, "%s%s", targetpath
, CLI_DIRSEP_STR
);
454 client_set_cur_dir(saved_dir
);
457 targetpath
= client_clean_name(ctx
, targetpath
);
459 client_set_cur_dir(saved_dir
);
463 status
= cli_chkpath(targetcli
, targetpath
);
464 if (!NT_STATUS_IS_OK(status
)) {
465 d_printf("cd %s: %s\n", new_cd
, nt_errstr(status
));
466 client_set_cur_dir(saved_dir
);
478 /****************************************************************************
480 ****************************************************************************/
482 static int cmd_cd(void)
487 if (next_token_talloc(talloc_tos(), &cmd_ptr
, &buf
,NULL
)) {
490 d_printf("Current directory is %s\n",client_get_cur_dir());
496 /****************************************************************************
498 ****************************************************************************/
500 static int cmd_cd_oneup(void)
505 /*******************************************************************
506 Decide if a file should be operated on.
507 ********************************************************************/
509 static bool do_this_one(struct file_info
*finfo
)
515 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
519 if (*client_get_fileselection() &&
520 !mask_match(finfo
->name
,client_get_fileselection(),false)) {
521 DEBUG(3,("mask_match %s failed\n", finfo
->name
));
525 if (newer_than
&& finfo
->mtime_ts
.tv_sec
< newer_than
) {
526 DEBUG(3,("newer_than %s failed\n", finfo
->name
));
530 if ((archive_level
==1 || archive_level
==2) && !(finfo
->attr
& FILE_ATTRIBUTE_ARCHIVE
)) {
531 DEBUG(3,("archive %s failed\n", finfo
->name
));
538 /****************************************************************************
539 Display info about a file.
540 ****************************************************************************/
542 static NTSTATUS
display_finfo(struct cli_state
*cli_state
, struct file_info
*finfo
,
546 TALLOC_CTX
*ctx
= talloc_tos();
547 NTSTATUS status
= NT_STATUS_OK
;
549 if (!do_this_one(finfo
)) {
553 t
= finfo
->mtime_ts
.tv_sec
; /* the time is assumed to be passed as GMT */
555 d_printf(" %-30s%7.7s %8.0f %s",
557 attrib_string(talloc_tos(), finfo
->attr
),
560 dir_total
+= finfo
->size
;
562 struct cli_state
*targetcli
= NULL
;
563 char *targetpath
= NULL
;
566 struct cli_credentials
*creds
= samba_cmdline_get_creds();
568 if (ISDOT(finfo
->name
) || ISDOTDOT(finfo
->name
)) {
571 /* create absolute filename for cli_ntcreate() FIXME */
572 afname
= talloc_asprintf(ctx
,
578 return NT_STATUS_NO_MEMORY
;
580 /* print file meta date header */
581 d_printf( "FILENAME:%s\n", finfo
->name
);
582 d_printf( "MODE:%s\n", attrib_string(talloc_tos(), finfo
->attr
));
583 d_printf( "SIZE:%.0f\n", (double)finfo
->size
);
584 d_printf( "MTIME:%s", time_to_asc(t
));
586 status
= cli_resolve_path(
594 if (!NT_STATUS_IS_OK(status
)) {
595 DBG_WARNING("display_finfo() Failed to resolve "
597 afname
, nt_errstr(status
));
601 status
= cli_ntcreate(
603 targetpath
, /* fname */
605 READ_CONTROL_ACCESS
, /* DesiredAccess */
606 0, /* FileAttributes */
608 FILE_SHARE_WRITE
, /* ShareAccess */
609 FILE_OPEN
, /* CreateDisposition */
610 0x0, /* CreateOptions */
611 0x0, /* SecurityFlags */
614 if (!NT_STATUS_IS_OK(status
)) {
615 DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
616 afname
, nt_errstr(status
)));
618 struct security_descriptor
*sd
= NULL
;
619 status
= cli_query_secdesc(targetcli
, fnum
,
621 if (!NT_STATUS_IS_OK(status
)) {
622 DEBUG( 0, ("display_finfo() failed to "
623 "get security descriptor: %s",
626 display_sec_desc(sd
);
635 /****************************************************************************
636 Accumulate size of a file.
637 ****************************************************************************/
639 static NTSTATUS
do_du(struct cli_state
*cli_state
, struct file_info
*finfo
,
642 if (do_this_one(finfo
)) {
643 dir_total
+= finfo
->size
;
648 struct do_list_queue_entry
{
649 struct do_list_queue_entry
*prev
, *next
;
653 struct do_list_queue
{
654 struct do_list_queue_entry
*list
;
657 static bool do_list_recurse
;
658 static bool do_list_dirs
;
659 static struct do_list_queue
*queue
= NULL
;
660 static NTSTATUS (*do_list_fn
)(struct cli_state
*cli_state
, struct file_info
*,
663 /****************************************************************************
664 Functions for do_list_queue.
665 ****************************************************************************/
667 static void reset_do_list_queue(void)
672 static void init_do_list_queue(void)
675 queue
= talloc_zero(NULL
, struct do_list_queue
);
678 static void add_to_do_list_queue(const char *entry
)
680 struct do_list_queue_entry
*e
= NULL
;
681 size_t entry_str_len
= strlen(entry
)+1;
682 size_t entry_len
= offsetof(struct do_list_queue_entry
, name
);
684 entry_len
+= entry_str_len
;
685 SMB_ASSERT(entry_len
>= entry_str_len
);
687 e
= talloc_size(queue
, entry_len
);
689 d_printf("talloc failed for entry %s\n", entry
);
692 talloc_set_name_const(e
, "struct do_list_queue_entry");
694 memcpy(e
->name
, entry
, entry_str_len
);
695 DLIST_ADD_END(queue
->list
, e
);
698 static char *do_list_queue_head(void)
700 return queue
->list
->name
;
703 static void remove_do_list_queue_head(void)
705 struct do_list_queue_entry
*e
= queue
->list
;
706 DLIST_REMOVE(queue
->list
, e
);
710 static int do_list_queue_empty(void)
712 return (queue
== NULL
) || (queue
->list
== NULL
);
715 /****************************************************************************
716 A helper for do_list.
717 ****************************************************************************/
719 struct do_list_helper_state
{
721 struct cli_state
*cli
;
724 static NTSTATUS
do_list_helper(
729 struct do_list_helper_state
*state
= private_data
;
730 TALLOC_CTX
*ctx
= talloc_tos();
732 char *dir_end
= NULL
;
733 NTSTATUS status
= NT_STATUS_OK
;
736 /* Work out the directory. */
737 dir
= talloc_strdup(ctx
, state
->mask
);
739 return NT_STATUS_NO_MEMORY
;
741 if ((dir_end
= strrchr(dir
, CLI_DIRSEP_CHAR
)) != NULL
) {
745 if (!(f
->attr
& FILE_ATTRIBUTE_DIRECTORY
)) {
746 if (do_this_one(f
)) {
747 status
= do_list_fn(state
->cli
, f
, dir
);
753 if (do_list_dirs
&& do_this_one(f
)) {
754 status
= do_list_fn(state
->cli
, f
, dir
);
755 if (!NT_STATUS_IS_OK(status
)) {
760 if (!do_list_recurse
||
768 d_printf("Empty dir name returned. Possible server misconfiguration.\n");
770 return NT_STATUS_UNSUCCESSFUL
;
773 mask2
= talloc_asprintf(ctx
,
781 return NT_STATUS_NO_MEMORY
;
783 add_to_do_list_queue(mask2
);
790 /****************************************************************************
791 A wrapper around cli_list that adds recursion.
792 ****************************************************************************/
794 NTSTATUS
do_list(const char *mask
,
796 NTSTATUS (*fn
)(struct cli_state
*cli_state
, struct file_info
*,
801 struct do_list_helper_state state
= { .cli
= cli
, };
802 static int in_do_list
= 0;
803 TALLOC_CTX
*ctx
= talloc_tos();
804 struct cli_credentials
*creds
= samba_cmdline_get_creds();
805 NTSTATUS ret_status
= NT_STATUS_OK
;
806 NTSTATUS status
= NT_STATUS_OK
;
808 if (in_do_list
&& rec
) {
809 fprintf(stderr
, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
815 do_list_recurse
= rec
;
819 init_do_list_queue();
820 add_to_do_list_queue(mask
);
822 while (!do_list_queue_empty()) {
823 struct cli_state
*targetcli
= NULL
;
824 char *targetpath
= NULL
;
826 state
.mask
= do_list_queue_head();
830 status
= cli_resolve_path(
838 if (!NT_STATUS_IS_OK(status
)) {
839 d_printf("do_list: [%s] %s\n", state
.mask
,
841 remove_do_list_queue_head();
851 if (!NT_STATUS_IS_OK(status
)) {
852 d_printf("%s listing %s\n",
853 nt_errstr(status
), targetpath
);
856 remove_do_list_queue_head();
857 if ((! do_list_queue_empty()) && (fn
== display_finfo
)) {
858 char *next_file
= do_list_queue_head();
860 if ((strlen(next_file
) >= 2) &&
861 (next_file
[strlen(next_file
) - 1] == '*') &&
862 (next_file
[strlen(next_file
) - 2] == CLI_DIRSEP_CHAR
)) {
863 save_ch
= next_file
+
864 strlen(next_file
) - 2;
867 /* cwd is only used if showacls is on */
868 client_set_cwd(next_file
);
871 if (!showacls
) /* don't disturbe the showacls output */
872 d_printf("\n%s\n",next_file
);
874 *save_ch
= CLI_DIRSEP_CHAR
;
877 TALLOC_FREE(targetpath
);
881 reset_do_list_queue();
885 /****************************************************************************
886 Get a directory listing.
887 ****************************************************************************/
889 static int cmd_dir(void)
891 TALLOC_CTX
*ctx
= talloc_tos();
892 uint32_t attribute
= FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
899 mask
= talloc_strdup(ctx
, client_get_cur_dir());
904 if (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
906 if (*buf
== CLI_DIRSEP_CHAR
) {
907 mask
= talloc_strdup(ctx
, buf
);
909 mask
= talloc_asprintf_append(mask
, "%s", buf
);
912 mask
= talloc_asprintf_append(mask
, "*");
918 mask
= client_clean_name(ctx
, mask
);
924 /* cwd is only used if showacls is on */
925 client_set_cwd(client_get_cur_dir());
928 status
= do_list(mask
, attribute
, display_finfo
, recurse
, true);
929 if (!NT_STATUS_IS_OK(status
)) {
935 DEBUG(3, ("Total bytes listed: %.0f\n", dir_total
));
940 /****************************************************************************
941 Get a directory listing.
942 ****************************************************************************/
944 static int cmd_du(void)
946 TALLOC_CTX
*ctx
= talloc_tos();
947 uint32_t attribute
= FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
954 mask
= talloc_strdup(ctx
, client_get_cur_dir());
958 if ((mask
[0] != '\0') && (mask
[strlen(mask
)-1]!=CLI_DIRSEP_CHAR
)) {
959 mask
= talloc_asprintf_append(mask
, "%s", CLI_DIRSEP_STR
);
965 if (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
967 if (*buf
== CLI_DIRSEP_CHAR
) {
968 mask
= talloc_strdup(ctx
, buf
);
970 mask
= talloc_asprintf_append(mask
, "%s", buf
);
973 mask
= talloc_strdup(ctx
, "*");
979 mask
= client_clean_name(ctx
, mask
);
984 status
= do_list(mask
, attribute
, do_du
, recurse
, true);
985 if (!NT_STATUS_IS_OK(status
)) {
991 d_printf("Total number of bytes: %.0f\n", dir_total
);
996 static int cmd_echo(void)
998 TALLOC_CTX
*ctx
= talloc_tos();
1003 if (!next_token_talloc(ctx
, &cmd_ptr
, &num
, NULL
)
1004 || !next_token_talloc(ctx
, &cmd_ptr
, &data
, NULL
)) {
1005 d_printf("echo <num> <data>\n");
1009 status
= cli_echo(cli
, atoi(num
), data_blob_const(data
, strlen(data
)));
1011 if (!NT_STATUS_IS_OK(status
)) {
1012 d_printf("echo failed: %s\n", nt_errstr(status
));
1019 /****************************************************************************
1020 Get a file from rname to lname
1021 ****************************************************************************/
1023 static NTSTATUS
writefile_sink(char *buf
, size_t n
, void *priv
)
1025 int *pfd
= (int *)priv
;
1028 rc
= writefile(*pfd
, buf
, n
);
1030 return map_nt_error_from_unix(errno
);
1032 return NT_STATUS_OK
;
1035 static int do_get(const char *rname
, const char *lname_in
, bool reget
)
1037 TALLOC_CTX
*ctx
= talloc_tos();
1040 bool newhandle
= false;
1041 struct timespec tp_start
;
1047 struct cli_state
*targetcli
= NULL
;
1048 char *targetname
= NULL
;
1050 struct cli_credentials
*creds
= samba_cmdline_get_creds();
1053 lname
= talloc_strdup(ctx
, lname_in
);
1059 if (!strlower_m(lname
)) {
1060 d_printf("strlower_m %s failed\n", lname
);
1065 status
= cli_resolve_path(ctx
, "",
1067 cli
, rname
, &targetcli
, &targetname
);
1068 if (!NT_STATUS_IS_OK(status
)) {
1069 d_printf("Failed to open %s: %s\n", rname
, nt_errstr(status
));
1073 clock_gettime_mono(&tp_start
);
1075 status
= cli_open(targetcli
, targetname
, O_RDONLY
, DENY_NONE
, &fnum
);
1076 if (!NT_STATUS_IS_OK(status
)) {
1077 d_printf("%s opening remote file %s\n", nt_errstr(status
),
1082 if(!strcmp(lname
,"-")) {
1083 handle
= fileno(stdout
);
1086 handle
= open(lname
, O_WRONLY
|O_CREAT
, 0644);
1088 start
= lseek(handle
, 0, SEEK_END
);
1090 d_printf("Error seeking local file\n");
1096 handle
= open(lname
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
1101 d_printf("Error opening local file %s\n",lname
);
1106 status
= cli_qfileinfo_basic(targetcli
, fnum
, &attr
, &size
, NULL
, NULL
,
1108 if (!NT_STATUS_IS_OK(status
)) {
1109 d_printf("getattrib: %s\n", nt_errstr(status
));
1116 DEBUG(1,("getting file %s of size %.0f as %s ",
1117 rname
, (double)size
, lname
));
1119 status
= cli_pull(targetcli
, fnum
, start
, size
, io_bufsize
,
1120 writefile_sink
, (void *)&handle
, &nread
);
1121 if (!NT_STATUS_IS_OK(status
)) {
1122 d_fprintf(stderr
, "parallel_read returned %s\n",
1127 cli_close(targetcli
, fnum
);
1131 status
= cli_close(targetcli
, fnum
);
1132 if (!NT_STATUS_IS_OK(status
)) {
1133 d_printf("Error %s closing remote file\n", nt_errstr(status
));
1141 if (archive_level
>= 2 && (attr
& FILE_ATTRIBUTE_ARCHIVE
)) {
1142 cli_setatr(cli
, rname
, attr
& ~(uint32_t)FILE_ATTRIBUTE_ARCHIVE
, 0);
1146 struct timespec tp_end
;
1149 clock_gettime_mono(&tp_end
);
1150 this_time
= nsec_time_diff(&tp_end
,&tp_start
)/1000000;
1151 get_total_time_ms
+= this_time
;
1152 get_total_size
+= nread
;
1154 DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
1155 nread
/ (1.024*this_time
+ 1.0e-4),
1156 get_total_size
/ (1.024*get_total_time_ms
)));
1159 TALLOC_FREE(targetname
);
1163 /****************************************************************************
1165 ****************************************************************************/
1167 static int cmd_get(void)
1169 TALLOC_CTX
*ctx
= talloc_tos();
1174 rname
= talloc_strdup(ctx
, client_get_cur_dir());
1179 if (!next_token_talloc(ctx
, &cmd_ptr
,&fname
,NULL
)) {
1180 d_printf("get <filename> [localname]\n");
1183 rname
= talloc_asprintf_append(rname
, "%s", fname
);
1187 rname
= client_clean_name(ctx
, rname
);
1192 next_token_talloc(ctx
, &cmd_ptr
,&lname
,NULL
);
1197 return do_get(rname
, lname
, false);
1200 /****************************************************************************
1201 Do an mget operation on one file.
1202 ****************************************************************************/
1204 static NTSTATUS
do_mget(struct cli_state
*cli_state
, struct file_info
*finfo
,
1207 TALLOC_CTX
*ctx
= talloc_tos();
1208 const char *client_cwd
= NULL
;
1209 size_t client_cwd_len
;
1211 char *local_path
= NULL
;
1214 return NT_STATUS_OK
;
1217 if (ISDOT(finfo
->name
) || ISDOTDOT(finfo
->name
)) {
1218 return NT_STATUS_OK
;
1221 if ((finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) && !recurse
) {
1222 return NT_STATUS_OK
;
1226 const char *object
= (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) ?
1227 "directory" : "file";
1231 quest
= talloc_asprintf(
1232 ctx
, "Get %s %s? ", object
, finfo
->name
);
1233 if (quest
== NULL
) {
1234 return NT_STATUS_NO_MEMORY
;
1240 return NT_STATUS_OK
;
1244 path
= talloc_asprintf(
1245 ctx
, "%s%c%s", dir
, CLI_DIRSEP_CHAR
, finfo
->name
);
1247 return NT_STATUS_NO_MEMORY
;
1249 path
= client_clean_name(ctx
, path
);
1251 return NT_STATUS_NO_MEMORY
;
1255 * Skip the path prefix if we've done a remote "cd" when
1256 * creating the local path
1258 client_cwd
= client_get_cur_dir();
1259 client_cwd_len
= strlen(client_cwd
);
1261 local_path
= talloc_strdup(ctx
, path
+ client_cwd_len
);
1262 if (local_path
== NULL
) {
1264 return NT_STATUS_NO_MEMORY
;
1266 string_replace(local_path
, CLI_DIRSEP_CHAR
, '/');
1268 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
1269 int ret
= mkdir(local_path
, 0777);
1271 if ((ret
== -1) && (errno
!= EEXIST
)) {
1272 return map_nt_error_from_unix(errno
);
1275 do_get(path
, local_path
, false);
1278 return NT_STATUS_OK
;
1281 /****************************************************************************
1282 View the file using the pager.
1283 ****************************************************************************/
1285 static int cmd_more(void)
1287 TALLOC_CTX
*ctx
= talloc_tos();
1291 char *pager_cmd
= NULL
;
1297 rname
= talloc_strdup(ctx
, client_get_cur_dir());
1302 lname
= talloc_asprintf(ctx
, "%s/smbmore.XXXXXX",tmpdir());
1306 mask
= umask(S_IRWXO
| S_IRWXG
);
1307 fd
= mkstemp(lname
);
1310 d_printf("failed to create temporary file for more\n");
1315 if (!next_token_talloc(ctx
, &cmd_ptr
,&fname
,NULL
)) {
1316 d_printf("more <filename>\n");
1320 rname
= talloc_asprintf_append(rname
, "%s", fname
);
1324 rname
= client_clean_name(ctx
,rname
);
1329 rc
= do_get(rname
, lname
, false);
1331 pager
=getenv("PAGER");
1333 pager_cmd
= talloc_asprintf(ctx
,
1335 (pager
? pager
:PAGER
),
1340 if (system(pager_cmd
) == -1) {
1341 d_printf("system command '%s' returned -1\n",
1349 /****************************************************************************
1351 ****************************************************************************/
1353 static int cmd_mget(void)
1355 TALLOC_CTX
*ctx
= talloc_tos();
1356 uint32_t attribute
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
1357 char *mget_mask
= NULL
;
1359 NTSTATUS status
= NT_STATUS_OK
;
1362 attribute
|= FILE_ATTRIBUTE_DIRECTORY
;
1365 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1367 mget_mask
= talloc_strdup(ctx
, client_get_cur_dir());
1371 if (*buf
== CLI_DIRSEP_CHAR
) {
1372 mget_mask
= talloc_strdup(ctx
, buf
);
1374 mget_mask
= talloc_asprintf_append(mget_mask
,
1380 mget_mask
= client_clean_name(ctx
, mget_mask
);
1381 if (mget_mask
== NULL
) {
1384 status
= do_list(mget_mask
, attribute
, do_mget
, recurse
, true);
1385 if (!NT_STATUS_IS_OK(status
)) {
1390 if (mget_mask
== NULL
) {
1391 d_printf("nothing to mget\n");
1396 mget_mask
= talloc_asprintf(ctx
,
1398 client_get_cur_dir());
1402 mget_mask
= client_clean_name(ctx
, mget_mask
);
1403 if (mget_mask
== NULL
) {
1406 status
= do_list(mget_mask
, attribute
, do_mget
, recurse
, true);
1407 if (!NT_STATUS_IS_OK(status
)) {
1415 /****************************************************************************
1416 Make a directory of name "name".
1417 ****************************************************************************/
1419 static bool do_mkdir(const char *name
)
1421 TALLOC_CTX
*ctx
= talloc_tos();
1422 struct cli_state
*targetcli
;
1423 char *targetname
= NULL
;
1424 struct cli_credentials
*creds
= samba_cmdline_get_creds();
1427 status
= cli_resolve_path(ctx
, "",
1429 cli
, name
, &targetcli
, &targetname
);
1430 if (!NT_STATUS_IS_OK(status
)) {
1431 d_printf("mkdir %s: %s\n", name
, nt_errstr(status
));
1435 status
= cli_mkdir(targetcli
, targetname
);
1436 if (!NT_STATUS_IS_OK(status
)) {
1437 d_printf("%s making remote directory %s\n",
1438 nt_errstr(status
),name
);
1445 /****************************************************************************
1446 Show 8.3 name of a file.
1447 ****************************************************************************/
1449 static bool do_altname(const char *name
)
1454 status
= cli_qpathinfo_alt_name(cli
, name
, altname
);
1455 if (!NT_STATUS_IS_OK(status
)) {
1456 d_printf("%s getting alt name for %s\n",
1457 nt_errstr(status
),name
);
1460 d_printf("%s\n", altname
);
1465 /****************************************************************************
1467 ****************************************************************************/
1469 static int cmd_quit(void)
1477 /****************************************************************************
1479 ****************************************************************************/
1481 static int cmd_mkdir(void)
1483 TALLOC_CTX
*ctx
= talloc_tos();
1486 struct cli_credentials
*creds
= samba_cmdline_get_creds();
1489 mask
= talloc_strdup(ctx
, client_get_cur_dir());
1494 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1496 d_printf("mkdir <dirname>\n");
1500 mask
= talloc_asprintf_append(mask
, "%s", buf
);
1504 mask
= client_clean_name(ctx
, mask
);
1512 struct cli_state
*targetcli
;
1513 char *targetname
= NULL
;
1517 ddir2
= talloc_strdup(ctx
, "");
1522 status
= cli_resolve_path(ctx
, "",
1525 &targetcli
, &targetname
);
1526 if (!NT_STATUS_IS_OK(status
)) {
1530 ddir
= talloc_strdup(ctx
, targetname
);
1534 trim_char(ddir
,'.','\0');
1535 p
= strtok_r(ddir
, "/\\", &saveptr
);
1537 ddir2
= talloc_asprintf_append(ddir2
, "%s", p
);
1541 if (!NT_STATUS_IS_OK(cli_chkpath(targetcli
, ddir2
))) {
1544 ddir2
= talloc_asprintf_append(ddir2
, "%s", CLI_DIRSEP_STR
);
1548 p
= strtok_r(NULL
, "/\\", &saveptr
);
1557 /****************************************************************************
1559 ****************************************************************************/
1561 static int cmd_altname(void)
1563 TALLOC_CTX
*ctx
= talloc_tos();
1567 name
= talloc_strdup(ctx
, client_get_cur_dir());
1572 if (!next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
)) {
1573 d_printf("altname <file>\n");
1576 name
= talloc_asprintf_append(name
, "%s", buf
);
1580 name
= client_clean_name(ctx
, name
);
1588 static char *attr_str(TALLOC_CTX
*mem_ctx
, uint32_t attr
)
1590 char *attrs
= talloc_zero_array(mem_ctx
, char, 17);
1593 if (!(attr
& FILE_ATTRIBUTE_NORMAL
)) {
1594 if (attr
& FILE_ATTRIBUTE_ENCRYPTED
) {
1597 if (attr
& FILE_ATTRIBUTE_NONINDEXED
) {
1600 if (attr
& FILE_ATTRIBUTE_OFFLINE
) {
1603 if (attr
& FILE_ATTRIBUTE_COMPRESSED
) {
1606 if (attr
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1609 if (attr
& FILE_ATTRIBUTE_SPARSE
) {
1612 if (attr
& FILE_ATTRIBUTE_TEMPORARY
) {
1615 if (attr
& FILE_ATTRIBUTE_NORMAL
) {
1618 if (attr
& FILE_ATTRIBUTE_READONLY
) {
1621 if (attr
& FILE_ATTRIBUTE_HIDDEN
) {
1624 if (attr
& FILE_ATTRIBUTE_SYSTEM
) {
1627 if (attr
& FILE_ATTRIBUTE_DIRECTORY
) {
1630 if (attr
& FILE_ATTRIBUTE_ARCHIVE
) {
1637 /****************************************************************************
1638 Show all info we can get
1639 ****************************************************************************/
1641 static int do_allinfo(const char *name
)
1644 struct timespec b_time
, a_time
, m_time
, c_time
;
1649 unsigned int num_streams
;
1650 struct stream_struct
*streams
;
1651 int j
, num_snapshots
;
1652 char **snapshots
= NULL
;
1656 status
= cli_qpathinfo_alt_name(cli
, name
, altname
);
1657 if (!NT_STATUS_IS_OK(status
)) {
1658 d_printf("%s getting alt name for %s\n", nt_errstr(status
),
1661 * Ignore not supported or not implemented, it does not
1662 * hurt if we can't list alternate names.
1664 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
) ||
1665 NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
1671 d_printf("altname: %s\n", altname
);
1673 status
= cli_qpathinfo3(cli
, name
, &b_time
, &a_time
, &m_time
, &c_time
,
1674 &size
, &attr
, NULL
);
1675 if (!NT_STATUS_IS_OK(status
)) {
1676 d_printf("%s getting pathinfo for %s\n", nt_errstr(status
),
1681 tmp
= full_timespec_to_nt_time(&b_time
);
1682 d_printf("create_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1684 tmp
= full_timespec_to_nt_time(&a_time
);
1685 d_printf("access_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1687 tmp
= full_timespec_to_nt_time(&m_time
);
1688 d_printf("write_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1690 tmp
= full_timespec_to_nt_time(&c_time
);
1691 d_printf("change_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1693 d_printf("attributes: %s (%x)\n", attr_str(talloc_tos(), attr
), attr
);
1695 status
= cli_qpathinfo_streams(cli
, name
, talloc_tos(), &num_streams
,
1697 if (!NT_STATUS_IS_OK(status
)) {
1698 d_printf("%s getting streams for %s\n", nt_errstr(status
),
1703 for (i
=0; i
<num_streams
; i
++) {
1704 d_printf("stream: [%s], %lld bytes\n", streams
[i
].name
,
1705 (unsigned long long)streams
[i
].size
);
1708 if (attr
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1709 char *subst
, *print
;
1712 status
= cli_readlink(cli
, name
, talloc_tos(), &subst
, &print
,
1714 if (!NT_STATUS_IS_OK(status
)) {
1715 d_fprintf(stderr
, "cli_readlink returned %s\n",
1718 d_printf("symlink: subst=[%s], print=[%s], flags=%x\n",
1719 subst
, print
, flags
);
1725 status
= cli_ntcreate(cli
, name
, 0,
1726 SEC_FILE_READ_DATA
| SEC_FILE_READ_ATTRIBUTE
|
1727 SEC_STD_SYNCHRONIZE
, 0,
1728 FILE_SHARE_READ
|FILE_SHARE_WRITE
1730 FILE_OPEN
, 0x0, 0x0, &fnum
, NULL
);
1731 if (!NT_STATUS_IS_OK(status
)) {
1733 * Ignore failure, it does not hurt if we can't list
1739 * In order to get shadow copy data over SMB1 we
1740 * must call twice, once with 'get_names = false'
1741 * to get the size, then again with 'get_names = true'
1742 * to get the data or a Windows server fails to return
1743 * valid info. Samba doesn't have this bug. JRA.
1746 status
= cli_shadow_copy_data(talloc_tos(), cli
, fnum
,
1747 false, &snapshots
, &num_snapshots
);
1748 if (!NT_STATUS_IS_OK(status
)) {
1749 cli_close(cli
, fnum
);
1752 status
= cli_shadow_copy_data(talloc_tos(), cli
, fnum
,
1753 true, &snapshots
, &num_snapshots
);
1754 if (!NT_STATUS_IS_OK(status
)) {
1755 cli_close(cli
, fnum
);
1759 for (j
=0; j
<num_snapshots
; j
++) {
1762 d_printf("%s\n", snapshots
[j
]);
1763 snap_name
= talloc_asprintf(talloc_tos(), "%s%s",
1764 snapshots
[j
], name
);
1765 status
= cli_qpathinfo3(cli
, snap_name
, &b_time
, &a_time
,
1766 &m_time
, &c_time
, &size
,
1768 if (!NT_STATUS_IS_OK(status
)) {
1769 d_fprintf(stderr
, "pathinfo(%s) failed: %s\n",
1770 snap_name
, nt_errstr(status
));
1771 TALLOC_FREE(snap_name
);
1774 tmp
= unix_timespec_to_nt_time(b_time
);
1775 d_printf("create_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1776 tmp
= unix_timespec_to_nt_time(a_time
);
1777 d_printf("access_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1778 tmp
=unix_timespec_to_nt_time(m_time
);
1779 d_printf("write_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1780 tmp
= unix_timespec_to_nt_time(c_time
);
1781 d_printf("change_time: %s\n", nt_time_string(talloc_tos(), tmp
));
1782 d_printf("size: %d\n", (int)size
);
1785 TALLOC_FREE(snapshots
);
1786 cli_close(cli
, fnum
);
1791 /****************************************************************************
1792 Show all info we can get
1793 ****************************************************************************/
1795 static int cmd_allinfo(void)
1797 TALLOC_CTX
*ctx
= talloc_tos();
1801 name
= talloc_strdup(ctx
, client_get_cur_dir());
1806 if (!next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
)) {
1807 d_printf("allinfo <file>\n");
1810 name
= talloc_asprintf_append(name
, "%s", buf
);
1814 name
= client_clean_name(ctx
, name
);
1823 /****************************************************************************
1825 ****************************************************************************/
1827 static int do_put(const char *rname
, const char *lname
, bool reput
)
1829 TALLOC_CTX
*ctx
= talloc_tos();
1834 struct timespec tp_start
;
1835 struct cli_state
*targetcli
;
1836 char *targetname
= NULL
;
1837 struct push_state state
;
1838 struct cli_credentials
*creds
= samba_cmdline_get_creds();
1841 status
= cli_resolve_path(ctx
, "",
1843 cli
, rname
, &targetcli
, &targetname
);
1844 if (!NT_STATUS_IS_OK(status
)) {
1845 d_printf("Failed to open %s: %s\n", rname
, nt_errstr(status
));
1849 clock_gettime_mono(&tp_start
);
1852 status
= cli_open(targetcli
, targetname
, O_RDWR
|O_CREAT
, DENY_NONE
, &fnum
);
1853 if (NT_STATUS_IS_OK(status
)) {
1854 if (!NT_STATUS_IS_OK(status
= cli_qfileinfo_basic(
1855 targetcli
, fnum
, NULL
,
1857 NULL
, NULL
, NULL
))) {
1858 d_printf("getattrib: %s\n", nt_errstr(status
));
1863 status
= cli_open(targetcli
, targetname
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
, &fnum
);
1866 if (!NT_STATUS_IS_OK(status
)) {
1867 d_printf("%s opening remote file %s\n", nt_errstr(status
),
1872 /* allow files to be piped into smbclient
1875 Note that in this case this function will exit(0) rather
1877 if (!strcmp(lname
, "-")) {
1879 /* size of file is not known */
1881 f
= fopen(lname
, "r");
1883 if (fseek(f
, start
, SEEK_SET
) == -1) {
1884 d_printf("Error seeking local file\n");
1892 d_printf("Error opening local file %s\n",lname
);
1896 DEBUG(1,("putting file %s as %s ",lname
,
1899 setvbuf(f
, NULL
, _IOFBF
, io_bufsize
);
1904 status
= cli_push(targetcli
, fnum
, 0, 0, io_bufsize
, push_source
,
1906 if (!NT_STATUS_IS_OK(status
)) {
1907 d_fprintf(stderr
, "cli_push returned %s\n", nt_errstr(status
));
1911 status
= cli_close(targetcli
, fnum
);
1912 if (!NT_STATUS_IS_OK(status
)) {
1913 d_printf("%s closing remote file %s\n", nt_errstr(status
),
1926 struct timespec tp_end
;
1929 clock_gettime_mono(&tp_end
);
1930 this_time
= nsec_time_diff(&tp_end
,&tp_start
)/1000000;
1931 put_total_time_ms
+= this_time
;
1932 put_total_size
+= state
.nread
;
1934 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
1935 state
.nread
/ (1.024*this_time
+ 1.0e-4),
1936 put_total_size
/ (1.024*put_total_time_ms
)));
1947 /****************************************************************************
1949 ****************************************************************************/
1951 static int cmd_put(void)
1953 TALLOC_CTX
*ctx
= talloc_tos();
1958 rname
= talloc_strdup(ctx
, client_get_cur_dir());
1963 if (!next_token_talloc(ctx
, &cmd_ptr
,&lname
,NULL
)) {
1964 d_printf("put <filename>\n");
1968 if (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1969 rname
= talloc_asprintf_append(rname
, "%s", buf
);
1971 rname
= talloc_asprintf_append(rname
, "%s", lname
);
1977 rname
= client_clean_name(ctx
, rname
);
1984 /* allow '-' to represent stdin
1985 jdblair, 24.jun.98 */
1986 if (!file_exist_stat(lname
, &st
, false) &&
1987 (strcmp(lname
,"-"))) {
1988 d_printf("%s does not exist\n",lname
);
1993 return do_put(rname
, lname
, false);
1996 /*************************************
1997 File list structure.
1998 *************************************/
2000 static struct file_list
{
2001 struct file_list
*prev
, *next
;
2006 /****************************************************************************
2007 Free a file_list structure.
2008 ****************************************************************************/
2010 static void free_file_list (struct file_list
*l_head
)
2012 struct file_list
*list
, *next
;
2014 for (list
= l_head
; list
; list
= next
) {
2016 DLIST_REMOVE(l_head
, list
);
2021 /****************************************************************************
2022 Seek in a directory/file list until you get something that doesn't start with
2024 ****************************************************************************/
2026 static bool seek_list(struct file_list
*list
, char *name
)
2029 trim_string(list
->file_path
,"./","\n");
2030 if (strncmp(list
->file_path
, name
, strlen(name
)) != 0) {
2039 /****************************************************************************
2040 Set the file selection mask.
2041 ****************************************************************************/
2043 static int cmd_select(void)
2045 TALLOC_CTX
*ctx
= talloc_tos();
2046 char *new_fs
= NULL
;
2047 next_token_talloc(ctx
, &cmd_ptr
,&new_fs
,NULL
)
2050 client_set_fileselection(new_fs
);
2052 client_set_fileselection("");
2057 /****************************************************************************
2058 Recursive file matching function act as find
2059 match must be always set to true when calling this function
2060 ****************************************************************************/
2062 static int file_find(TALLOC_CTX
*ctx
,
2063 struct file_list
**list
,
2064 const char *directory
,
2065 const char *expression
,
2069 struct file_list
*entry
;
2070 struct stat statbuf
;
2076 dir
= opendir(directory
);
2080 while ((dname
= readdirname(dir
))) {
2081 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2085 path
= talloc_asprintf(ctx
, "%s/%s", directory
, dname
);
2091 if (!match
|| !gen_fnmatch(expression
, dname
)) {
2093 ret
= stat(path
, &statbuf
);
2095 if (S_ISDIR(statbuf
.st_mode
)) {
2097 ret
= file_find(ctx
,
2104 d_printf("file_find: cannot stat file %s\n", path
);
2113 entry
= talloc_zero(ctx
, struct file_list
);
2115 d_printf("Out of memory in file_find\n");
2119 entry
->file_path
= talloc_move(entry
, &path
);
2120 entry
->isdir
= isdir
;
2121 DLIST_ADD(*list
, entry
);
2131 /****************************************************************************
2133 ****************************************************************************/
2135 static int cmd_mput(void)
2137 TALLOC_CTX
*ctx
= talloc_tos();
2140 while (next_token_talloc(ctx
, &cmd_ptr
,&p
,NULL
)) {
2142 struct file_list
*temp_list
;
2143 char *quest
, *lname
, *rname
;
2147 ret
= file_find(ctx
, &file_list
, ".", p
, true);
2149 free_file_list(file_list
);
2157 for (temp_list
= file_list
; temp_list
;
2158 temp_list
= temp_list
->next
) {
2161 if (asprintf(&lname
, "%s/", temp_list
->file_path
) <= 0) {
2164 trim_string(lname
, "./", "/");
2166 /* check if it's a directory */
2167 if (temp_list
->isdir
) {
2168 /* if (!recurse) continue; */
2171 if (asprintf(&quest
, "Put directory %s? ", lname
) < 0) {
2174 if (prompt
&& !yesno(quest
)) { /* No */
2175 /* Skip the directory */
2176 lname
[strlen(lname
)-1] = '/';
2177 if (!seek_list(temp_list
, lname
))
2181 if(asprintf(&rname
, "%s%s", client_get_cur_dir(), lname
) < 0) {
2184 normalize_name(rname
);
2187 client_clean_name(ctx
, rname
);
2188 if (tmp_rname
== NULL
) {
2192 rname
= smb_xstrdup(tmp_rname
);
2193 TALLOC_FREE(tmp_rname
);
2194 if (rname
== NULL
) {
2198 if (!NT_STATUS_IS_OK(cli_chkpath(cli
, rname
)) &&
2200 DEBUG (0, ("Unable to make dir, skipping..."));
2201 /* Skip the directory */
2202 lname
[strlen(lname
)-1] = '/';
2203 if (!seek_list(temp_list
, lname
)) {
2211 if (asprintf(&quest
,"Put file %s? ", lname
) < 0) {
2214 if (prompt
&& !yesno(quest
)) {
2221 if (asprintf(&rname
, "%s%s", client_get_cur_dir(), lname
) < 0) {
2226 normalize_name(rname
);
2229 char *tmp_rname
= client_clean_name(ctx
, rname
);
2230 if (tmp_rname
== NULL
) {
2234 rname
= smb_xstrdup(tmp_rname
);
2235 TALLOC_FREE(tmp_rname
);
2236 if (rname
== NULL
) {
2240 do_put(rname
, lname
, false);
2242 free_file_list(file_list
);
2251 /****************************************************************************
2253 ****************************************************************************/
2255 static int do_cancel(int job
)
2257 if (cli_printjob_del(cli
, job
)) {
2258 d_printf("Job %d cancelled\n",job
);
2261 NTSTATUS status
= cli_nt_error(cli
);
2262 d_printf("Error cancelling job %d : %s\n",
2263 job
, nt_errstr(status
));
2268 /****************************************************************************
2270 ****************************************************************************/
2272 static int cmd_cancel(void)
2274 TALLOC_CTX
*ctx
= talloc_tos();
2278 if (!next_token_talloc(ctx
, &cmd_ptr
, &buf
,NULL
)) {
2279 d_printf("cancel <jobid> ...\n");
2285 } while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
));
2290 /****************************************************************************
2292 ****************************************************************************/
2294 static int cmd_print(void)
2296 TALLOC_CTX
*ctx
= talloc_tos();
2301 if (!next_token_talloc(ctx
, &cmd_ptr
, &lname
,NULL
)) {
2302 d_printf("print <filename>\n");
2306 rname
= talloc_strdup(ctx
, lname
);
2310 p
= strrchr_m(rname
,'/');
2312 rname
= talloc_asprintf(ctx
,
2317 if (strequal(lname
,"-")) {
2318 rname
= talloc_asprintf(ctx
,
2326 return do_put(rname
, lname
, false);
2329 /****************************************************************************
2330 Show a print queue entry.
2331 ****************************************************************************/
2333 static void queue_fn(struct print_job_info
*p
)
2335 d_printf("%-6d %-9d %s\n", (int)p
->id
, (int)p
->size
, p
->name
);
2338 /****************************************************************************
2340 ****************************************************************************/
2342 static int cmd_queue(void)
2344 cli_print_queue(cli
, queue_fn
);
2348 /****************************************************************************
2350 ****************************************************************************/
2352 static NTSTATUS
do_del(struct cli_state
*cli_state
, struct file_info
*finfo
,
2355 TALLOC_CTX
*ctx
= talloc_tos();
2357 struct cli_state
*targetcli
= NULL
;
2358 char *targetname
= NULL
;
2359 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2362 mask
= talloc_asprintf(ctx
,
2368 return NT_STATUS_NO_MEMORY
;
2371 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
2373 return NT_STATUS_OK
;
2376 status
= cli_resolve_path(ctx
, "",
2378 cli
, mask
, &targetcli
, &targetname
);
2379 if (!NT_STATUS_IS_OK(status
)) {
2383 status
= cli_unlink(targetcli
, targetname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2385 if (!NT_STATUS_IS_OK(status
)) {
2386 d_printf("%s deleting remote file %s\n",
2387 nt_errstr(status
), mask
);
2393 /****************************************************************************
2395 ****************************************************************************/
2397 static int cmd_del(void)
2399 TALLOC_CTX
*ctx
= talloc_tos();
2402 NTSTATUS status
= NT_STATUS_OK
;
2403 uint32_t attribute
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
2406 attribute
|= FILE_ATTRIBUTE_DIRECTORY
;
2409 mask
= talloc_strdup(ctx
, client_get_cur_dir());
2413 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2414 d_printf("del <filename>\n");
2417 mask
= talloc_asprintf_append(mask
, "%s", buf
);
2421 mask
= client_clean_name(ctx
, mask
);
2426 status
= do_list(mask
,attribute
,do_del
,false,false);
2427 if (!NT_STATUS_IS_OK(status
)) {
2433 /****************************************************************************
2435 ****************************************************************************/
2437 static NTSTATUS
delete_remote_files_list(struct cli_state
*cli_state
,
2438 struct file_list
*flist
)
2440 NTSTATUS status
= NT_STATUS_OK
;
2441 struct file_list
*deltree_list_iter
= NULL
;
2442 char *targetname
= NULL
;
2443 struct cli_state
*targetcli
= NULL
;
2444 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2445 TALLOC_CTX
*ctx
= talloc_tos();
2447 for (deltree_list_iter
= flist
;
2448 deltree_list_iter
!= NULL
;
2449 deltree_list_iter
= deltree_list_iter
->next
) {
2450 status
= cli_resolve_path(ctx
,
2454 deltree_list_iter
->file_path
,
2457 if (!NT_STATUS_IS_OK(status
)) {
2458 d_printf("delete_remote_files %s: %s\n",
2459 deltree_list_iter
->file_path
,
2463 if (CLI_DIRSEP_CHAR
== '/') {
2465 status
= cli_posix_unlink(targetcli
,
2467 } else if (deltree_list_iter
->isdir
) {
2468 status
= cli_rmdir(targetcli
,
2471 status
= cli_unlink(targetcli
,
2473 FILE_ATTRIBUTE_SYSTEM
|
2474 FILE_ATTRIBUTE_HIDDEN
);
2476 if (!NT_STATUS_IS_OK(status
)) {
2477 d_printf("%s deleting remote %s %s\n",
2479 deltree_list_iter
->isdir
?
2480 "directory" : "file",
2481 deltree_list_iter
->file_path
);
2485 return NT_STATUS_OK
;
2488 /****************************************************************************
2489 Save a list of files to delete.
2490 ****************************************************************************/
2492 static struct file_list
*deltree_list_head
;
2494 static NTSTATUS
do_deltree_list(struct cli_state
*cli_state
,
2495 struct file_info
*finfo
,
2498 struct file_list
**file_list_head_pp
= &deltree_list_head
;
2499 struct file_list
*dt
= NULL
;
2501 if (!do_this_one(finfo
)) {
2502 return NT_STATUS_OK
;
2505 /* skip if this is . or .. */
2506 if (ISDOT(finfo
->name
) || ISDOTDOT(finfo
->name
)) {
2507 return NT_STATUS_OK
;
2510 dt
= talloc_zero(NULL
, struct file_list
);
2512 return NT_STATUS_NO_MEMORY
;
2515 /* create absolute filename for cli_ntcreate() */
2516 dt
->file_path
= talloc_asprintf(dt
,
2521 if (dt
->file_path
== NULL
) {
2523 return NT_STATUS_NO_MEMORY
;
2526 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
2530 DLIST_ADD(*file_list_head_pp
, dt
);
2531 return NT_STATUS_OK
;
2534 static int cmd_deltree(void)
2536 TALLOC_CTX
*ctx
= talloc_tos();
2538 NTSTATUS status
= NT_STATUS_OK
;
2539 struct file_list
*deltree_list_norecurse
= NULL
;
2540 struct file_list
*deltree_list_iter
= NULL
;
2541 uint32_t attribute
= FILE_ATTRIBUTE_SYSTEM
|
2542 FILE_ATTRIBUTE_HIDDEN
|
2543 FILE_ATTRIBUTE_DIRECTORY
;
2545 char *mask
= talloc_strdup(ctx
, client_get_cur_dir());
2549 ok
= next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
);
2551 d_printf("deltree <filename>\n");
2554 mask
= talloc_asprintf_append(mask
, "%s", buf
);
2558 mask
= client_clean_name(ctx
, mask
);
2563 deltree_list_head
= NULL
;
2566 * Get the list of directories to
2567 * delete (in case mask has a wildcard).
2569 status
= do_list(mask
, attribute
, do_deltree_list
, false, true);
2570 if (!NT_STATUS_IS_OK(status
)) {
2573 deltree_list_norecurse
= deltree_list_head
;
2574 deltree_list_head
= NULL
;
2576 for (deltree_list_iter
= deltree_list_norecurse
;
2577 deltree_list_iter
!= NULL
;
2578 deltree_list_iter
= deltree_list_iter
->next
) {
2580 if (deltree_list_iter
->isdir
== false) {
2581 char *targetname
= NULL
;
2582 struct cli_state
*targetcli
= NULL
;
2583 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2584 status
= cli_resolve_path(ctx
,
2588 deltree_list_iter
->file_path
,
2591 if (!NT_STATUS_IS_OK(status
)) {
2594 /* Just a regular file. */
2595 if (CLI_DIRSEP_CHAR
== '/') {
2597 status
= cli_posix_unlink(targetcli
,
2600 status
= cli_unlink(targetcli
,
2602 FILE_ATTRIBUTE_SYSTEM
|
2603 FILE_ATTRIBUTE_HIDDEN
);
2605 if (!NT_STATUS_IS_OK(status
)) {
2612 * Get the list of files or directories to
2613 * delete in depth order.
2615 status
= do_list(deltree_list_iter
->file_path
,
2620 if (!NT_STATUS_IS_OK(status
)) {
2623 status
= delete_remote_files_list(cli
, deltree_list_head
);
2624 free_file_list(deltree_list_head
);
2625 deltree_list_head
= NULL
;
2626 if (!NT_STATUS_IS_OK(status
)) {
2631 free_file_list(deltree_list_norecurse
);
2632 free_file_list(deltree_list_head
);
2637 free_file_list(deltree_list_norecurse
);
2638 free_file_list(deltree_list_head
);
2639 deltree_list_head
= NULL
;
2644 /****************************************************************************
2645 Wildcard delete some files.
2646 ****************************************************************************/
2648 static int cmd_wdel(void)
2650 TALLOC_CTX
*ctx
= talloc_tos();
2654 struct cli_state
*targetcli
;
2655 char *targetname
= NULL
;
2656 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2659 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2660 d_printf("wdel 0x<attrib> <wcard>\n");
2664 attribute
= (uint32_t)strtol(buf
, (char **)NULL
, 16);
2666 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2667 d_printf("wdel 0x<attrib> <wcard>\n");
2671 mask
= talloc_asprintf(ctx
, "%s%s",
2672 client_get_cur_dir(),
2677 mask
= client_clean_name(ctx
, mask
);
2682 status
= cli_resolve_path(ctx
, "",
2684 cli
, mask
, &targetcli
, &targetname
);
2685 if (!NT_STATUS_IS_OK(status
)) {
2686 d_printf("cmd_wdel %s: %s\n", mask
, nt_errstr(status
));
2690 status
= cli_unlink(targetcli
, targetname
, attribute
);
2691 if (!NT_STATUS_IS_OK(status
)) {
2692 d_printf("%s deleting remote files %s\n", nt_errstr(status
),
2698 /****************************************************************************
2699 ****************************************************************************/
2701 static int cmd_open(void)
2703 TALLOC_CTX
*ctx
= talloc_tos();
2706 char *targetname
= NULL
;
2707 struct cli_state
*targetcli
;
2708 uint16_t fnum
= (uint16_t)-1;
2709 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2712 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2713 d_printf("open <filename>\n");
2716 mask
= talloc_asprintf(ctx
,
2718 client_get_cur_dir(),
2724 mask
= client_clean_name(ctx
, mask
);
2729 status
= cli_resolve_path(ctx
, "",
2731 cli
, mask
, &targetcli
, &targetname
);
2732 if (!NT_STATUS_IS_OK(status
)) {
2733 d_printf("open %s: %s\n", mask
, nt_errstr(status
));
2737 status
= cli_ntcreate(targetcli
, targetname
, 0,
2738 FILE_READ_DATA
|FILE_WRITE_DATA
, 0,
2739 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
,
2740 0x0, 0x0, &fnum
, NULL
);
2741 if (!NT_STATUS_IS_OK(status
)) {
2742 status
= cli_ntcreate(targetcli
, targetname
, 0,
2744 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
,
2745 0x0, 0x0, &fnum
, NULL
);
2746 if (NT_STATUS_IS_OK(status
)) {
2747 d_printf("open file %s: for read/write fnum %d\n", targetname
, fnum
);
2749 d_printf("Failed to open file %s. %s\n",
2750 targetname
, nt_errstr(status
));
2753 d_printf("open file %s: for read/write fnum %d\n", targetname
, fnum
);
2758 static int cmd_posix_encrypt(void)
2760 TALLOC_CTX
*ctx
= talloc_tos();
2761 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
2762 char *domain
= NULL
;
2764 char *password
= NULL
;
2765 struct cli_credentials
*creds
= NULL
;
2766 struct cli_credentials
*lcreds
= NULL
;
2768 if (next_token_talloc(ctx
, &cmd_ptr
, &domain
, NULL
)) {
2770 if (!next_token_talloc(ctx
, &cmd_ptr
, &user
, NULL
)) {
2771 d_printf("posix_encrypt domain user password\n");
2775 if (!next_token_talloc(ctx
, &cmd_ptr
, &password
, NULL
)) {
2776 d_printf("posix_encrypt domain user password\n");
2780 lcreds
= cli_session_creds_init(ctx
,
2785 false, /* use_kerberos */
2786 false, /* fallback_after_kerberos */
2787 false, /* use_ccache */
2788 false); /* password_is_nt_hash */
2789 if (lcreds
== NULL
) {
2790 d_printf("cli_session_creds_init() failed.\n");
2795 bool auth_requested
= false;
2797 creds
= samba_cmdline_get_creds();
2799 auth_requested
= cli_credentials_authentication_requested(creds
);
2800 if (!auth_requested
) {
2801 d_printf("posix_encrypt domain user password\n");
2806 status
= cli_smb1_setup_encryption(cli
, creds
);
2807 /* gensec currently references the creds so we can't free them here */
2808 talloc_unlink(ctx
, lcreds
);
2809 if (!NT_STATUS_IS_OK(status
)) {
2810 d_printf("posix_encrypt failed with error %s\n", nt_errstr(status
));
2814 d_printf("encryption on\n");
2815 ok
= cli_credentials_set_smb_encryption(creds
,
2816 SMB_ENCRYPTION_REQUIRED
,
2824 /****************************************************************************
2825 ****************************************************************************/
2827 static int cmd_posix_open(void)
2829 TALLOC_CTX
*ctx
= talloc_tos();
2832 char *targetname
= NULL
;
2833 struct cli_state
*targetcli
;
2836 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2839 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2840 d_printf("posix_open <filename> 0<mode>\n");
2843 mask
= talloc_asprintf(ctx
,
2845 client_get_cur_dir(),
2850 mask
= client_clean_name(ctx
, mask
);
2855 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2856 d_printf("posix_open <filename> 0<mode>\n");
2859 if (CLI_DIRSEP_CHAR
!= '/') {
2860 d_printf("Command \"posix\" must be issued before "
2861 "the \"posix_open\" command can be used.\n");
2864 mode
= (mode_t
)strtol(buf
, (char **)NULL
, 8);
2866 status
= cli_resolve_path(ctx
, "",
2868 cli
, mask
, &targetcli
, &targetname
);
2869 if (!NT_STATUS_IS_OK(status
)) {
2870 d_printf("posix_open %s: %s\n", mask
, nt_errstr(status
));
2874 status
= cli_posix_open(targetcli
, targetname
, O_CREAT
|O_RDWR
, mode
,
2876 if (!NT_STATUS_IS_OK(status
)) {
2877 status
= cli_posix_open(targetcli
, targetname
,
2878 O_CREAT
|O_RDONLY
, mode
, &fnum
);
2879 if (!NT_STATUS_IS_OK(status
)) {
2880 d_printf("Failed to open file %s. %s\n", targetname
,
2883 d_printf("posix_open file %s: for readonly fnum %d\n",
2887 d_printf("posix_open file %s: for read/write fnum %d\n",
2894 static int cmd_posix_mkdir(void)
2896 TALLOC_CTX
*ctx
= talloc_tos();
2899 char *targetname
= NULL
;
2900 struct cli_state
*targetcli
;
2902 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2905 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2906 d_printf("posix_mkdir <filename> 0<mode>\n");
2909 mask
= talloc_asprintf(ctx
,
2911 client_get_cur_dir(),
2916 mask
= client_clean_name(ctx
, mask
);
2921 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2922 d_printf("posix_mkdir <filename> 0<mode>\n");
2925 if (CLI_DIRSEP_CHAR
!= '/') {
2926 d_printf("Command \"posix\" must be issued before "
2927 "the \"posix_mkdir\" command can be used.\n");
2930 mode
= (mode_t
)strtol(buf
, (char **)NULL
, 8);
2932 status
= cli_resolve_path(ctx
, "",
2934 cli
, mask
, &targetcli
, &targetname
);
2935 if (!NT_STATUS_IS_OK(status
)) {
2936 d_printf("posix_mkdir %s: %s\n", mask
, nt_errstr(status
));
2940 status
= cli_posix_mkdir(targetcli
, targetname
, mode
);
2941 if (!NT_STATUS_IS_OK(status
)) {
2942 d_printf("Failed to open file %s. %s\n",
2943 targetname
, nt_errstr(status
));
2945 d_printf("posix_mkdir created directory %s\n", targetname
);
2950 static int cmd_posix_unlink(void)
2952 TALLOC_CTX
*ctx
= talloc_tos();
2955 char *targetname
= NULL
;
2956 struct cli_state
*targetcli
;
2957 struct cli_credentials
*creds
= samba_cmdline_get_creds();
2960 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
2961 d_printf("posix_unlink <filename>\n");
2964 if (CLI_DIRSEP_CHAR
!= '/') {
2965 d_printf("Command \"posix\" must be issued before "
2966 "the \"posix_unlink\" command can be used.\n");
2969 mask
= talloc_asprintf(ctx
,
2971 client_get_cur_dir(),
2976 mask
= client_clean_name(ctx
, mask
);
2981 status
= cli_resolve_path(ctx
, "",
2983 cli
, mask
, &targetcli
, &targetname
);
2984 if (!NT_STATUS_IS_OK(status
)) {
2985 d_printf("posix_unlink %s: %s\n", mask
, nt_errstr(status
));
2989 status
= cli_posix_unlink(targetcli
, targetname
);
2990 if (!NT_STATUS_IS_OK(status
)) {
2991 d_printf("Failed to unlink file %s. %s\n",
2992 targetname
, nt_errstr(status
));
2994 d_printf("posix_unlink deleted file %s\n", targetname
);
3000 static int cmd_posix_rmdir(void)
3002 TALLOC_CTX
*ctx
= talloc_tos();
3005 char *targetname
= NULL
;
3006 struct cli_state
*targetcli
;
3007 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3010 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3011 d_printf("posix_rmdir <filename>\n");
3014 if (CLI_DIRSEP_CHAR
!= '/') {
3015 d_printf("Command \"posix\" must be issued before "
3016 "the \"posix_rmdir\" command can be used.\n");
3019 mask
= talloc_asprintf(ctx
,
3021 client_get_cur_dir(),
3026 mask
= client_clean_name(ctx
, mask
);
3031 status
= cli_resolve_path(ctx
, "",
3033 cli
, mask
, &targetcli
, &targetname
);
3034 if (!NT_STATUS_IS_OK(status
)) {
3035 d_printf("posix_rmdir %s: %s\n", mask
, nt_errstr(status
));
3039 status
= cli_posix_rmdir(targetcli
, targetname
);
3040 if (!NT_STATUS_IS_OK(status
)) {
3041 d_printf("Failed to unlink directory %s. %s\n",
3042 targetname
, nt_errstr(status
));
3044 d_printf("posix_rmdir deleted directory %s\n", targetname
);
3050 static int cmd_close(void)
3052 TALLOC_CTX
*ctx
= talloc_tos();
3057 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3058 d_printf("close <fnum>\n");
3063 /* We really should use the targetcli here.... */
3064 status
= cli_close(cli
, fnum
);
3065 if (!NT_STATUS_IS_OK(status
)) {
3066 d_printf("close %d: %s\n", fnum
, nt_errstr(status
));
3072 static int cmd_posix(void)
3074 TALLOC_CTX
*ctx
= talloc_tos();
3075 uint16_t major
, minor
;
3076 uint32_t caplow
, caphigh
;
3080 if (!SERVER_HAS_UNIX_CIFS(cli
)) {
3081 d_printf("Server doesn't support UNIX CIFS extensions.\n");
3085 status
= cli_unix_extensions_version(cli
, &major
, &minor
, &caplow
,
3087 if (!NT_STATUS_IS_OK(status
)) {
3088 d_printf("Can't get UNIX CIFS extensions version from "
3089 "server: %s\n", nt_errstr(status
));
3093 d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major
, (unsigned int)minor
);
3095 caps
= talloc_strdup(ctx
, "");
3099 if (caplow
& CIFS_UNIX_FCNTL_LOCKS_CAP
) {
3100 caps
= talloc_asprintf_append(caps
, "locks ");
3105 if (caplow
& CIFS_UNIX_POSIX_ACLS_CAP
) {
3106 caps
= talloc_asprintf_append(caps
, "acls ");
3111 if (caplow
& CIFS_UNIX_XATTTR_CAP
) {
3112 caps
= talloc_asprintf_append(caps
, "eas ");
3117 if (caplow
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3118 caps
= talloc_asprintf_append(caps
, "pathnames ");
3123 if (caplow
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
) {
3124 caps
= talloc_asprintf_append(caps
, "posix_path_operations ");
3129 if (caplow
& CIFS_UNIX_LARGE_READ_CAP
) {
3130 caps
= talloc_asprintf_append(caps
, "large_read ");
3135 if (caplow
& CIFS_UNIX_LARGE_WRITE_CAP
) {
3136 caps
= talloc_asprintf_append(caps
, "large_write ");
3141 if (caplow
& CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
) {
3142 caps
= talloc_asprintf_append(caps
, "posix_encrypt ");
3147 if (caplow
& CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
) {
3148 caps
= talloc_asprintf_append(caps
, "mandatory_posix_encrypt ");
3154 if (*caps
&& caps
[strlen(caps
)-1] == ' ') {
3155 caps
[strlen(caps
)-1] = '\0';
3158 d_printf("Server supports CIFS capabilities %s\n", caps
);
3160 status
= cli_set_unix_extensions_capabilities(cli
, major
, minor
,
3162 if (!NT_STATUS_IS_OK(status
)) {
3163 d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n",
3168 if (caplow
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3169 CLI_DIRSEP_CHAR
= '/';
3170 *CLI_DIRSEP_STR
= '/';
3171 client_set_cur_dir(CLI_DIRSEP_STR
);
3177 static int cmd_lock(void)
3179 TALLOC_CTX
*ctx
= talloc_tos();
3181 uint64_t start
, len
;
3182 enum brl_type lock_type
;
3186 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3187 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3192 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3193 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3197 if (*buf
== 'r' || *buf
== 'R') {
3198 lock_type
= READ_LOCK
;
3199 } else if (*buf
== 'w' || *buf
== 'W') {
3200 lock_type
= WRITE_LOCK
;
3202 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3206 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3207 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3211 start
= (uint64_t)strtol(buf
, (char **)NULL
, 16);
3213 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3214 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3218 if (CLI_DIRSEP_CHAR
!= '/') {
3219 d_printf("Command \"posix\" must be issued before "
3220 "the \"lock\" command can be used.\n");
3224 len
= (uint64_t)strtol(buf
, (char **)NULL
, 16);
3226 status
= cli_posix_lock(cli
, fnum
, start
, len
, true, lock_type
);
3227 if (!NT_STATUS_IS_OK(status
)) {
3228 d_printf("lock failed %d: %s\n", fnum
, nt_errstr(status
));
3234 static int cmd_unlock(void)
3236 TALLOC_CTX
*ctx
= talloc_tos();
3238 uint64_t start
, len
;
3242 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3243 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
3248 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3249 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
3253 start
= (uint64_t)strtol(buf
, (char **)NULL
, 16);
3255 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3256 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
3260 if (CLI_DIRSEP_CHAR
!= '/') {
3261 d_printf("Command \"posix\" must be issued before "
3262 "the \"unlock\" command can be used.\n");
3266 len
= (uint64_t)strtol(buf
, (char **)NULL
, 16);
3268 status
= cli_posix_unlock(cli
, fnum
, start
, len
);
3269 if (!NT_STATUS_IS_OK(status
)) {
3270 d_printf("unlock failed %d: %s\n", fnum
, nt_errstr(status
));
3276 static int cmd_posix_whoami(void)
3278 TALLOC_CTX
*ctx
= talloc_tos();
3279 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
3282 uint32_t num_gids
= 0;
3283 uint32_t num_sids
= 0;
3284 uint64_t *gids
= NULL
;
3285 struct dom_sid
*sids
= NULL
;
3289 if (CLI_DIRSEP_CHAR
!= '/') {
3290 d_printf("Command \"posix\" must be issued before "
3291 "the \"posix_whoami\" command can be used.\n");
3295 status
= cli_posix_whoami(cli
,
3305 if (!NT_STATUS_IS_OK(status
)) {
3306 d_printf("posix_whoami failed with error %s\n", nt_errstr(status
));
3310 d_printf("GUEST:%s\n", guest
? "True" : "False");
3311 d_printf("UID:%" PRIu64
"\n", uid
);
3312 d_printf("GID:%" PRIu64
"\n", gid
);
3313 d_printf("NUM_GIDS:%" PRIu32
"\n", num_gids
);
3314 for (i
= 0; i
< num_gids
; i
++) {
3315 d_printf("GIDS[%" PRIu32
"]:%" PRIu64
"\n", i
, gids
[i
]);
3317 d_printf("NUM_SIDS:%" PRIu32
"\n", num_sids
);
3318 for (i
= 0; i
< num_sids
; i
++) {
3319 struct dom_sid_buf buf
;
3320 d_printf("SIDS[%" PRIu32
"]:%s\n",
3322 dom_sid_str_buf(&sids
[i
], &buf
));
3328 /****************************************************************************
3330 ****************************************************************************/
3332 static int cmd_rmdir(void)
3334 TALLOC_CTX
*ctx
= talloc_tos();
3337 char *targetname
= NULL
;
3338 struct cli_state
*targetcli
;
3339 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3342 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3343 d_printf("rmdir <dirname>\n");
3346 mask
= talloc_asprintf(ctx
,
3348 client_get_cur_dir(),
3353 mask
= client_clean_name(ctx
, mask
);
3358 status
= cli_resolve_path(ctx
, "",
3360 cli
, mask
, &targetcli
, &targetname
);
3361 if (!NT_STATUS_IS_OK(status
)) {
3362 d_printf("rmdir %s: %s\n", mask
, nt_errstr(status
));
3366 status
= cli_rmdir(targetcli
, targetname
);
3367 if (!NT_STATUS_IS_OK(status
)) {
3368 d_printf("%s removing remote directory file %s\n",
3369 nt_errstr(status
), mask
);
3375 /****************************************************************************
3377 ****************************************************************************/
3379 static int cmd_link(void)
3381 TALLOC_CTX
*ctx
= talloc_tos();
3382 char *oldname
= NULL
;
3383 char *newname
= NULL
;
3386 char *targetname
= NULL
;
3387 struct cli_state
*targetcli
;
3388 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3391 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
3392 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
)) {
3393 d_printf("link <oldname> <newname>\n");
3396 oldname
= talloc_asprintf(ctx
,
3398 client_get_cur_dir(),
3403 oldname
= client_clean_name(ctx
, oldname
);
3404 if (oldname
== NULL
) {
3407 newname
= talloc_asprintf(ctx
,
3409 client_get_cur_dir(),
3414 newname
= client_clean_name(ctx
, newname
);
3415 if (newname
== NULL
) {
3419 status
= cli_resolve_path(ctx
, "",
3421 cli
, oldname
, &targetcli
, &targetname
);
3422 if (!NT_STATUS_IS_OK(status
)) {
3423 d_printf("link %s: %s\n", oldname
, nt_errstr(status
));
3427 if (!SERVER_HAS_UNIX_CIFS(targetcli
)) {
3428 d_printf("Server doesn't support UNIX CIFS calls.\n");
3432 if (CLI_DIRSEP_CHAR
!= '/') {
3433 d_printf("Command \"posix\" must be issued before "
3434 "the \"link\" command can be used.\n");
3438 status
= cli_posix_hardlink(targetcli
, targetname
, newname
);
3439 if (!NT_STATUS_IS_OK(status
)) {
3440 d_printf("%s linking files (%s -> %s)\n",
3441 nt_errstr(status
), newname
, oldname
);
3447 /****************************************************************************
3449 ****************************************************************************/
3451 static int cmd_readlink(void)
3453 TALLOC_CTX
*ctx
= talloc_tos();
3456 char *targetname
= NULL
;
3457 char *linkname
= NULL
;
3458 char *printname
= NULL
;
3460 struct cli_state
*targetcli
;
3461 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3464 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
3465 d_printf("readlink <name>\n");
3468 name
= talloc_asprintf(ctx
,
3470 client_get_cur_dir(),
3475 name
= client_clean_name(ctx
, name
);
3480 status
= cli_resolve_path(ctx
, "",
3482 cli
, name
, &targetcli
, &targetname
);
3483 if (!NT_STATUS_IS_OK(status
)) {
3484 d_printf("readlink %s: %s\n", name
, nt_errstr(status
));
3488 status
= cli_readlink(
3489 cli
, name
, talloc_tos(), &linkname
, &printname
, &flags
);
3490 if (!NT_STATUS_IS_OK(status
)) {
3491 d_printf("%s readlink on file %s\n",
3492 nt_errstr(status
), name
);
3496 d_printf("%s -> %s\n", name
, linkname
);
3498 TALLOC_FREE(linkname
);
3504 /****************************************************************************
3506 ****************************************************************************/
3508 static int cmd_symlink(void)
3510 TALLOC_CTX
*ctx
= talloc_tos();
3511 char *link_target
= NULL
;
3512 char *newname
= NULL
;
3515 struct cli_state
*newcli
;
3516 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3519 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
3520 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
)) {
3521 d_printf("symlink <link_target> <newname>\n");
3524 /* Oldname (link target) must be an untouched blob. */
3527 if (SERVER_HAS_UNIX_CIFS(cli
)) {
3528 if (CLI_DIRSEP_CHAR
!= '/') {
3529 d_printf("Command \"posix\" must be issued before "
3530 "the \"symlink\" command can be used.\n");
3533 newname
= talloc_asprintf(ctx
, "%s%s", client_get_cur_dir(),
3538 newname
= client_clean_name(ctx
, newname
);
3539 if (newname
== NULL
) {
3542 /* New name must be present in share namespace. */
3543 status
= cli_resolve_path(ctx
, "",
3547 if (!NT_STATUS_IS_OK(status
)) {
3548 d_printf("link %s: %s\n", newname
,
3552 status
= cli_posix_symlink(newcli
, link_target
, newname
);
3554 status
= cli_symlink(
3555 cli
, link_target
, buf2
,
3556 buf2
[0] == '\\' ? 0 : SYMLINK_FLAG_RELATIVE
);
3559 if (!NT_STATUS_IS_OK(status
)) {
3560 d_printf("%s symlinking files (%s -> %s)\n",
3561 nt_errstr(status
), newname
, link_target
);
3568 /****************************************************************************
3570 ****************************************************************************/
3572 static int cmd_chmod(void)
3574 TALLOC_CTX
*ctx
= talloc_tos();
3578 char *targetname
= NULL
;
3579 struct cli_state
*targetcli
;
3581 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3584 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
3585 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
)) {
3586 d_printf("chmod mode file\n");
3589 src
= talloc_asprintf(ctx
,
3591 client_get_cur_dir(),
3596 src
= client_clean_name(ctx
, src
);
3601 mode
= (mode_t
)strtol(buf
, NULL
, 8);
3603 status
= cli_resolve_path(ctx
, "",
3605 cli
, src
, &targetcli
, &targetname
);
3606 if (!NT_STATUS_IS_OK(status
)) {
3607 d_printf("chmod %s: %s\n", src
, nt_errstr(status
));
3611 if (!SERVER_HAS_UNIX_CIFS(targetcli
)) {
3612 d_printf("Server doesn't support UNIX CIFS calls.\n");
3616 if (CLI_DIRSEP_CHAR
!= '/') {
3617 d_printf("Command \"posix\" must be issued before "
3618 "the \"chmod\" command can be used.\n");
3622 status
= cli_posix_chmod(targetcli
, targetname
, mode
);
3623 if (!NT_STATUS_IS_OK(status
)) {
3624 d_printf("%s chmod file %s 0%o\n",
3625 nt_errstr(status
), src
, (unsigned int)mode
);
3632 static const char *filetype_to_str(mode_t mode
)
3634 if (S_ISREG(mode
)) {
3635 return "regular file";
3636 } else if (S_ISDIR(mode
)) {
3640 if (S_ISCHR(mode
)) {
3641 return "character device";
3645 if (S_ISBLK(mode
)) {
3646 return "block device";
3650 if (S_ISFIFO(mode
)) {
3655 if (S_ISLNK(mode
)) {
3656 return "symbolic link";
3660 if (S_ISSOCK(mode
)) {
3667 static char rwx_to_str(mode_t m
, mode_t bt
, char ret
)
3676 static char *unix_mode_to_str(char *s
, mode_t m
)
3679 const char *str
= filetype_to_str(m
);
3695 *p
++ = str
[1] == 'y' ? 'l' : 's';
3702 *p
++ = rwx_to_str(m
, S_IRUSR
, 'r');
3703 *p
++ = rwx_to_str(m
, S_IWUSR
, 'w');
3704 *p
++ = rwx_to_str(m
, S_IXUSR
, 'x');
3705 *p
++ = rwx_to_str(m
, S_IRGRP
, 'r');
3706 *p
++ = rwx_to_str(m
, S_IWGRP
, 'w');
3707 *p
++ = rwx_to_str(m
, S_IXGRP
, 'x');
3708 *p
++ = rwx_to_str(m
, S_IROTH
, 'r');
3709 *p
++ = rwx_to_str(m
, S_IWOTH
, 'w');
3710 *p
++ = rwx_to_str(m
, S_IXOTH
, 'x');
3715 /****************************************************************************
3716 Utility function for UNIX getfacl.
3717 ****************************************************************************/
3719 static char *perms_to_string(fstring permstr
, unsigned char perms
)
3721 fstrcpy(permstr
, "---");
3722 if (perms
& SMB_POSIX_ACL_READ
) {
3725 if (perms
& SMB_POSIX_ACL_WRITE
) {
3728 if (perms
& SMB_POSIX_ACL_EXECUTE
) {
3734 /****************************************************************************
3736 ****************************************************************************/
3738 static int cmd_getfacl(void)
3740 TALLOC_CTX
*ctx
= talloc_tos();
3743 char *targetname
= NULL
;
3744 struct cli_state
*targetcli
;
3745 uint16_t major
, minor
;
3746 uint32_t caplow
, caphigh
;
3747 char *retbuf
= NULL
;
3749 SMB_STRUCT_STAT sbuf
;
3750 size_t num_file_acls
= 0;
3751 size_t num_dir_acls
= 0;
3752 size_t expected_buflen
;
3754 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3757 if (!next_token_talloc(ctx
, &cmd_ptr
,&name
,NULL
)) {
3758 d_printf("getfacl filename\n");
3761 src
= talloc_asprintf(ctx
,
3763 client_get_cur_dir(),
3768 src
= client_clean_name(ctx
, src
);
3773 status
= cli_resolve_path(ctx
, "",
3775 cli
, src
, &targetcli
, &targetname
);
3776 if (!NT_STATUS_IS_OK(status
)) {
3777 d_printf("stat %s: %s\n", src
, nt_errstr(status
));
3781 if (!SERVER_HAS_UNIX_CIFS(targetcli
)) {
3782 d_printf("Server doesn't support UNIX CIFS calls.\n");
3786 if (CLI_DIRSEP_CHAR
!= '/') {
3787 d_printf("Command \"posix\" must be issued before "
3788 "the \"getfacl\" command can be used.\n");
3792 status
= cli_unix_extensions_version(targetcli
, &major
, &minor
,
3794 if (!NT_STATUS_IS_OK(status
)) {
3795 d_printf("Can't get UNIX CIFS version from server: %s.\n",
3800 if (!(caplow
& CIFS_UNIX_POSIX_ACLS_CAP
)) {
3801 d_printf("This server supports UNIX extensions "
3802 "but doesn't support POSIX ACLs.\n");
3806 status
= cli_posix_stat(targetcli
, targetname
, &sbuf
);
3807 if (!NT_STATUS_IS_OK(status
)) {
3808 d_printf("%s getfacl doing a stat on file %s\n",
3809 nt_errstr(status
), src
);
3813 status
= cli_posix_getacl(targetcli
, targetname
, ctx
, &rb_size
, &retbuf
);
3814 if (!NT_STATUS_IS_OK(status
)) {
3815 d_printf("%s getfacl file %s\n",
3816 nt_errstr(status
), src
);
3820 /* ToDo : Print out the ACL values. */
3821 if (rb_size
< 6 || SVAL(retbuf
,0) != SMB_POSIX_ACL_VERSION
) {
3822 d_printf("getfacl file %s, unknown POSIX acl version %u.\n",
3823 src
, (unsigned int)CVAL(retbuf
,0) );
3827 num_file_acls
= SVAL(retbuf
,2);
3828 num_dir_acls
= SVAL(retbuf
,4);
3831 * No overflow check, num_*_acls comes from a 16-bit value,
3832 * and we expect expected_buflen (size_t) to be of at least 32
3835 expected_buflen
= SMB_POSIX_ACL_HEADER_SIZE
+
3836 SMB_POSIX_ACL_ENTRY_SIZE
*(num_file_acls
+num_dir_acls
);
3838 if (rb_size
!= expected_buflen
) {
3839 d_printf("getfacl file %s, incorrect POSIX acl buffer size "
3840 "(should be %zu, was %zu).\n",
3847 d_printf("# file: %s\n", src
);
3848 d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf
.st_ex_uid
, (unsigned int)sbuf
.st_ex_gid
);
3850 if (num_file_acls
== 0 && num_dir_acls
== 0) {
3851 d_printf("No acls found.\n");
3854 for (i
= 0; i
< num_file_acls
; i
++) {
3857 unsigned char tagtype
= CVAL(retbuf
, SMB_POSIX_ACL_HEADER_SIZE
+(i
*SMB_POSIX_ACL_ENTRY_SIZE
));
3858 unsigned char perms
= CVAL(retbuf
, SMB_POSIX_ACL_HEADER_SIZE
+(i
*SMB_POSIX_ACL_ENTRY_SIZE
)+1);
3861 case SMB_POSIX_ACL_USER_OBJ
:
3864 case SMB_POSIX_ACL_USER
:
3865 uorg
= IVAL(retbuf
,SMB_POSIX_ACL_HEADER_SIZE
+(i
*SMB_POSIX_ACL_ENTRY_SIZE
)+2);
3866 d_printf("user:%u:", uorg
);
3868 case SMB_POSIX_ACL_GROUP_OBJ
:
3869 d_printf("group::");
3871 case SMB_POSIX_ACL_GROUP
:
3872 uorg
= IVAL(retbuf
,SMB_POSIX_ACL_HEADER_SIZE
+(i
*SMB_POSIX_ACL_ENTRY_SIZE
)+2);
3873 d_printf("group:%u:", uorg
);
3875 case SMB_POSIX_ACL_MASK
:
3878 case SMB_POSIX_ACL_OTHER
:
3879 d_printf("other::");
3882 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
3883 src
, (unsigned int)tagtype
);
3888 d_printf("%s\n", perms_to_string(permstring
, perms
));
3891 for (i
= 0; i
< num_dir_acls
; i
++) {
3894 unsigned char tagtype
= CVAL(retbuf
, SMB_POSIX_ACL_HEADER_SIZE
+((i
+num_file_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
));
3895 unsigned char perms
= CVAL(retbuf
, SMB_POSIX_ACL_HEADER_SIZE
+((i
+num_file_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
)+1);
3898 case SMB_POSIX_ACL_USER_OBJ
:
3899 d_printf("default:user::");
3901 case SMB_POSIX_ACL_USER
:
3902 uorg
= IVAL(retbuf
,SMB_POSIX_ACL_HEADER_SIZE
+((i
+num_file_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
)+2);
3903 d_printf("default:user:%u:", uorg
);
3905 case SMB_POSIX_ACL_GROUP_OBJ
:
3906 d_printf("default:group::");
3908 case SMB_POSIX_ACL_GROUP
:
3909 uorg
= IVAL(retbuf
,SMB_POSIX_ACL_HEADER_SIZE
+((i
+num_file_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
)+2);
3910 d_printf("default:group:%u:", uorg
);
3912 case SMB_POSIX_ACL_MASK
:
3913 d_printf("default:mask::");
3915 case SMB_POSIX_ACL_OTHER
:
3916 d_printf("default:other::");
3919 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
3920 src
, (unsigned int)tagtype
);
3925 d_printf("%s\n", perms_to_string(permstring
, perms
));
3931 /****************************************************************************
3932 Get the EA list of a file
3933 ****************************************************************************/
3935 static int cmd_geteas(void)
3937 TALLOC_CTX
*ctx
= talloc_tos();
3940 char *targetname
= NULL
;
3941 struct cli_state
*targetcli
;
3944 struct ea_struct
*eas
;
3945 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3947 if (!next_token_talloc(ctx
, &cmd_ptr
,&name
,NULL
)) {
3948 d_printf("geteas filename\n");
3951 src
= talloc_asprintf(ctx
,
3953 client_get_cur_dir(),
3958 src
= client_clean_name(ctx
, src
);
3963 status
= cli_resolve_path(ctx
, "",
3965 cli
, src
, &targetcli
, &targetname
);
3966 if (!NT_STATUS_IS_OK(status
)) {
3967 d_printf("stat %s: %s\n", src
, nt_errstr(status
));
3971 status
= cli_get_ea_list_path(targetcli
, targetname
, talloc_tos(),
3973 if (!NT_STATUS_IS_OK(status
)) {
3974 d_printf("cli_get_ea_list_path: %s\n", nt_errstr(status
));
3978 for (i
=0; i
<num_eas
; i
++) {
3979 d_printf("%s (%d) =\n", eas
[i
].name
, (int)eas
[i
].flags
);
3980 dump_data_file(eas
[i
].value
.data
, eas
[i
].value
.length
, false,
3990 /****************************************************************************
3992 ****************************************************************************/
3994 static int cmd_setea(void)
3996 TALLOC_CTX
*ctx
= talloc_tos();
3999 char *eaname
= NULL
;
4000 char *eavalue
= NULL
;
4001 char *targetname
= NULL
;
4002 struct cli_state
*targetcli
;
4003 struct cli_credentials
*creds
= samba_cmdline_get_creds();
4006 if (!next_token_talloc(ctx
, &cmd_ptr
, &name
, NULL
)
4007 || !next_token_talloc(ctx
, &cmd_ptr
, &eaname
, NULL
)) {
4008 d_printf("setea filename eaname value\n");
4011 if (!next_token_talloc(ctx
, &cmd_ptr
, &eavalue
, NULL
)) {
4012 eavalue
= talloc_strdup(ctx
, "");
4014 src
= talloc_asprintf(ctx
,
4016 client_get_cur_dir(),
4021 src
= client_clean_name(ctx
, src
);
4026 status
= cli_resolve_path(ctx
, "",
4028 cli
, src
, &targetcli
, &targetname
);
4029 if (!NT_STATUS_IS_OK(status
)) {
4030 d_printf("stat %s: %s\n", src
, nt_errstr(status
));
4034 status
= cli_set_ea_path(targetcli
, targetname
, eaname
, eavalue
,
4036 if (!NT_STATUS_IS_OK(status
)) {
4037 d_printf("set_ea %s: %s\n", src
, nt_errstr(status
));
4044 /****************************************************************************
4046 ****************************************************************************/
4048 static int cmd_stat(void)
4050 TALLOC_CTX
*ctx
= talloc_tos();
4053 char *targetname
= NULL
;
4054 struct cli_state
*targetcli
;
4056 SMB_STRUCT_STAT sbuf
;
4059 struct cli_credentials
*creds
= samba_cmdline_get_creds();
4062 if (!next_token_talloc(ctx
, &cmd_ptr
,&name
,NULL
)) {
4063 d_printf("stat file\n");
4066 src
= talloc_asprintf(ctx
,
4068 client_get_cur_dir(),
4073 src
= client_clean_name(ctx
, src
);
4078 status
= cli_resolve_path(ctx
, "",
4080 cli
, src
, &targetcli
, &targetname
);
4081 if (!NT_STATUS_IS_OK(status
)) {
4082 d_printf("stat %s: %s\n", src
, nt_errstr(status
));
4086 if (!SERVER_HAS_UNIX_CIFS(targetcli
)) {
4087 d_printf("Server doesn't support UNIX CIFS calls.\n");
4091 if (CLI_DIRSEP_CHAR
!= '/') {
4092 d_printf("Command \"posix\" must be issued before "
4093 "the \"stat\" command can be used.\n");
4097 status
= cli_posix_stat(targetcli
, targetname
, &sbuf
);
4098 if (!NT_STATUS_IS_OK(status
)) {
4099 d_printf("%s stat file %s\n",
4100 nt_errstr(status
), src
);
4104 /* Print out the stat values. */
4105 d_printf("File: %s\n", src
);
4106 d_printf("Size: %-12.0f\tBlocks: %u\t%s\n",
4107 (double)sbuf
.st_ex_size
,
4108 (unsigned int)sbuf
.st_ex_blocks
,
4109 filetype_to_str(sbuf
.st_ex_mode
));
4111 #if defined(S_ISCHR) && defined(S_ISBLK)
4112 if (S_ISCHR(sbuf
.st_ex_mode
) || S_ISBLK(sbuf
.st_ex_mode
)) {
4113 d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n",
4114 (double)sbuf
.st_ex_ino
,
4115 (unsigned int)sbuf
.st_ex_nlink
,
4116 unix_dev_major(sbuf
.st_ex_rdev
),
4117 unix_dev_minor(sbuf
.st_ex_rdev
));
4120 d_printf("Inode: %.0f\tLinks: %u\n",
4121 (double)sbuf
.st_ex_ino
,
4122 (unsigned int)sbuf
.st_ex_nlink
);
4124 d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n",
4125 ((int)sbuf
.st_ex_mode
& 0777),
4126 unix_mode_to_str(mode_str
, sbuf
.st_ex_mode
),
4127 (unsigned int)sbuf
.st_ex_uid
,
4128 (unsigned int)sbuf
.st_ex_gid
);
4130 tmp_time
= convert_timespec_to_time_t(sbuf
.st_ex_atime
);
4131 lt
= localtime(&tmp_time
);
4133 strftime(mode_str
, sizeof(mode_str
), "%Y-%m-%d %T %z", lt
);
4135 fstrcpy(mode_str
, "unknown");
4137 d_printf("Access: %s\n", mode_str
);
4139 tmp_time
= convert_timespec_to_time_t(sbuf
.st_ex_mtime
);
4140 lt
= localtime(&tmp_time
);
4142 strftime(mode_str
, sizeof(mode_str
), "%Y-%m-%d %T %z", lt
);
4144 fstrcpy(mode_str
, "unknown");
4146 d_printf("Modify: %s\n", mode_str
);
4148 tmp_time
= convert_timespec_to_time_t(sbuf
.st_ex_ctime
);
4149 lt
= localtime(&tmp_time
);
4151 strftime(mode_str
, sizeof(mode_str
), "%Y-%m-%d %T %z", lt
);
4153 fstrcpy(mode_str
, "unknown");
4155 d_printf("Change: %s\n", mode_str
);
4161 /****************************************************************************
4163 ****************************************************************************/
4165 static int cmd_chown(void)
4167 TALLOC_CTX
*ctx
= talloc_tos();
4171 char *buf
, *buf2
, *buf3
;
4172 struct cli_state
*targetcli
;
4173 char *targetname
= NULL
;
4174 struct cli_credentials
*creds
= samba_cmdline_get_creds();
4177 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
4178 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
) ||
4179 !next_token_talloc(ctx
, &cmd_ptr
,&buf3
,NULL
)) {
4180 d_printf("chown uid gid file\n");
4184 uid
= (uid_t
)atoi(buf
);
4185 gid
= (gid_t
)atoi(buf2
);
4187 src
= talloc_asprintf(ctx
,
4189 client_get_cur_dir(),
4194 src
= client_clean_name(ctx
, src
);
4198 status
= cli_resolve_path(ctx
, "",
4200 cli
, src
, &targetcli
, &targetname
);
4201 if (!NT_STATUS_IS_OK(status
)) {
4202 d_printf("chown %s: %s\n", src
, nt_errstr(status
));
4206 if (!SERVER_HAS_UNIX_CIFS(targetcli
)) {
4207 d_printf("Server doesn't support UNIX CIFS calls.\n");
4211 if (CLI_DIRSEP_CHAR
!= '/') {
4212 d_printf("Command \"posix\" must be issued before "
4213 "the \"chown\" command can be used.\n");
4217 status
= cli_posix_chown(targetcli
, targetname
, uid
, gid
);
4218 if (!NT_STATUS_IS_OK(status
)) {
4219 d_printf("%s chown file %s uid=%d, gid=%d\n",
4220 nt_errstr(status
), src
, (int)uid
, (int)gid
);
4227 /****************************************************************************
4229 ****************************************************************************/
4231 static int cmd_rename(void)
4233 TALLOC_CTX
*ctx
= talloc_tos();
4236 struct cli_state
*targetcli
;
4239 struct cli_credentials
*creds
= samba_cmdline_get_creds();
4241 bool replace
= false;
4243 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
4244 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
)) {
4245 d_printf("rename <src> <dest> [-f]\n");
4249 src
= talloc_asprintf(ctx
,
4251 client_get_cur_dir(),
4256 src
= client_clean_name(ctx
, src
);
4261 dest
= talloc_asprintf(ctx
,
4263 client_get_cur_dir(),
4268 dest
= client_clean_name(ctx
, dest
);
4273 if (next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
) &&
4274 strcsequal(buf
, "-f")) {
4278 status
= cli_resolve_path(ctx
, "",
4280 cli
, src
, &targetcli
, &targetsrc
);
4281 if (!NT_STATUS_IS_OK(status
)) {
4282 d_printf("rename %s: %s\n", src
, nt_errstr(status
));
4286 status
= cli_resolve_path(ctx
, "",
4288 cli
, dest
, &targetcli
, &targetdest
);
4289 if (!NT_STATUS_IS_OK(status
)) {
4290 d_printf("rename %s: %s\n", dest
, nt_errstr(status
));
4294 status
= cli_rename(targetcli
, targetsrc
, targetdest
, replace
);
4295 if (!NT_STATUS_IS_OK(status
)) {
4296 d_printf("%s renaming files %s -> %s \n",
4306 struct scopy_timing
{
4307 struct timespec tp_start
;
4310 static int scopy_status(off_t written
, void *priv
)
4312 struct timespec tp_end
;
4313 unsigned int scopy_total_time_ms
;
4314 struct scopy_timing
*st
= priv
;
4316 clock_gettime_mono(&tp_end
);
4317 scopy_total_time_ms
= nsec_time_diff(&tp_end
,&st
->tp_start
)/1000000;
4319 DEBUG(5,("Copied %jd bytes at an average %3.1f kb/s\n",
4320 (intmax_t)written
, written
/ (1.024*scopy_total_time_ms
)));
4325 /****************************************************************************
4326 Server-Side copy some file.
4327 ****************************************************************************/
4329 static int cmd_scopy(void)
4331 TALLOC_CTX
*ctx
= talloc_tos();
4334 struct cli_state
*targetcli
;
4337 uint32_t DesiredAccess
, ShareAccess
, CreateDisposition
, CreateOptions
;
4338 struct smb_create_returns cr
;
4339 uint16_t destfnum
= (uint16_t)-1;
4340 uint16_t srcfnum
= (uint16_t)-1;
4342 struct scopy_timing st
;
4344 struct cli_credentials
*creds
= samba_cmdline_get_creds();
4347 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
4348 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
)) {
4349 d_printf("scopy <src> <dest>\n");
4353 src
= talloc_asprintf(ctx
,
4355 client_get_cur_dir(),
4360 src
= client_clean_name(ctx
, src
);
4365 dest
= talloc_asprintf(ctx
,
4367 client_get_cur_dir(),
4372 dest
= client_clean_name(ctx
, dest
);
4377 status
= cli_resolve_path(ctx
, "",
4379 cli
, src
, &targetcli
, &targetsrc
);
4380 if (!NT_STATUS_IS_OK(status
)) {
4381 d_printf("scopy %s: %s\n", src
, nt_errstr(status
));
4385 status
= cli_resolve_path(ctx
, "",
4387 cli
, dest
, &targetcli
, &targetdest
);
4388 if (!NT_STATUS_IS_OK(status
)) {
4389 d_printf("scopy %s: %s\n", dest
, nt_errstr(status
));
4394 DesiredAccess
= (FILE_READ_DATA
|FILE_READ_EA
|FILE_READ_ATTRIBUTES
|
4395 READ_CONTROL_ACCESS
|SYNCHRONIZE_ACCESS
);
4396 ShareAccess
= FILE_SHARE_READ
|FILE_SHARE_DELETE
;
4397 CreateDisposition
= FILE_OPEN
;
4398 CreateOptions
= (FILE_SEQUENTIAL_ONLY
|FILE_NON_DIRECTORY_FILE
|
4399 FILE_OPEN_REPARSE_POINT
);
4400 status
= cli_ntcreate(targetcli
, targetsrc
, 0, DesiredAccess
, 0,
4401 ShareAccess
, CreateDisposition
, CreateOptions
, 0x0,
4403 if (!NT_STATUS_IS_OK(status
)) {
4404 d_printf("Failed to open file %s. %s\n",
4405 targetsrc
, nt_errstr(status
));
4409 DesiredAccess
= (FILE_READ_DATA
|FILE_WRITE_DATA
|FILE_APPEND_DATA
|FILE_READ_EA
|
4410 FILE_WRITE_EA
|FILE_READ_ATTRIBUTES
|FILE_WRITE_ATTRIBUTES
|
4411 DELETE_ACCESS
|READ_CONTROL_ACCESS
|WRITE_DAC_ACCESS
|SYNCHRONIZE_ACCESS
);
4412 ShareAccess
= FILE_SHARE_NONE
;
4413 CreateDisposition
= FILE_CREATE
;
4414 CreateOptions
= FILE_SEQUENTIAL_ONLY
|FILE_NON_DIRECTORY_FILE
;
4415 status
= cli_ntcreate(targetcli
, targetdest
, 0, DesiredAccess
,
4416 FILE_ATTRIBUTE_ARCHIVE
, ShareAccess
, CreateDisposition
,
4417 CreateOptions
, 0x0, &destfnum
, NULL
);
4418 if (!NT_STATUS_IS_OK(status
)) {
4419 d_printf("Failed to create file %s. %s\n",
4420 targetdest
, nt_errstr(status
));
4421 cli_close(targetcli
, srcfnum
);
4425 clock_gettime_mono(&st
.tp_start
);
4426 status
= cli_splice(targetcli
, targetcli
, srcfnum
, destfnum
,
4427 cr
.end_of_file
, 0, 0, &written
, scopy_status
, &st
);
4428 if (!NT_STATUS_IS_OK(status
)) {
4429 d_printf("%s copying file %s -> %s \n",
4436 status
= cli_close(targetcli
, srcfnum
);
4437 if (!NT_STATUS_IS_OK(status
)) {
4438 d_printf("Error %s closing remote source file\n", nt_errstr(status
));
4441 status
= cli_close(targetcli
, destfnum
);
4442 if (!NT_STATUS_IS_OK(status
)) {
4443 d_printf("Error %s closing remote dest file\n", nt_errstr(status
));
4450 /****************************************************************************
4451 Print the volume name.
4452 ****************************************************************************/
4454 static int cmd_volume(void)
4457 uint32_t serial_num
;
4461 status
= cli_get_fs_volume_info(cli
, talloc_tos(),
4462 &volname
, &serial_num
,
4464 if (!NT_STATUS_IS_OK(status
)) {
4465 d_printf("Error %s getting volume info\n", nt_errstr(status
));
4469 d_printf("Volume: |%s| serial number 0x%x\n",
4470 volname
, (unsigned int)serial_num
);
4474 /****************************************************************************
4475 Hard link files using the NT call.
4476 ****************************************************************************/
4478 static int cmd_hardlink(void)
4480 TALLOC_CTX
*ctx
= talloc_tos();
4483 struct cli_state
*targetcli
;
4485 struct cli_credentials
*creds
= samba_cmdline_get_creds();
4488 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
) ||
4489 !next_token_talloc(ctx
, &cmd_ptr
,&buf2
,NULL
)) {
4490 d_printf("hardlink <src> <dest>\n");
4494 src
= talloc_asprintf(ctx
,
4496 client_get_cur_dir(),
4501 src
= client_clean_name(ctx
, src
);
4506 dest
= talloc_asprintf(ctx
,
4508 client_get_cur_dir(),
4513 dest
= client_clean_name(ctx
, dest
);
4518 status
= cli_resolve_path(ctx
, "",
4520 cli
, src
, &targetcli
, &targetname
);
4521 if (!NT_STATUS_IS_OK(status
)) {
4522 d_printf("hardlink %s: %s\n", src
, nt_errstr(status
));
4526 status
= cli_hardlink(targetcli
, targetname
, dest
);
4527 if (!NT_STATUS_IS_OK(status
)) {
4528 d_printf("%s doing an NT hard link of files\n",
4536 /****************************************************************************
4537 Toggle the prompt flag.
4538 ****************************************************************************/
4540 static int cmd_prompt(void)
4543 DEBUG(2,("prompting is now %s\n",prompt
?"on":"off"));
4547 /****************************************************************************
4548 Set the newer than time.
4549 ****************************************************************************/
4551 static int cmd_newer(void)
4553 TALLOC_CTX
*ctx
= talloc_tos();
4556 SMB_STRUCT_STAT sbuf
;
4558 ok
= next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
);
4559 if (ok
&& (sys_stat(buf
, &sbuf
, false) == 0)) {
4560 newer_than
= convert_timespec_to_time_t(sbuf
.st_ex_mtime
);
4561 DEBUG(1,("Getting files newer than %s",
4562 time_to_asc(newer_than
)));
4567 if (ok
&& newer_than
== 0) {
4568 d_printf("Error setting newer-than time\n");
4575 /****************************************************************************
4576 Watch directory changes
4577 ****************************************************************************/
4579 static int cmd_notify(void)
4581 TALLOC_CTX
*frame
= talloc_stackframe();
4586 name
= talloc_strdup(talloc_tos(), client_get_cur_dir());
4590 if (!next_token_talloc(talloc_tos(), &cmd_ptr
, &buf
, NULL
)) {
4593 name
= talloc_asprintf_append(name
, "%s", buf
);
4597 name
= client_clean_name(talloc_tos(), name
);
4601 status
= cli_ntcreate(
4602 cli
, name
, 0, FILE_READ_DATA
, 0,
4603 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
4604 FILE_OPEN
, 0, 0, &fnum
, NULL
);
4605 if (!NT_STATUS_IS_OK(status
)) {
4606 d_printf("Could not open file: %s\n", nt_errstr(status
));
4612 uint32_t num_changes
= 0;
4613 struct notify_change
*changes
= NULL
;
4615 status
= cli_notify(cli
, fnum
, 1000, FILE_NOTIFY_CHANGE_ALL
,
4617 talloc_tos(), &num_changes
, &changes
);
4618 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOTIFY_ENUM_DIR
)) {
4619 printf("NOTIFY_ENUM_DIR\n");
4620 status
= NT_STATUS_OK
;
4622 if (!NT_STATUS_IS_OK(status
)) {
4623 d_printf("notify returned %s\n",
4627 for (i
=0; i
<num_changes
; i
++) {
4628 printf("%4.4x %s\n", changes
[i
].action
,
4631 TALLOC_FREE(changes
);
4634 d_printf("notify <dir name>\n");
4640 /****************************************************************************
4641 Set the archive level.
4642 ****************************************************************************/
4644 static int cmd_archive(void)
4646 TALLOC_CTX
*ctx
= talloc_tos();
4649 if (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
4650 archive_level
= atoi(buf
);
4652 d_printf("Archive level is %d\n",archive_level
);
4658 /****************************************************************************
4659 Toggle the backup_intent state.
4660 ****************************************************************************/
4662 static int cmd_backup(void)
4664 backup_intent
= !backup_intent
;
4665 cli_set_backup_intent(cli
, backup_intent
);
4666 DEBUG(2,("backup intent is now %s\n",backup_intent
?"on":"off"));
4670 /****************************************************************************
4671 Toggle the lowercaseflag.
4672 ****************************************************************************/
4674 static int cmd_lowercase(void)
4676 lowercase
= !lowercase
;
4677 DEBUG(2,("filename lowercasing is now %s\n",lowercase
?"on":"off"));
4681 /****************************************************************************
4682 Toggle the case sensitive flag.
4683 ****************************************************************************/
4685 static int cmd_setcase(void)
4687 bool orig_case_sensitive
= cli_set_case_sensitive(cli
, false);
4689 cli_set_case_sensitive(cli
, !orig_case_sensitive
);
4690 DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive
?
4695 /****************************************************************************
4696 Toggle the showacls flag.
4697 ****************************************************************************/
4699 static int cmd_showacls(void)
4701 showacls
= !showacls
;
4702 DEBUG(2,("showacls is now %s\n",showacls
?"on":"off"));
4707 /****************************************************************************
4708 Toggle the recurse flag.
4709 ****************************************************************************/
4711 static int cmd_recurse(void)
4714 DEBUG(2,("directory recursion is now %s\n",recurse
?"on":"off"));
4718 /****************************************************************************
4719 Toggle the translate flag.
4720 ****************************************************************************/
4722 static int cmd_translate(void)
4724 translation
= !translation
;
4725 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
4726 translation
?"on":"off"));
4730 /****************************************************************************
4732 ****************************************************************************/
4734 static int cmd_lcd(void)
4736 TALLOC_CTX
*ctx
= talloc_tos();
4740 if (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
4741 if (chdir(buf
) == -1) {
4742 d_printf("chdir to %s failed (%s)\n",
4743 buf
, strerror(errno
));
4750 DEBUG(2,("the local directory is now %s\n",d
));
4755 /****************************************************************************
4756 Get a file restarting at end of local file.
4757 ****************************************************************************/
4759 static int cmd_reget(void)
4761 TALLOC_CTX
*ctx
= talloc_tos();
4762 char *local_name
= NULL
;
4763 char *remote_name
= NULL
;
4767 remote_name
= talloc_strdup(ctx
, client_get_cur_dir());
4772 if (!next_token_talloc(ctx
, &cmd_ptr
, &fname
, NULL
)) {
4773 d_printf("reget <filename>\n");
4776 remote_name
= talloc_asprintf_append(remote_name
, "%s", fname
);
4780 remote_name
= client_clean_name(ctx
,remote_name
);
4786 next_token_talloc(ctx
, &cmd_ptr
, &p
, NULL
);
4791 return do_get(remote_name
, local_name
, true);
4794 /****************************************************************************
4795 Put a file restarting at end of local file.
4796 ****************************************************************************/
4798 static int cmd_reput(void)
4800 TALLOC_CTX
*ctx
= talloc_tos();
4801 char *local_name
= NULL
;
4802 char *remote_name
= NULL
;
4806 remote_name
= talloc_strdup(ctx
, client_get_cur_dir());
4811 if (!next_token_talloc(ctx
, &cmd_ptr
, &local_name
, NULL
)) {
4812 d_printf("reput <filename>\n");
4816 if (!file_exist_stat(local_name
, &st
, false)) {
4817 d_printf("%s does not exist\n", local_name
);
4821 if (next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
)) {
4822 remote_name
= talloc_asprintf_append(remote_name
,
4825 remote_name
= talloc_asprintf_append(remote_name
,
4832 remote_name
= client_clean_name(ctx
, remote_name
);
4837 return do_put(remote_name
, local_name
, true);
4840 /****************************************************************************
4842 ****************************************************************************/
4844 static void browse_fn(const char *name
, uint32_t m
,
4845 const char *comment
, void *state
)
4847 const char *typestr
= "";
4850 case STYPE_DISKTREE
:
4854 typestr
= "Printer";
4863 /* FIXME: If the remote machine returns non-ascii characters
4864 in any of these fields, they can corrupt the output. We
4865 should remove them. */
4867 d_printf("\t%-15s %-10.10s%s\n",
4868 name
,typestr
,comment
);
4870 d_printf ("%s|%s|%s\n",typestr
,name
,comment
);
4874 static bool browse_host_rpc(bool sort
)
4877 struct rpc_pipe_client
*pipe_hnd
= NULL
;
4878 TALLOC_CTX
*frame
= talloc_stackframe();
4880 struct srvsvc_NetShareInfoCtr info_ctr
;
4881 struct srvsvc_NetShareCtr1 ctr1
;
4882 uint32_t resume_handle
= 0;
4883 uint32_t total_entries
= 0;
4885 struct dcerpc_binding_handle
*b
;
4887 status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_srvsvc
,
4890 if (!NT_STATUS_IS_OK(status
)) {
4891 DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
4892 nt_errstr(status
)));
4897 b
= pipe_hnd
->binding_handle
;
4899 ZERO_STRUCT(info_ctr
);
4903 info_ctr
.ctr
.ctr1
= &ctr1
;
4905 status
= dcerpc_srvsvc_NetShareEnumAll(b
, frame
,
4913 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
4914 TALLOC_FREE(pipe_hnd
);
4919 for (i
=0; i
< info_ctr
.ctr
.ctr1
->count
; i
++) {
4920 struct srvsvc_NetShareInfo1 info
= info_ctr
.ctr
.ctr1
->array
[i
];
4921 browse_fn(info
.name
, info
.type
, info
.comment
, NULL
);
4924 TALLOC_FREE(pipe_hnd
);
4929 /****************************************************************************
4930 Try and browse available connections on a host.
4931 ****************************************************************************/
4933 static bool browse_host(bool sort
)
4938 d_printf("\n\tSharename Type Comment\n");
4939 d_printf("\t--------- ---- -------\n");
4942 if (browse_host_rpc(sort
)) {
4946 if (smbXcli_conn_protocol(cli
->conn
) > PROTOCOL_NT1
) {
4950 ret
= cli_RNetShareEnum(cli
, browse_fn
, NULL
);
4952 NTSTATUS status
= cli_nt_error(cli
);
4953 d_printf("Error returning browse list: %s\n",
4960 /****************************************************************************
4962 ****************************************************************************/
4964 static void server_fn(const char *name
, uint32_t m
,
4965 const char *comment
, void *state
)
4969 d_printf("\t%-16s %s\n", name
, comment
);
4971 d_printf("%s|%s|%s\n",(char *)state
, name
, comment
);
4975 /****************************************************************************
4976 Try and browse available connections on a host.
4977 ****************************************************************************/
4979 static bool list_servers(const char *wk_grp
)
4983 if (!cli
->server_domain
)
4987 d_printf("\n\tServer Comment\n");
4988 d_printf("\t--------- -------\n");
4990 fstrcpy( state
, "Server" );
4991 cli_NetServerEnum(cli
, cli
->server_domain
, SV_TYPE_ALL
, server_fn
,
4995 d_printf("\n\tWorkgroup Master\n");
4996 d_printf("\t--------- -------\n");
4999 fstrcpy( state
, "Workgroup" );
5000 cli_NetServerEnum(cli
, cli
->server_domain
, SV_TYPE_DOMAIN_ENUM
,
5005 /****************************************************************************
5006 Print or set current VUID
5007 ****************************************************************************/
5009 static int cmd_vuid(void)
5011 TALLOC_CTX
*ctx
= talloc_tos();
5014 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
5015 d_printf("Current VUID is %d\n",
5016 cli_state_get_uid(cli
));
5020 cli_state_set_uid(cli
, atoi(buf
));
5024 /****************************************************************************
5025 Setup a new VUID, by issuing a session setup
5026 ****************************************************************************/
5028 static int cmd_logon(void)
5030 TALLOC_CTX
*ctx
= talloc_tos();
5031 char *l_username
, *l_password
;
5032 struct cli_credentials
*creds
= NULL
;
5035 if (!next_token_talloc(ctx
, &cmd_ptr
,&l_username
,NULL
)) {
5036 d_printf("logon <username> [<password>]\n");
5040 if (!next_token_talloc(ctx
, &cmd_ptr
,&l_password
,NULL
)) {
5041 char pwd
[256] = {0};
5044 rc
= samba_getpass("Password: ", pwd
, sizeof(pwd
), false, false);
5046 l_password
= talloc_strdup(ctx
, pwd
);
5053 creds
= cli_session_creds_init(ctx
,
5058 false, /* use_kerberos */
5059 false, /* fallback_after_kerberos */
5060 false, /* use_ccache */
5061 false); /* password_is_nt_hash */
5062 if (creds
== NULL
) {
5063 d_printf("cli_session_creds_init() failed.\n");
5066 nt_status
= cli_session_setup_creds(cli
, creds
);
5068 if (!NT_STATUS_IS_OK(nt_status
)) {
5069 d_printf("session setup failed: %s\n", nt_errstr(nt_status
));
5073 d_printf("Current VUID is %d\n", cli_state_get_uid(cli
));
5081 static int cmd_logoff(void)
5085 status
= cli_ulogoff(cli
);
5086 if (!NT_STATUS_IS_OK(status
)) {
5087 d_printf("logoff failed: %s\n", nt_errstr(status
));
5091 d_printf("logoff successful\n");
5097 * tree connect (connect to a share)
5100 static int cmd_tcon(void)
5102 TALLOC_CTX
*ctx
= talloc_tos();
5106 if (!next_token_talloc(ctx
, &cmd_ptr
, &sharename
, NULL
)) {
5107 d_printf("tcon <sharename>\n");
5115 status
= cli_tree_connect(cli
, sharename
, "?????", NULL
);
5116 if (!NT_STATUS_IS_OK(status
)) {
5117 d_printf("tcon failed: %s\n", nt_errstr(status
));
5121 talloc_free(sharename
);
5123 d_printf("tcon to %s successful, tid: %u\n", sharename
,
5124 cli_state_get_tid(cli
));
5129 * tree disconnect (disconnect from a share)
5132 static int cmd_tdis(void)
5136 status
= cli_tdis(cli
);
5137 if (!NT_STATUS_IS_OK(status
)) {
5138 d_printf("tdis failed: %s\n", nt_errstr(status
));
5142 d_printf("tdis successful\n");
5151 static int cmd_tid(void)
5153 TALLOC_CTX
*ctx
= talloc_tos();
5156 if (!next_token_talloc(ctx
, &cmd_ptr
, &tid_str
, NULL
)) {
5157 if (cli_state_has_tcon(cli
)) {
5158 d_printf("current tid is %d\n", cli_state_get_tid(cli
));
5160 d_printf("no tcon currently\n");
5163 uint32_t tid
= atoi(tid_str
);
5164 if (!cli_state_has_tcon(cli
)) {
5165 d_printf("no tcon currently\n");
5167 cli_state_set_tid(cli
, tid
);
5174 /****************************************************************************
5175 list active connections
5176 ****************************************************************************/
5178 static int cmd_list_connect(void)
5180 cli_cm_display(cli
);
5184 /****************************************************************************
5185 display the current active client connection
5186 ****************************************************************************/
5188 static int cmd_show_connect( void )
5190 TALLOC_CTX
*ctx
= talloc_tos();
5191 struct cli_state
*targetcli
;
5193 struct cli_credentials
*creds
= samba_cmdline_get_creds();
5196 status
= cli_resolve_path(ctx
, "",
5199 client_get_cur_dir(), &targetcli
,
5201 if (!NT_STATUS_IS_OK(status
)) {
5202 d_printf("showconnect %s: %s\n", cur_dir
, nt_errstr(status
));
5206 d_printf("//%s/%s\n", smbXcli_conn_remote_name(targetcli
->conn
), targetcli
->share
);
5211 * cmd_utimes - interactive command to set the four times
5213 * Read a filename and four times from the client command line and update
5214 * the file times. A value of -1 for a time means don't change.
5216 static int cmd_utimes(void)
5220 struct timespec times
[4] = {{0}};
5221 struct timeval_buf tbuf
[4];
5225 TALLOC_CTX
*ctx
= talloc_new(NULL
);
5232 ok
= next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
);
5234 d_printf("utimes <filename> <create-time> <access-time> "
5235 "<write-time> <change-time>\n");
5236 d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
5237 "or -1 for no change\n");
5242 fname
= talloc_asprintf(ctx
,
5244 client_get_cur_dir(),
5246 if (fname
== NULL
) {
5250 fname
= client_clean_name(ctx
, fname
);
5251 if (fname
== NULL
) {
5256 while (next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
) &&
5258 const char *s
= buf
;
5259 struct tm tm
= {0,};
5263 if (strlen(s
) == 2 && strcmp(s
, "-1") == 0) {
5264 times
[time_count
] = make_omit_timespec();
5269 ret
= strptime(s
, "%y:%m:%d-%H:%M:%S", &tm
);
5272 ret
= strptime(s
, "%Y:%m:%d-%H:%M:%S", &tm
);
5275 /* We could not match all the chars, so print error */
5276 if (ret
== NULL
|| *ret
!= 0) {
5277 d_printf("Invalid date format: %s\n", s
);
5278 d_printf("utimes <filename> <create-time> "
5279 "<access-time> <write-time> <change-time>\n");
5280 d_printf("Dates should be in [YY]YY:MM:DD-HH:MM:SS "
5281 "format or -1 for no change\n");
5286 /* Convert tm to a time_t */
5288 times
[time_count
] = (struct timespec
){.tv_sec
= t
};
5292 if (time_count
< 4) {
5293 d_printf("Insufficient dates: %d\n", time_count
);
5294 d_printf("utimes <filename> <create-time> <access-time> "
5295 "<write-time> <change-time>\n");
5296 d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
5297 "or -1 for no change\n");
5302 DEBUG(10, ("times\nCreate: %sAccess: %s Write: %sChange: %s\n",
5303 timespec_string_buf(×
[0], false, &tbuf
[0]),
5304 timespec_string_buf(×
[1], false, &tbuf
[1]),
5305 timespec_string_buf(×
[2], false, &tbuf
[2]),
5306 timespec_string_buf(×
[3], false, &tbuf
[3])));
5308 status
= cli_setpathinfo_ext(
5309 cli
, fname
, times
[0], times
[1], times
[2], times
[3],
5311 if (!NT_STATUS_IS_OK(status
)) {
5312 d_printf("cli_setpathinfo_ext failed: %s\n",
5323 * set_remote_attr - set DOS attributes of a remote file
5324 * @filename: path to the file name
5325 * @new_attr: attribute bit mask to use
5326 * @mode: one of ATTR_SET or ATTR_UNSET
5328 * Update the file attributes with the one provided.
5330 int set_remote_attr(const char *filename
, uint32_t new_attr
, int mode
)
5332 extern struct cli_state
*cli
;
5336 status
= cli_getatr(cli
, filename
, &old_attr
, NULL
, NULL
);
5337 if (!NT_STATUS_IS_OK(status
)) {
5338 d_printf("cli_getatr failed: %s\n", nt_errstr(status
));
5342 if (mode
== ATTR_SET
) {
5343 new_attr
|= old_attr
;
5345 new_attr
= old_attr
& ~new_attr
;
5348 status
= cli_setatr(cli
, filename
, new_attr
, 0);
5349 if (!NT_STATUS_IS_OK(status
)) {
5350 d_printf("cli_setatr failed: %s\n", nt_errstr(status
));
5358 * cmd_setmode - interactive command to set DOS attributes
5360 * Read a filename and mode from the client command line and update
5361 * the file DOS attributes.
5363 int cmd_setmode(void)
5367 uint32_t attr
[2] = {0};
5368 int mode
= ATTR_SET
;
5371 TALLOC_CTX
*ctx
= talloc_new(NULL
);
5376 ok
= next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
);
5378 d_printf("setmode <filename> <[+|-]rsha>\n");
5383 fname
= talloc_asprintf(ctx
,
5385 client_get_cur_dir(),
5387 if (fname
== NULL
) {
5391 fname
= client_clean_name(ctx
, fname
);
5392 if (fname
== NULL
) {
5397 while (next_token_talloc(ctx
, &cmd_ptr
, &buf
, NULL
)) {
5398 const char *s
= buf
;
5409 attr
[mode
] |= FILE_ATTRIBUTE_READONLY
;
5412 attr
[mode
] |= FILE_ATTRIBUTE_HIDDEN
;
5415 attr
[mode
] |= FILE_ATTRIBUTE_SYSTEM
;
5418 attr
[mode
] |= FILE_ATTRIBUTE_ARCHIVE
;
5421 d_printf("setmode <filename> <perm=[+|-]rsha>\n");
5428 if (attr
[ATTR_SET
] == 0 && attr
[ATTR_UNSET
] == 0) {
5429 d_printf("setmode <filename> <[+|-]rsha>\n");
5434 DEBUG(2, ("perm set %d %d\n", attr
[ATTR_SET
], attr
[ATTR_UNSET
]));
5436 /* ignore return value: server might not store DOS attributes */
5437 set_remote_attr(fname
, attr
[ATTR_SET
], ATTR_SET
);
5438 set_remote_attr(fname
, attr
[ATTR_UNSET
], ATTR_UNSET
);
5444 /****************************************************************************
5446 ***************************************************************************/
5448 int cmd_iosize(void)
5450 TALLOC_CTX
*ctx
= talloc_tos();
5453 struct cli_credentials
*creds
= samba_cmdline_get_creds();
5455 (cli_credentials_get_smb_encryption(creds
) ==
5456 SMB_ENCRYPTION_REQUIRED
);
5458 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
5459 if (smbXcli_conn_protocol(cli
->conn
) < PROTOCOL_SMB2_02
) {
5461 d_printf("iosize <n> or iosize 0x<n>. "
5462 "Minimum is 0 (default), "
5463 "max is 16776960 (0xFFFF00)\n");
5465 d_printf("iosize <n> or iosize 0x<n>. "
5466 "(Encrypted connection) ,"
5467 "Minimum is 0 (default), "
5468 "max is 130048 (0x1FC00)\n");
5471 d_printf("iosize <n> or iosize 0x<n>.\n");
5476 iosize
= strtol(buf
,NULL
,0);
5477 if (smbXcli_conn_protocol(cli
->conn
) < PROTOCOL_SMB2_02
) {
5478 if (smb_encrypt
&& (iosize
< 0 || iosize
> 0xFC00)) {
5479 d_printf("iosize out of range for encrypted "
5480 "connection (min = 0 (default), "
5481 "max = 130048 (0x1FC00)\n");
5483 } else if (!smb_encrypt
&& (iosize
< 0 || iosize
> 0xFFFF00)) {
5484 d_printf("iosize out of range (min = 0 (default), "
5485 "max = 16776960 (0xFFFF00)\n");
5490 io_bufsize
= iosize
;
5491 d_printf("iosize is now %d\n", io_bufsize
);
5495 /****************************************************************************
5497 ***************************************************************************/
5499 static int cmd_timeout(void)
5501 TALLOC_CTX
*ctx
= talloc_tos();
5504 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
5505 unsigned int old_timeout
= cli_set_timeout(cli
, 0);
5506 cli_set_timeout(cli
, old_timeout
);
5507 d_printf("timeout <n> (per-operation timeout "
5508 "in seconds - currently %u).\n",
5513 io_timeout
= strtol(buf
,NULL
,0);
5514 cli_set_timeout(cli
, io_timeout
*1000);
5515 d_printf("io_timeout per operation is now %d\n", io_timeout
);
5520 /****************************************************************************
5522 ****************************************************************************/
5523 static int cmd_history(void)
5525 #if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
5529 hlist
= history_list();
5531 for (i
= 0; hlist
&& hlist
[i
]; i
++) {
5532 DEBUG(0, ("%d: %s\n", i
, hlist
[i
]->line
));
5535 DEBUG(0,("no history without readline support\n"));
5541 /* Some constants for completing filename arguments */
5543 #define COMPL_NONE 0 /* No completions */
5544 #define COMPL_REMOTE 1 /* Complete remote filename */
5545 #define COMPL_LOCAL 2 /* Complete local filename */
5547 /* This defines the commands supported by this client.
5548 * NOTE: The "!" must be the last one in the list because it's fn pointer
5549 * field is NULL, and NULL in that field is used in process_tok()
5550 * (below) to indicate the end of the list. crh
5555 const char *description
;
5556 char compl_args
[2]; /* Completion argument info */
5558 {"?",cmd_help
,"[command] give help on a command",{COMPL_NONE
,COMPL_NONE
}},
5559 {"allinfo",cmd_allinfo
,"<file> show all available info",
5560 {COMPL_REMOTE
,COMPL_NONE
}},
5561 {"altname",cmd_altname
,"<file> show alt name",{COMPL_REMOTE
,COMPL_NONE
}},
5562 {"archive",cmd_archive
,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE
,COMPL_NONE
}},
5563 {"backup",cmd_backup
,"toggle backup intent state",{COMPL_NONE
,COMPL_NONE
}},
5564 {"blocksize",cmd_block
,"blocksize <number> (default 20)",{COMPL_NONE
,COMPL_NONE
}},
5565 {"cancel",cmd_cancel
,"<jobid> cancel a print queue entry",{COMPL_NONE
,COMPL_NONE
}},
5566 {"case_sensitive",cmd_setcase
,"toggle the case sensitive flag to server",{COMPL_NONE
,COMPL_NONE
}},
5567 {"cd",cmd_cd
,"[directory] change/report the remote directory",{COMPL_REMOTE
,COMPL_NONE
}},
5568 {"chmod",cmd_chmod
,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE
,COMPL_NONE
}},
5569 {"chown",cmd_chown
,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE
,COMPL_NONE
}},
5570 {"close",cmd_close
,"<fid> close a file given a fid",{COMPL_REMOTE
,COMPL_NONE
}},
5571 {"del",cmd_del
,"<mask> delete all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
5572 {"deltree",cmd_deltree
,"<mask> recursively delete all matching files and directories",{COMPL_REMOTE
,COMPL_NONE
}},
5573 {"dir",cmd_dir
,"<mask> list the contents of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
5574 {"du",cmd_du
,"<mask> computes the total size of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
5575 {"echo",cmd_echo
,"ping the server",{COMPL_NONE
,COMPL_NONE
}},
5576 {"exit",cmd_quit
,"logoff the server",{COMPL_NONE
,COMPL_NONE
}},
5577 {"get",cmd_get
,"<remote name> [local name] get a file",{COMPL_REMOTE
,COMPL_LOCAL
}},
5578 {"getfacl",cmd_getfacl
,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE
,COMPL_NONE
}},
5579 {"geteas", cmd_geteas
, "<file name> get the EA list of a file",
5580 {COMPL_REMOTE
, COMPL_NONE
}},
5581 {"hardlink",cmd_hardlink
,"<src> <dest> create a Windows hard link",{COMPL_REMOTE
,COMPL_REMOTE
}},
5582 {"help",cmd_help
,"[command] give help on a command",{COMPL_NONE
,COMPL_NONE
}},
5583 {"history",cmd_history
,"displays the command history",{COMPL_NONE
,COMPL_NONE
}},
5584 {"iosize",cmd_iosize
,"iosize <number> (default 64512)",{COMPL_NONE
,COMPL_NONE
}},
5585 {"lcd",cmd_lcd
,"[directory] change/report the local current working directory",{COMPL_LOCAL
,COMPL_NONE
}},
5586 {"link",cmd_link
,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE
,COMPL_REMOTE
}},
5587 {"lock",cmd_lock
,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE
,COMPL_REMOTE
}},
5588 {"lowercase",cmd_lowercase
,"toggle lowercasing of filenames for get",{COMPL_NONE
,COMPL_NONE
}},
5589 {"ls",cmd_dir
,"<mask> list the contents of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
5590 {"l",cmd_dir
,"<mask> list the contents of the current directory",{COMPL_REMOTE
,COMPL_NONE
}},
5591 {"mask",cmd_select
,"<mask> mask all filenames against this",{COMPL_REMOTE
,COMPL_NONE
}},
5592 {"md",cmd_mkdir
,"<directory> make a directory",{COMPL_NONE
,COMPL_NONE
}},
5593 {"mget",cmd_mget
,"<mask> get all the matching files",{COMPL_REMOTE
,COMPL_NONE
}},
5594 {"mkdir",cmd_mkdir
,"<directory> make a directory",{COMPL_NONE
,COMPL_NONE
}},
5595 {"more",cmd_more
,"<remote name> view a remote file with your pager",{COMPL_REMOTE
,COMPL_NONE
}},
5596 {"mput",cmd_mput
,"<mask> put all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
5597 {"newer",cmd_newer
,"<file> only mget files newer than the specified local file",{COMPL_LOCAL
,COMPL_NONE
}},
5598 {"notify",cmd_notify
,"<file>Get notified of dir changes",{COMPL_REMOTE
,COMPL_NONE
}},
5599 {"open",cmd_open
,"<mask> open a file",{COMPL_REMOTE
,COMPL_NONE
}},
5600 {"posix", cmd_posix
, "turn on all POSIX capabilities", {COMPL_REMOTE
,COMPL_NONE
}},
5601 {"posix_encrypt",cmd_posix_encrypt
,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE
,COMPL_NONE
}},
5602 {"posix_open",cmd_posix_open
,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE
,COMPL_NONE
}},
5603 {"posix_mkdir",cmd_posix_mkdir
,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE
,COMPL_NONE
}},
5604 {"posix_rmdir",cmd_posix_rmdir
,"<name> removes a directory using POSIX interface",{COMPL_REMOTE
,COMPL_NONE
}},
5605 {"posix_unlink",cmd_posix_unlink
,"<name> removes a file using POSIX interface",{COMPL_REMOTE
,COMPL_NONE
}},
5606 {"posix_whoami",cmd_posix_whoami
,"return logged on user information "
5607 "using POSIX interface",{COMPL_REMOTE
,COMPL_NONE
}},
5608 {"print",cmd_print
,"<file name> print a file",{COMPL_NONE
,COMPL_NONE
}},
5609 {"prompt",cmd_prompt
,"toggle prompting for filenames for mget and mput",{COMPL_NONE
,COMPL_NONE
}},
5610 {"put",cmd_put
,"<local name> [remote name] put a file",{COMPL_LOCAL
,COMPL_REMOTE
}},
5611 {"pwd",cmd_pwd
,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE
,COMPL_NONE
}},
5612 {"q",cmd_quit
,"logoff the server",{COMPL_NONE
,COMPL_NONE
}},
5613 {"queue",cmd_queue
,"show the print queue",{COMPL_NONE
,COMPL_NONE
}},
5614 {"quit",cmd_quit
,"logoff the server",{COMPL_NONE
,COMPL_NONE
}},
5615 {"readlink",cmd_readlink
,"filename Do a UNIX extensions readlink call on a symlink",{COMPL_REMOTE
,COMPL_REMOTE
}},
5616 {"rd",cmd_rmdir
,"<directory> remove a directory",{COMPL_NONE
,COMPL_NONE
}},
5617 {"recurse",cmd_recurse
,"toggle directory recursion for mget and mput",{COMPL_NONE
,COMPL_NONE
}},
5618 {"reget",cmd_reget
,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE
,COMPL_LOCAL
}},
5619 {"rename",cmd_rename
,"<src> <dest> rename some files",{COMPL_REMOTE
,COMPL_REMOTE
}},
5620 {"reput",cmd_reput
,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL
,COMPL_REMOTE
}},
5621 {"rm",cmd_del
,"<mask> delete all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
5622 {"rmdir",cmd_rmdir
,"<directory> remove a directory",{COMPL_REMOTE
,COMPL_NONE
}},
5623 {"showacls",cmd_showacls
,"toggle if ACLs are shown or not",{COMPL_NONE
,COMPL_NONE
}},
5624 {"setea", cmd_setea
, "<file name> <eaname> <eaval> Set an EA of a file",
5625 {COMPL_REMOTE
, COMPL_LOCAL
}},
5626 {"setmode",cmd_setmode
,"<file name> <setmode string> change modes of file",{COMPL_REMOTE
,COMPL_NONE
}},
5627 {"scopy",cmd_scopy
,"<src> <dest> server-side copy file",{COMPL_REMOTE
,COMPL_REMOTE
}},
5628 {"stat",cmd_stat
,"<file name> Do a UNIX extensions stat call on a file",{COMPL_REMOTE
,COMPL_NONE
}},
5629 {"symlink",cmd_symlink
,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE
,COMPL_REMOTE
}},
5630 {"tar",cmd_tar
,"tar <c|x>[IXFvbgNan] current directory to/from <file name>",{COMPL_NONE
,COMPL_NONE
}},
5631 {"tarmode",cmd_tarmode
,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE
,COMPL_NONE
}},
5632 {"timeout",cmd_timeout
,"timeout <number> - set the per-operation timeout in seconds (default 20)",{COMPL_NONE
,COMPL_NONE
}},
5633 {"translate",cmd_translate
,"toggle text translation for printing",{COMPL_NONE
,COMPL_NONE
}},
5634 {"unlock",cmd_unlock
,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE
,COMPL_REMOTE
}},
5635 {"volume",cmd_volume
,"print the volume name",{COMPL_NONE
,COMPL_NONE
}},
5636 {"vuid",cmd_vuid
,"change current vuid",{COMPL_NONE
,COMPL_NONE
}},
5637 {"wdel",cmd_wdel
,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE
,COMPL_NONE
}},
5638 {"logon",cmd_logon
,"establish new logon",{COMPL_NONE
,COMPL_NONE
}},
5639 {"listconnect",cmd_list_connect
,"list open connections",{COMPL_NONE
,COMPL_NONE
}},
5640 {"showconnect",cmd_show_connect
,"display the current active connection",{COMPL_NONE
,COMPL_NONE
}},
5641 {"tcon",cmd_tcon
,"connect to a share" ,{COMPL_NONE
,COMPL_NONE
}},
5642 {"tdis",cmd_tdis
,"disconnect from a share",{COMPL_NONE
,COMPL_NONE
}},
5643 {"tid",cmd_tid
,"show or set the current tid (tree-id)",{COMPL_NONE
,COMPL_NONE
}},
5644 {"utimes", cmd_utimes
,"<file name> <create_time> <access_time> <mod_time> "
5645 "<ctime> set times", {COMPL_REMOTE
,COMPL_NONE
}},
5646 {"logoff",cmd_logoff
,"log off (close the session)",{COMPL_NONE
,COMPL_NONE
}},
5647 {"..",cmd_cd_oneup
,"change the remote directory (up one level)",{COMPL_REMOTE
,COMPL_NONE
}},
5649 /* Yes, this must be here, see crh's comment above. */
5650 {"!",NULL
,"run a shell command on the local system",{COMPL_NONE
,COMPL_NONE
}},
5651 {NULL
,NULL
,NULL
,{COMPL_NONE
,COMPL_NONE
}}
5654 /*******************************************************************
5655 Lookup a command string in the list of commands, including
5657 ******************************************************************/
5659 static int process_tok(char *tok
)
5661 size_t i
= 0, matches
= 0;
5663 size_t tok_len
= strlen(tok
);
5665 while (commands
[i
].fn
!= NULL
) {
5666 if (strequal(commands
[i
].name
,tok
)) {
5670 } else if (strnequal(commands
[i
].name
, tok
, tok_len
)) {
5679 else if (matches
== 1)
5685 /****************************************************************************
5687 ****************************************************************************/
5689 static int cmd_help(void)
5691 TALLOC_CTX
*ctx
= talloc_tos();
5695 if (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
5696 if ((i
= process_tok(buf
)) >= 0)
5697 d_printf("HELP %s:\n\t%s\n\n",
5698 commands
[i
].name
,commands
[i
].description
);
5700 while (commands
[i
].description
) {
5701 for (j
=0; commands
[i
].description
&& (j
<5); j
++) {
5702 d_printf("%-15s",commands
[i
].name
);
5711 /****************************************************************************
5712 Process a -c command string.
5713 ****************************************************************************/
5715 static int process_command_string(const char *cmd_in
)
5717 TALLOC_CTX
*ctx
= talloc_tos();
5718 char *cmd
= talloc_strdup(ctx
, cmd_in
);
5720 struct cli_credentials
*creds
= samba_cmdline_get_creds();
5725 /* establish the connection if not already */
5730 status
= cli_cm_open(talloc_tos(), NULL
,
5734 have_ip
? &dest_ss
: NULL
, port
,
5737 if (!NT_STATUS_IS_OK(status
)) {
5740 cli_set_timeout(cli
, io_timeout
*1000);
5743 while (cmd
[0] != '\0') {
5749 if ((p
= strchr_m(cmd
, ';')) == 0) {
5758 /* and get the first part of the command */
5760 if (!next_token_talloc(ctx
, &cmd_ptr
,&tok
,NULL
)) {
5764 if ((i
= process_tok(tok
)) >= 0) {
5765 rc
= commands
[i
].fn();
5766 } else if (i
== -2) {
5767 d_printf("%s: command abbreviation ambiguous\n",tok
);
5769 d_printf("%s: command not found\n",tok
);
5776 #define MAX_COMPLETIONS 100
5778 struct completion_remote
{
5786 static NTSTATUS
completion_remote_filter(struct file_info
*f
,
5790 struct completion_remote
*info
= (struct completion_remote
*)state
;
5792 if (info
->count
>= MAX_COMPLETIONS
- 1) {
5793 return NT_STATUS_OK
;
5795 if (strncmp(info
->text
, f
->name
, info
->len
) != 0) {
5796 return NT_STATUS_OK
;
5798 if (ISDOT(f
->name
) || ISDOTDOT(f
->name
)) {
5799 return NT_STATUS_OK
;
5802 if ((info
->dirmask
[0] == 0) && !(f
->attr
& FILE_ATTRIBUTE_DIRECTORY
))
5803 info
->matches
[info
->count
] = SMB_STRDUP(f
->name
);
5805 TALLOC_CTX
*ctx
= talloc_stackframe();
5808 tmp
= talloc_strdup(ctx
,info
->dirmask
);
5811 return NT_STATUS_NO_MEMORY
;
5813 tmp
= talloc_asprintf_append(tmp
, "%s", f
->name
);
5816 return NT_STATUS_NO_MEMORY
;
5818 if (f
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
5819 tmp
= talloc_asprintf_append(tmp
, "%s",
5824 return NT_STATUS_NO_MEMORY
;
5826 info
->matches
[info
->count
] = SMB_STRDUP(tmp
);
5829 if (info
->matches
[info
->count
] == NULL
) {
5830 return NT_STATUS_OK
;
5832 if (f
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
5833 smb_readline_ca_char(0);
5835 if (info
->count
== 1) {
5836 info
->samelen
= strlen(info
->matches
[info
->count
]);
5838 while (strncmp(info
->matches
[info
->count
],
5839 info
->matches
[info
->count
-1],
5840 info
->samelen
) != 0) {
5845 return NT_STATUS_OK
;
5848 static char **remote_completion(const char *text
, int len
)
5850 TALLOC_CTX
*ctx
= talloc_stackframe();
5851 char *dirmask
= NULL
;
5852 char *targetpath
= NULL
;
5853 struct cli_state
*targetcli
= NULL
;
5855 struct completion_remote info
= { NULL
, NULL
, 1, 0, NULL
, 0 };
5856 struct cli_credentials
*creds
= samba_cmdline_get_creds();
5859 /* can't have non-static initialisation on Sun CC, so do it
5865 info
.matches
= SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS
);
5866 if (!info
.matches
) {
5872 * We're leaving matches[0] free to fill it later with the text to
5873 * display: Either the one single match or the longest common subset
5876 info
.matches
[0] = NULL
;
5879 for (i
= len
-1; i
>= 0; i
--) {
5880 if ((text
[i
] == '/') || (text
[i
] == CLI_DIRSEP_CHAR
)) {
5885 info
.text
= text
+i
+1;
5886 info
.samelen
= info
.len
= len
-i
-1;
5889 info
.dirmask
= SMB_MALLOC_ARRAY(char, i
+2);
5890 if (!info
.dirmask
) {
5893 strncpy(info
.dirmask
, text
, i
+1);
5894 info
.dirmask
[i
+1] = 0;
5895 dirmask
= talloc_asprintf(ctx
,
5897 client_get_cur_dir(),
5901 info
.dirmask
= SMB_STRDUP("");
5902 if (!info
.dirmask
) {
5905 dirmask
= talloc_asprintf(ctx
,
5907 client_get_cur_dir());
5912 dirmask
= client_clean_name(ctx
, dirmask
);
5913 if (dirmask
== NULL
) {
5917 status
= cli_resolve_path(ctx
, "",
5919 cli
, dirmask
, &targetcli
, &targetpath
);
5920 if (!NT_STATUS_IS_OK(status
)) {
5923 status
= cli_list(targetcli
, targetpath
, FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
,
5924 completion_remote_filter
, (void *)&info
);
5925 if (!NT_STATUS_IS_OK(status
)) {
5929 if (info
.count
== 1) {
5931 * No matches at all, NULL indicates there is nothing
5933 SAFE_FREE(info
.matches
[0]);
5934 SAFE_FREE(info
.matches
);
5939 if (info
.count
== 2) {
5941 * Exactly one match in matches[1], indicate this is the one
5944 info
.matches
[0] = info
.matches
[1];
5945 info
.matches
[1] = NULL
;
5948 return info
.matches
;
5952 * We got more than one possible match, set the result to the maximum
5956 info
.matches
[0] = SMB_STRNDUP(info
.matches
[1], info
.samelen
);
5957 info
.matches
[info
.count
] = NULL
;
5959 return info
.matches
;
5962 for (i
= 0; i
< info
.count
; i
++) {
5963 SAFE_FREE(info
.matches
[i
]);
5965 SAFE_FREE(info
.matches
);
5966 SAFE_FREE(info
.dirmask
);
5971 static char **completion_fn(const char *text
, int start
, int end
)
5973 smb_readline_ca_char(' ');
5976 const char *buf
, *sp
;
5980 buf
= smb_readline_get_line_buffer();
5984 sp
= strchr(buf
, ' ');
5988 for (i
= 0; commands
[i
].name
; i
++) {
5989 if ((strncmp(commands
[i
].name
, buf
, sp
- buf
) == 0) &&
5990 (commands
[i
].name
[sp
- buf
] == 0)) {
5994 if (commands
[i
].name
== NULL
)
6000 if (sp
== (buf
+ start
))
6001 compl_type
= commands
[i
].compl_args
[0];
6003 compl_type
= commands
[i
].compl_args
[1];
6005 if (compl_type
== COMPL_REMOTE
)
6006 return remote_completion(text
, end
- start
);
6007 else /* fall back to local filename completion */
6011 size_t i
, len
, samelen
= 0, count
=1;
6013 matches
= SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS
);
6020 for (i
=0;commands
[i
].fn
&& count
< MAX_COMPLETIONS
-1;i
++) {
6021 if (strncmp(text
, commands
[i
].name
, len
) == 0) {
6022 matches
[count
] = SMB_STRDUP(commands
[i
].name
);
6023 if (!matches
[count
])
6026 samelen
= strlen(matches
[count
]);
6028 while (strncmp(matches
[count
], matches
[count
-1], samelen
) != 0)
6035 case 0: /* should never happen */
6039 matches
[0] = SMB_STRDUP(matches
[1]);
6042 matches
[0] = (char *)SMB_MALLOC(samelen
+1);
6045 strncpy(matches
[0], matches
[1], samelen
);
6046 matches
[0][samelen
] = 0;
6048 matches
[count
] = NULL
;
6052 for (i
= 0; i
< count
; i
++)
6060 static bool finished
;
6062 /****************************************************************************
6063 Make sure we swallow keepalives during idle time.
6064 ****************************************************************************/
6066 static void readline_callback(void)
6068 static time_t last_t
;
6069 struct timespec now
;
6072 unsigned char garbage
[16];
6074 clock_gettime_mono(&now
);
6082 /* Ping the server to keep the connection alive using SMBecho. */
6083 memset(garbage
, 0xf0, sizeof(garbage
));
6084 status
= cli_echo(cli
, 1, data_blob_const(garbage
, sizeof(garbage
)));
6085 if (NT_STATUS_IS_OK(status
) ||
6086 NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
6088 * Even if server returns NT_STATUS_INVALID_PARAMETER
6089 * it still responded.
6090 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13007
6095 if (!cli_state_is_connected(cli
)) {
6096 DEBUG(0,("SMBecho failed (%s). The connection is "
6097 "disconnected now\n", nt_errstr(status
)));
6099 smb_readline_done();
6103 /****************************************************************************
6104 Process commands on stdin.
6105 ****************************************************************************/
6107 static int process_stdin(void)
6112 d_printf("Try \"help\" to get a list of possible commands.\n");
6116 TALLOC_CTX
*frame
= talloc_stackframe();
6118 char *the_prompt
= NULL
;
6122 /* display a prompt */
6123 if (asprintf(&the_prompt
, "smb: %s> ", client_get_cur_dir()) < 0) {
6127 line
= smb_readline(the_prompt
, readline_callback
, completion_fn
);
6128 SAFE_FREE(the_prompt
);
6134 /* special case - first char is ! */
6136 if (system(line
+ 1) == -1) {
6137 d_printf("system() command %s failed.\n",
6145 /* and get the first part of the command */
6147 if (!next_token_talloc(frame
, &cmd_ptr
,&tok
,NULL
)) {
6153 if ((i
= process_tok(tok
)) >= 0) {
6154 rc
= commands
[i
].fn();
6155 } else if (i
== -2) {
6156 d_printf("%s: command abbreviation ambiguous\n",tok
);
6158 d_printf("%s: command not found\n",tok
);
6166 /****************************************************************************
6167 Process commands from the client.
6168 ****************************************************************************/
6170 static int process(const char *base_directory
)
6174 struct cli_credentials
*creds
= samba_cmdline_get_creds();
6176 status
= cli_cm_open(talloc_tos(), NULL
,
6180 have_ip
? &dest_ss
: NULL
, port
,
6182 if (!NT_STATUS_IS_OK(status
)) {
6186 cli_set_timeout(cli
, io_timeout
*1000);
6188 if (base_directory
&& *base_directory
) {
6189 rc
= do_cd(base_directory
);
6197 rc
= process_command_string(cmdstr
);
6206 /****************************************************************************
6208 ****************************************************************************/
6210 static int do_host_query(const char *query_host
)
6213 struct cli_credentials
*creds
= samba_cmdline_get_creds();
6215 status
= cli_cm_open(talloc_tos(), NULL
,
6219 have_ip
? &dest_ss
: NULL
, port
,
6221 if (!NT_STATUS_IS_OK(status
)) {
6225 cli_set_timeout(cli
, io_timeout
*1000);
6228 /* Ensure that the host can do IPv4 */
6230 if (!interpret_addr(query_host
)) {
6231 struct sockaddr_storage ss
;
6232 if (interpret_string_addr(&ss
, query_host
, 0) &&
6233 (ss
.ss_family
!= AF_INET
)) {
6234 d_printf("%s is an IPv6 address -- no workgroup available\n",
6240 if (lp_client_min_protocol() > PROTOCOL_NT1
) {
6241 d_printf("SMB1 disabled -- no workgroup available\n");
6245 if (lp_disable_netbios()) {
6246 d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
6250 if (port
!= NBT_SMB_PORT
||
6251 smbXcli_conn_protocol(cli
->conn
) > PROTOCOL_NT1
)
6254 * Workgroups simply don't make sense over anything
6255 * else but port 139 and SMB1.
6259 d_printf("Reconnecting with SMB1 for workgroup listing.\n");
6260 lp_set_cmdline("client max protocol", "NT1");
6261 status
= cli_cm_open(talloc_tos(), NULL
,
6265 have_ip
? &dest_ss
: NULL
, NBT_SMB_PORT
,
6267 if (!NT_STATUS_IS_OK(status
)) {
6268 d_printf("Unable to connect with SMB1 "
6269 "-- no workgroup available\n");
6274 cli_set_timeout(cli
, io_timeout
*1000);
6275 list_servers(lp_workgroup());
6282 /****************************************************************************
6283 Handle a tar operation.
6284 ****************************************************************************/
6286 static int do_tar_op(const char *base_directory
)
6288 struct tar
*tar_ctx
= tar_get_ctx();
6290 struct cli_credentials
*creds
= samba_cmdline_get_creds();
6292 /* do we already have a connection? */
6296 status
= cli_cm_open(talloc_tos(), NULL
,
6300 have_ip
? &dest_ss
: NULL
, port
,
6302 if (!NT_STATUS_IS_OK(status
)) {
6306 cli_set_timeout(cli
, io_timeout
*1000);
6311 if (base_directory
&& *base_directory
) {
6312 ret
= do_cd(base_directory
);
6318 ret
= tar_process(tar_ctx
);
6326 /****************************************************************************
6327 Handle a message operation.
6328 ****************************************************************************/
6330 static int do_message_op(struct cli_credentials
*creds
)
6334 if (lp_disable_netbios()) {
6335 d_printf("NetBIOS over TCP disabled.\n");
6339 status
= cli_connect_nb(desthost
, have_ip
? &dest_ss
: NULL
,
6340 port
? port
: NBT_SMB_PORT
, name_type
,
6345 if (!NT_STATUS_IS_OK(status
)) {
6346 d_printf("Connection to %s failed. Error %s\n", desthost
, nt_errstr(status
));
6350 cli_set_timeout(cli
, io_timeout
*1000);
6351 send_message(cli_credentials_get_username(creds
));
6357 /****************************************************************************
6359 ****************************************************************************/
6361 int main(int argc
,char *argv
[])
6363 const char **const_argv
= discard_const_p(const char *, argv
);
6364 char *base_directory
= NULL
;
6366 char *query_host
= NULL
;
6367 bool message
= false;
6368 static const char *new_name_resolve_order
= NULL
;
6372 bool tar_opt
= false;
6373 bool service_opt
= false;
6374 struct tar
*tar_ctx
= tar_get_ctx();
6377 struct poptOption long_options
[] = {
6381 .longName
= "message",
6383 .argInfo
= POPT_ARG_STRING
,
6386 .descrip
= "Send message",
6387 .argDescrip
= "HOST",
6390 .longName
= "ip-address",
6392 .argInfo
= POPT_ARG_STRING
,
6395 .descrip
= "Use this IP to connect to",
6399 .longName
= "stderr",
6401 .argInfo
= POPT_ARG_NONE
,
6404 .descrip
= "Write messages to stderr instead of stdout",
6409 .argInfo
= POPT_ARG_STRING
,
6412 .descrip
= "Get a list of shares available on a host",
6413 .argDescrip
= "HOST",
6418 .argInfo
= POPT_ARG_STRING
,
6421 .descrip
= "Command line tar",
6422 .argDescrip
= "<c|x>IXFvgbNan",
6425 .longName
= "directory",
6427 .argInfo
= POPT_ARG_STRING
,
6430 .descrip
= "Start from directory",
6431 .argDescrip
= "DIR",
6434 .longName
= "command",
6436 .argInfo
= POPT_ARG_STRING
,
6439 .descrip
= "Execute semicolon separated commands",
6442 .longName
= "send-buffer",
6444 .argInfo
= POPT_ARG_INT
,
6447 .descrip
= "Changes the transmit/send buffer",
6448 .argDescrip
= "BYTES",
6451 .longName
= "timeout",
6453 .argInfo
= POPT_ARG_INT
,
6456 .descrip
= "Changes the per-operation timeout",
6457 .argDescrip
= "SECONDS",
6462 .argInfo
= POPT_ARG_INT
,
6465 .descrip
= "Port to connect to",
6466 .argDescrip
= "PORT",
6469 .longName
= "grepable",
6471 .argInfo
= POPT_ARG_NONE
,
6474 .descrip
= "Produce grepable output",
6477 .longName
= "quiet",
6479 .argInfo
= POPT_ARG_NONE
,
6482 .descrip
= "Suppress help message",
6485 .longName
= "browse",
6487 .argInfo
= POPT_ARG_NONE
,
6490 .descrip
= "Browse SMB servers using DNS",
6493 POPT_COMMON_CONNECTION
6494 POPT_COMMON_CREDENTIALS
6499 TALLOC_CTX
*frame
= talloc_stackframe();
6500 struct cli_credentials
*creds
= NULL
;
6502 if (!client_set_cur_dir("\\")) {
6508 ok
= samba_cmdline_init(frame
,
6509 SAMBA_CMDLINE_CONFIG_CLIENT
,
6510 false /* require_smbconf */);
6512 DBG_ERR("Failed to init cmdline parser!\n");
6515 lp_set_cmdline("log level", "1");
6518 pc
= samba_popt_get_context(getprogname(),
6524 DBG_ERR("Failed to setup popt context!\n");
6528 poptSetOtherOptionHelp(pc
, "[OPTIONS] service <password>");
6530 creds
= samba_cmdline_get_creds();
6531 while ((opt
= poptGetNextOpt(pc
)) != -1) {
6534 * if the tar option has been called previously, now
6535 * we need to eat out the leftovers
6537 /* I see no other way to keep things sane --SSS */
6538 if (tar_opt
== true) {
6539 while (poptPeekArg(pc
)) {
6545 /* if the service has not yet been specified lets see if it is available in the popt stack */
6546 if (!service_opt
&& poptPeekArg(pc
)) {
6547 service
= talloc_strdup(frame
, poptGetArg(pc
));
6554 /* if the service has already been retrieved then check if we have also a password */
6556 cli_credentials_get_password(creds
) == NULL
&&
6558 cli_credentials_set_password(creds
,
6566 /* Messages are sent to NetBIOS name type 0x3
6567 * (Messenger Service). Make sure we default
6568 * to port 139 instead of port 445. srl,crh
6571 desthost
= talloc_strdup(frame
,poptGetOptArg(pc
));
6576 port
= NBT_SMB_PORT
;
6581 if (!interpret_string_addr(&dest_ss
, poptGetOptArg(pc
), 0)) {
6585 print_sockaddr(dest_ss_str
, sizeof(dest_ss_str
), &dest_ss
);
6589 setup_logging("smbclient", DEBUG_STDERR
);
6590 display_set_stderr();
6594 query_host
= talloc_strdup(frame
, poptGetOptArg(pc
));
6600 /* We must use old option processing for this. Find the
6601 * position of the -T option in the raw argv[]. */
6605 for (i
= 1; i
< argc
; i
++) {
6606 if (strncmp("-T", argv
[i
],2)==0)
6610 if (tar_parse_args(tar_ctx
, poptGetOptArg(pc
),
6611 const_argv
+ i
, argc
- i
)) {
6612 poptPrintUsage(pc
, stderr
, 0);
6616 /* this must be the last option, mark we have parsed it so that we know we have */
6620 base_directory
= talloc_strdup(frame
, poptGetOptArg(pc
));
6621 if (!base_directory
) {
6632 return(do_smb_browse());
6633 case POPT_ERROR_BADOPT
:
6634 fprintf(stderr
, "\nInvalid option %s: %s\n\n",
6635 poptBadOption(pc
, 0), poptStrerror(opt
));
6636 poptPrintUsage(pc
, stderr
, 0);
6641 /* We may still have some leftovers after the last popt option has been called */
6642 if (tar_opt
== true) {
6643 while (poptPeekArg(pc
)) {
6649 /* if the service has not yet been specified lets see if it is available in the popt stack */
6650 if (!service_opt
&& poptPeekArg(pc
)) {
6651 service
= talloc_strdup(frame
,poptGetArg(pc
));
6658 /* if the service has already been retrieved then check if we have also a password */
6660 cli_credentials_get_password(creds
) == NULL
&&
6662 cli_credentials_set_password(creds
,
6667 if (service_opt
&& service
) {
6670 /* Convert any '/' characters in the service name to '\' characters */
6671 string_replace(service
, '/','\\');
6672 if (count_chars(service
,'\\') < 3) {
6673 d_printf("\n%s: Not enough '\\' characters in service\n",service
);
6674 poptPrintUsage(pc
, stderr
, 0);
6677 /* Remove trailing slashes */
6678 len
= strlen(service
);
6679 while(len
> 0 && service
[len
- 1] == '\\') {
6681 service
[len
] = '\0';
6685 if(new_name_resolve_order
)
6686 lp_set_cmdline("name resolve order", new_name_resolve_order
);
6688 if (!tar_to_process(tar_ctx
) && !query_host
&& !service
&& !message
) {
6689 poptPrintUsage(pc
, stderr
, 0);
6693 poptFreeContext(pc
);
6694 samba_cmdline_burn(argc
, argv
);
6696 DEBUG(3,("Client started (version %s).\n", samba_version_string()));
6698 if (tar_to_process(tar_ctx
)) {
6700 process_command_string(cmdstr
);
6701 rc
= do_tar_op(base_directory
);
6702 } else if (query_host
&& *query_host
) {
6703 char *qhost
= query_host
;
6706 while (*qhost
== '\\' || *qhost
== '/')
6709 if ((slash
= strchr_m(qhost
, '/'))
6710 || (slash
= strchr_m(qhost
, '\\'))) {
6714 if ((p
=strchr_m(qhost
, '#'))) {
6717 sscanf(p
, "%x", &name_type
);
6720 rc
= do_host_query(qhost
);
6721 } else if (message
) {
6722 rc
= do_message_op(creds
);
6723 } else if (process(base_directory
)) {