3 put in subdir does in \
7 Unix SMB/CIFS implementation.
9 Copyright (C) Andrew Tridgell 1994-1998
10 Copyright (C) Simo Sorce 2001-2002
11 Copyright (C) Jelmer Vernooij 2003-2004
12 Copyright (C) James J Myers 2003 <myersjj@samba.org>
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include "libcli/libcli.h"
32 #include "lib/cmdline/popt_common.h"
33 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
34 #include "librpc/gen_ndr/ndr_lsa.h"
35 #include "librpc/gen_ndr/ndr_security.h"
36 #include "libcli/raw/libcliraw.h"
37 #include "libcli/util/clilsa.h"
38 #include "system/dir.h"
39 #include "system/filesys.h"
40 #include "lib/util/dlinklist.h"
41 #include "system/readline.h"
42 #include "auth/credentials/credentials.h"
43 #include "auth/gensec/gensec.h"
44 #include "system/time.h" /* needed by some systems for asctime() */
45 #include "libcli/resolve/resolve.h"
46 #include "libcli/security/security.h"
47 #include "lib/smbreadline/smbreadline.h"
48 #include "librpc/gen_ndr/ndr_nbt.h"
50 static int io_bufsize = 64512;
52 struct smbclient_context {
54 struct smbcli_state *cli;
66 static uint64_t get_total_size = 0;
67 static uint_t get_total_time_ms = 0;
68 static uint64_t put_total_size = 0;
69 static uint_t put_total_time_ms = 0;
71 /* Unfortunately, there is no way to pass the a context to the completion function as an argument */
72 static struct smbclient_context *rl_ctx;
75 static double dir_total;
77 /*******************************************************************
78 Reduce a file name, removing .. elements.
79 ********************************************************************/
80 void dos_clean_name(char *s)
84 DEBUG(3,("dos_clean_name [%s]\n",s));
86 /* remove any double slashes */
87 all_string_sub(s, "\\\\", "\\", 0);
89 while ((p = strstr(s,"\\..\\")) != NULL) {
91 if ((r = strrchr(s,'\\')) != NULL)
92 memmove(r,p+3,strlen(p+3)+1);
95 trim_string(s,NULL,"\\..");
97 all_string_sub(s, "\\.\\", "\\", 0);
100 /****************************************************************************
101 write to a local file with CR/LF->LF translation if appropriate. return the
102 number taken from the buffer. This may not equal the number written.
103 ****************************************************************************/
104 static int writefile(int f, const void *_b, int n, BOOL translation)
106 const uint8_t *b = _b;
115 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
118 if (write(f, b, 1) != 1) {
128 /****************************************************************************
129 read from a file with LF->CR/LF translation if appropriate. return the
130 number read. read approx n bytes.
131 ****************************************************************************/
132 static int readfile(void *_b, int n, XFILE *f, BOOL translation)
139 return x_fread(b,1,n,f);
142 while (i < (n - 1)) {
143 if ((c = x_getc(f)) == EOF) {
147 if (c == '\n') { /* change all LFs to CR/LF */
158 /****************************************************************************
160 ****************************************************************************/
161 static void send_message(struct smbcli_state *cli, const char *desthost)
167 if (!smbcli_message_start(cli->tree, desthost, cli_credentials_get_username(cmdline_credentials), &grp_id)) {
168 d_printf("message start: %s\n", smbcli_errstr(cli->tree));
173 d_printf("Connected. Type your message, ending it with a Control-D\n");
175 while (!feof(stdin) && total_len < 1600) {
176 int maxlen = MIN(1600 - total_len,127);
180 for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) {
186 if (!smbcli_message_text(cli->tree, msg, l, grp_id)) {
187 d_printf("SMBsendtxt failed (%s)\n",smbcli_errstr(cli->tree));
194 if (total_len >= 1600)
195 d_printf("the message was truncated to 1600 bytes\n");
197 d_printf("sent %d bytes\n",total_len);
199 if (!smbcli_message_end(cli->tree, grp_id)) {
200 d_printf("SMBsendend failed (%s)\n",smbcli_errstr(cli->tree));
207 /****************************************************************************
208 check the space on a device
209 ****************************************************************************/
210 static int do_dskattr(struct smbclient_context *ctx)
212 int total, bsize, avail;
214 if (NT_STATUS_IS_ERR(smbcli_dskattr(ctx->cli->tree, &bsize, &total, &avail))) {
215 d_printf("Error in dskattr: %s\n",smbcli_errstr(ctx->cli->tree));
219 d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
220 total, bsize, avail);
225 /****************************************************************************
227 ****************************************************************************/
228 static int cmd_pwd(struct smbclient_context *ctx, const char **args)
230 d_printf("Current directory is %s\n", ctx->remote_cur_dir);
235 convert a string to dos format
237 static void dos_format(char *s)
239 string_replace(s, '/', '\\');
242 /****************************************************************************
243 change directory - inner section
244 ****************************************************************************/
245 static int do_cd(struct smbclient_context *ctx, const char *newdir)
249 /* Save the current directory in case the
250 new directory is invalid */
251 if (newdir[0] == '\\')
252 dname = talloc_strdup(NULL, newdir);
254 dname = talloc_asprintf(NULL, "%s\\%s", ctx->remote_cur_dir, newdir);
258 if (*(dname+strlen(dname)-1) != '\\') {
259 dname = talloc_append_string(NULL, dname, "\\");
261 dos_clean_name(dname);
263 if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, dname))) {
264 d_printf("cd %s: %s\n", dname, smbcli_errstr(ctx->cli->tree));
267 ctx->remote_cur_dir = dname;
273 /****************************************************************************
275 ****************************************************************************/
276 static int cmd_cd(struct smbclient_context *ctx, const char **args)
281 rc = do_cd(ctx, args[1]);
283 d_printf("Current directory is %s\n",ctx->remote_cur_dir);
289 BOOL mask_match(struct smbcli_state *c, const char *string, const char *pattern,
290 BOOL is_case_sensitive)
295 if (ISDOTDOT(string))
300 if (is_case_sensitive)
301 return ms_fnmatch(pattern, string,
302 c->transport->negotiate.protocol) == 0;
304 p2 = strlower_talloc(NULL, pattern);
305 s2 = strlower_talloc(NULL, string);
306 ret = ms_fnmatch(p2, s2, c->transport->negotiate.protocol) == 0;
315 /*******************************************************************
316 decide if a file should be operated on
317 ********************************************************************/
318 static BOOL do_this_one(struct smbclient_context *ctx, struct clilist_file_info *finfo)
320 if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) return(True);
322 if (ctx->fileselection &&
323 !mask_match(ctx->cli, finfo->name,ctx->fileselection,False)) {
324 DEBUG(3,("mask_match %s failed\n", finfo->name));
328 if (ctx->newer_than && finfo->mtime < ctx->newer_than) {
329 DEBUG(3,("newer_than %s failed\n", finfo->name));
333 if ((ctx->archive_level==1 || ctx->archive_level==2) && !(finfo->attrib & FILE_ATTRIBUTE_ARCHIVE)) {
334 DEBUG(3,("archive %s failed\n", finfo->name));
341 /****************************************************************************
342 display info about a file
343 ****************************************************************************/
344 static void display_finfo(struct smbclient_context *ctx, struct clilist_file_info *finfo)
346 if (do_this_one(ctx, finfo)) {
347 time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
348 char *astr = attrib_string(NULL, finfo->attrib);
349 d_printf(" %-30s%7.7s %8.0f %s",
353 asctime(localtime(&t)));
354 dir_total += finfo->size;
360 /****************************************************************************
361 accumulate size of a file
362 ****************************************************************************/
363 static void do_du(struct smbclient_context *ctx, struct clilist_file_info *finfo)
365 if (do_this_one(ctx, finfo)) {
366 dir_total += finfo->size;
370 static BOOL do_list_recurse;
371 static BOOL do_list_dirs;
372 static char *do_list_queue = 0;
373 static long do_list_queue_size = 0;
374 static long do_list_queue_start = 0;
375 static long do_list_queue_end = 0;
376 static void (*do_list_fn)(struct smbclient_context *, struct clilist_file_info *);
378 /****************************************************************************
379 functions for do_list_queue
380 ****************************************************************************/
383 * The do_list_queue is a NUL-separated list of strings stored in a
384 * char*. Since this is a FIFO, we keep track of the beginning and
385 * ending locations of the data in the queue. When we overflow, we
386 * double the size of the char*. When the start of the data passes
387 * the midpoint, we move everything back. This is logically more
388 * complex than a linked list, but easier from a memory management
389 * angle. In any memory error condition, do_list_queue is reset.
390 * Functions check to ensure that do_list_queue is non-NULL before
393 static void reset_do_list_queue(void)
395 SAFE_FREE(do_list_queue);
396 do_list_queue_size = 0;
397 do_list_queue_start = 0;
398 do_list_queue_end = 0;
401 static void init_do_list_queue(void)
403 reset_do_list_queue();
404 do_list_queue_size = 1024;
405 do_list_queue = malloc(do_list_queue_size);
406 if (do_list_queue == 0) {
407 d_printf("malloc fail for size %d\n",
408 (int)do_list_queue_size);
409 reset_do_list_queue();
411 memset(do_list_queue, 0, do_list_queue_size);
415 static void adjust_do_list_queue(void)
417 if (do_list_queue == NULL) return;
420 * If the starting point of the queue is more than half way through,
421 * move everything toward the beginning.
423 if (do_list_queue_start == do_list_queue_end)
425 DEBUG(4,("do_list_queue is empty\n"));
426 do_list_queue_start = do_list_queue_end = 0;
427 *do_list_queue = '\0';
429 else if (do_list_queue_start > (do_list_queue_size / 2))
431 DEBUG(4,("sliding do_list_queue backward\n"));
432 memmove(do_list_queue,
433 do_list_queue + do_list_queue_start,
434 do_list_queue_end - do_list_queue_start);
435 do_list_queue_end -= do_list_queue_start;
436 do_list_queue_start = 0;
441 static void add_to_do_list_queue(const char* entry)
444 long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
445 while (new_end > do_list_queue_size)
447 do_list_queue_size *= 2;
448 DEBUG(4,("enlarging do_list_queue to %d\n",
449 (int)do_list_queue_size));
450 dlq = realloc_p(do_list_queue, char, do_list_queue_size);
452 d_printf("failure enlarging do_list_queue to %d bytes\n",
453 (int)do_list_queue_size);
454 reset_do_list_queue();
459 memset(do_list_queue + do_list_queue_size / 2,
460 0, do_list_queue_size / 2);
465 safe_strcpy(do_list_queue + do_list_queue_end, entry,
466 do_list_queue_size - do_list_queue_end - 1);
467 do_list_queue_end = new_end;
468 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
469 entry, (int)do_list_queue_start, (int)do_list_queue_end));
473 static char *do_list_queue_head(void)
475 return do_list_queue + do_list_queue_start;
478 static void remove_do_list_queue_head(void)
480 if (do_list_queue_end > do_list_queue_start)
482 do_list_queue_start += strlen(do_list_queue_head()) + 1;
483 adjust_do_list_queue();
484 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
485 (int)do_list_queue_start, (int)do_list_queue_end));
489 static int do_list_queue_empty(void)
491 return (! (do_list_queue && *do_list_queue));
494 /****************************************************************************
496 ****************************************************************************/
497 static void do_list_helper(struct clilist_file_info *f, const char *mask, void *state)
499 struct smbclient_context *ctx = state;
501 if (f->attrib & FILE_ATTRIBUTE_DIRECTORY) {
502 if (do_list_dirs && do_this_one(ctx, f)) {
505 if (do_list_recurse &&
507 !ISDOTDOT(f->name)) {
511 mask2 = talloc_strdup(NULL, mask);
512 p = strrchr_m(mask2,'\\');
515 mask2 = talloc_asprintf_append(mask2, "%s\\*", f->name);
516 add_to_do_list_queue(mask2);
521 if (do_this_one(ctx, f)) {
527 /****************************************************************************
528 a wrapper around smbcli_list that adds recursion
529 ****************************************************************************/
530 static void do_list(struct smbclient_context *ctx, const char *mask,uint16_t attribute,
531 void (*fn)(struct smbclient_context *, struct clilist_file_info *),BOOL rec, BOOL dirs)
533 static int in_do_list = 0;
535 if (in_do_list && rec)
537 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
543 do_list_recurse = rec;
549 init_do_list_queue();
550 add_to_do_list_queue(mask);
552 while (! do_list_queue_empty())
555 * Need to copy head so that it doesn't become
556 * invalid inside the call to smbcli_list. This
557 * would happen if the list were expanded
559 * Fix from E. Jay Berkenbilt (ejb@ql.org)
562 head = do_list_queue_head();
563 smbcli_list(ctx->cli->tree, head, attribute, do_list_helper, ctx);
564 remove_do_list_queue_head();
565 if ((! do_list_queue_empty()) && (fn == display_finfo))
567 char* next_file = do_list_queue_head();
569 if ((strlen(next_file) >= 2) &&
570 (next_file[strlen(next_file) - 1] == '*') &&
571 (next_file[strlen(next_file) - 2] == '\\'))
573 save_ch = next_file +
574 strlen(next_file) - 2;
577 d_printf("\n%s\n",next_file);
587 if (smbcli_list(ctx->cli->tree, mask, attribute, do_list_helper, ctx) == -1)
589 d_printf("%s listing %s\n", smbcli_errstr(ctx->cli->tree), mask);
594 reset_do_list_queue();
597 /****************************************************************************
598 get a directory listing
599 ****************************************************************************/
600 static int cmd_dir(struct smbclient_context *ctx, const char **args)
602 uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
608 mask = talloc_strdup(ctx, ctx->remote_cur_dir);
609 if(mask[strlen(mask)-1]!='\\')
610 mask = talloc_append_string(ctx, mask,"\\");
613 mask = talloc_strdup(ctx, args[1]);
615 mask = talloc_append_string(ctx, mask, "\\");
619 if (ctx->cli->tree->session->transport->negotiate.protocol <=
621 mask = talloc_append_string(ctx, mask, "*.*");
623 mask = talloc_append_string(ctx, mask, "*");
627 do_list(ctx, mask, attribute, display_finfo, ctx->recurse, True);
629 rc = do_dskattr(ctx);
631 DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
637 /****************************************************************************
638 get a directory listing
639 ****************************************************************************/
640 static int cmd_du(struct smbclient_context *ctx, const char **args)
642 uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
649 if (args[1][0] == '\\')
650 mask = talloc_strdup(ctx, args[1]);
652 mask = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
655 mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
658 do_list(ctx, mask, attribute, do_du, ctx->recurse, True);
662 rc = do_dskattr(ctx);
664 d_printf("Total number of bytes: %.0f\n", dir_total);
670 /****************************************************************************
671 get a file from rname to lname
672 ****************************************************************************/
673 static int do_get(struct smbclient_context *ctx, char *rname, const char *lname, BOOL reget)
675 int handle = 0, fnum;
676 BOOL newhandle = False;
678 struct timeval tp_start;
679 int read_size = io_bufsize;
686 GetTimeOfDay(&tp_start);
688 if (ctx->lowercase) {
689 strlower(discard_const_p(char, lname));
692 fnum = smbcli_open(ctx->cli->tree, rname, O_RDONLY, DENY_NONE);
695 d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
699 if(!strcmp(lname,"-")) {
700 handle = fileno(stdout);
703 handle = open(lname, O_WRONLY|O_CREAT, 0644);
705 start = lseek(handle, 0, SEEK_END);
707 d_printf("Error seeking local file\n");
712 handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
717 d_printf("Error opening local file %s\n",lname);
722 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum,
723 &attr, &size, NULL, NULL, NULL, NULL, NULL)) &&
724 NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum,
725 &attr, &size, NULL, NULL, NULL))) {
726 d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
730 DEBUG(2,("getting file %s of size %.0f as %s ",
731 rname, (double)size, lname));
733 if(!(data = (uint8_t *)malloc(read_size))) {
734 d_printf("malloc fail for size %d\n", read_size);
735 smbcli_close(ctx->cli->tree, fnum);
740 int n = smbcli_read(ctx->cli->tree, fnum, data, nread + start, read_size);
744 if (writefile(handle,data, n, ctx->translation) != n) {
745 d_printf("Error writing local file\n");
753 if (nread + start < size) {
754 DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
755 rname, (long)nread));
762 if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) {
763 d_printf("Error %s closing remote file\n",smbcli_errstr(ctx->cli->tree));
771 if (ctx->archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
772 smbcli_setatr(ctx->cli->tree, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0);
776 struct timeval tp_end;
779 GetTimeOfDay(&tp_end);
781 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
782 (tp_end.tv_usec - tp_start.tv_usec)/1000;
783 get_total_time_ms += this_time;
784 get_total_size += nread;
786 DEBUG(2,("(%3.1f kb/s) (average %3.1f kb/s)\n",
787 nread / (1.024*this_time + 1.0e-4),
788 get_total_size / (1.024*get_total_time_ms)));
795 /****************************************************************************
797 ****************************************************************************/
798 static int cmd_get(struct smbclient_context *ctx, const char **args)
804 d_printf("get <filename>\n");
808 rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
815 dos_clean_name(rname);
817 return do_get(ctx, rname, lname, False);
820 /****************************************************************************
821 Put up a yes/no prompt.
822 ****************************************************************************/
823 static BOOL yesno(char *p)
828 if (!fgets(ans,sizeof(ans)-1,stdin))
831 if (*ans == 'y' || *ans == 'Y')
837 /****************************************************************************
838 do a mget operation on one file
839 ****************************************************************************/
840 static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *finfo)
847 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name))
850 if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)
851 asprintf(&quest, "Get directory %s? ",finfo->name);
853 asprintf(&quest, "Get file %s? ",finfo->name);
855 if (ctx->prompt && !yesno(quest)) return;
859 if (!(finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)) {
860 asprintf(&rname, "%s%s",ctx->remote_cur_dir,finfo->name);
861 do_get(ctx, rname, finfo->name, False);
866 /* handle directories */
867 saved_curdir = talloc_strdup(NULL, ctx->remote_cur_dir);
869 ctx->remote_cur_dir = talloc_asprintf_append(NULL, "%s\\", finfo->name);
871 string_replace(discard_const_p(char, finfo->name), '\\', '/');
872 if (ctx->lowercase) {
873 strlower(discard_const_p(char, finfo->name));
876 if (!directory_exist(finfo->name) &&
877 mkdir(finfo->name,0777) != 0) {
878 d_printf("failed to create directory %s\n",finfo->name);
882 if (chdir(finfo->name) != 0) {
883 d_printf("failed to chdir to directory %s\n",finfo->name);
887 mget_mask = talloc_asprintf(NULL, "%s*", ctx->remote_cur_dir);
889 do_list(ctx, mget_mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,do_mget,False, True);
891 talloc_free(ctx->remote_cur_dir);
893 ctx->remote_cur_dir = saved_curdir;
897 /****************************************************************************
898 view the file using the pager
899 ****************************************************************************/
900 static int cmd_more(struct smbclient_context *ctx, const char **args)
909 lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
912 d_printf("failed to create temporary file for more\n");
918 d_printf("more <filename>\n");
922 rname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
923 dos_clean_name(rname);
925 rc = do_get(ctx, rname, lname, False);
927 pager=getenv("PAGER");
929 pager_cmd = talloc_asprintf(ctx, "%s %s",(pager? pager:PAGER), lname);
938 /****************************************************************************
940 ****************************************************************************/
941 static int cmd_mget(struct smbclient_context *ctx, const char **args)
943 uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
944 char *mget_mask = NULL;
948 attribute |= FILE_ATTRIBUTE_DIRECTORY;
950 for (i = 1; args[i]; i++) {
951 mget_mask = talloc_strdup(ctx,ctx->remote_cur_dir);
952 if(mget_mask[strlen(mget_mask)-1]!='\\')
953 mget_mask = talloc_append_string(ctx, mget_mask, "\\");
955 mget_mask = talloc_strdup(ctx, args[i]);
956 if (mget_mask[0] != '\\')
957 mget_mask = talloc_append_string(ctx, mget_mask, "\\");
958 do_list(ctx, mget_mask, attribute,do_mget,False,True);
960 talloc_free(mget_mask);
963 if (mget_mask == NULL) {
964 mget_mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
965 do_list(ctx, mget_mask, attribute,do_mget,False,True);
966 talloc_free(mget_mask);
973 /****************************************************************************
974 make a directory of name "name"
975 ****************************************************************************/
976 static NTSTATUS do_mkdir(struct smbclient_context *ctx, char *name)
980 if (NT_STATUS_IS_ERR(status = smbcli_mkdir(ctx->cli->tree, name))) {
981 d_printf("%s making remote directory %s\n",
982 smbcli_errstr(ctx->cli->tree),name);
990 /****************************************************************************
992 ****************************************************************************/
993 static int cmd_quit(struct smbclient_context *ctx, const char **args)
1002 /****************************************************************************
1004 ****************************************************************************/
1005 static int cmd_mkdir(struct smbclient_context *ctx, const char **args)
1011 d_printf("mkdir <dirname>\n");
1015 mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir,args[1]);
1018 dos_clean_name(mask);
1020 trim_string(mask,".",NULL);
1021 for (p = strtok(mask,"/\\"); p; p = strtok(p, "/\\")) {
1022 char *parent = talloc_strndup(ctx, mask, PTR_DIFF(p, mask));
1024 if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, parent))) {
1025 do_mkdir(ctx, parent);
1028 talloc_free(parent);
1031 do_mkdir(ctx, mask);
1037 /****************************************************************************
1038 show 8.3 name of a file
1039 ****************************************************************************/
1040 static int cmd_altname(struct smbclient_context *ctx, const char **args)
1042 const char *altname;
1046 d_printf("altname <file>\n");
1050 name = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
1052 if (!NT_STATUS_IS_OK(smbcli_qpathinfo_alt_name(ctx->cli->tree, name, &altname))) {
1053 d_printf("%s getting alt name for %s\n",
1054 smbcli_errstr(ctx->cli->tree),name);
1057 d_printf("%s\n", altname);
1063 /****************************************************************************
1065 ****************************************************************************/
1066 static int do_put(struct smbclient_context *ctx, char *rname, char *lname, BOOL reput)
1072 uint8_t *buf = NULL;
1073 int maxwrite = io_bufsize;
1076 struct timeval tp_start;
1077 GetTimeOfDay(&tp_start);
1080 fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT, DENY_NONE);
1082 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL)) &&
1083 NT_STATUS_IS_ERR(smbcli_getattrE(ctx->cli->tree, fnum, NULL, &start, NULL, NULL, NULL))) {
1084 d_printf("getattrib: %s\n",smbcli_errstr(ctx->cli->tree));
1089 fnum = smbcli_open(ctx->cli->tree, rname, O_RDWR|O_CREAT|O_TRUNC,
1094 d_printf("%s opening remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
1098 /* allow files to be piped into smbclient
1101 Note that in this case this function will exit(0) rather
1103 if (!strcmp(lname, "-")) {
1105 /* size of file is not known */
1107 f = x_fopen(lname,O_RDONLY, 0);
1109 if (x_tseek(f, start, SEEK_SET) == -1) {
1110 d_printf("Error seeking local file\n");
1117 d_printf("Error opening local file %s\n",lname);
1122 DEBUG(1,("putting file %s as %s ",lname,
1125 buf = (uint8_t *)malloc(maxwrite);
1127 d_printf("ERROR: Not enough memory!\n");
1130 while (!x_feof(f)) {
1134 if ((n = readfile(buf,n,f,ctx->translation)) < 1) {
1135 if((n == 0) && x_feof(f))
1136 break; /* Empty local file. */
1138 d_printf("Error reading local file: %s\n", strerror(errno));
1143 ret = smbcli_write(ctx->cli->tree, fnum, 0, buf, nread + start, n);
1146 d_printf("Error writing file: %s\n", smbcli_errstr(ctx->cli->tree));
1154 if (NT_STATUS_IS_ERR(smbcli_close(ctx->cli->tree, fnum))) {
1155 d_printf("%s closing remote file %s\n",smbcli_errstr(ctx->cli->tree),rname);
1169 struct timeval tp_end;
1172 GetTimeOfDay(&tp_end);
1174 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1175 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1176 put_total_time_ms += this_time;
1177 put_total_size += nread;
1179 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
1180 nread / (1.024*this_time + 1.0e-4),
1181 put_total_size / (1.024*put_total_time_ms)));
1194 /****************************************************************************
1196 ****************************************************************************/
1197 static int cmd_put(struct smbclient_context *ctx, const char **args)
1203 d_printf("put <filename> [<remotename>]\n");
1207 lname = talloc_strdup(ctx, args[1]);
1210 rname = talloc_strdup(ctx, args[2]);
1212 rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, lname);
1214 dos_clean_name(rname);
1216 /* allow '-' to represent stdin
1217 jdblair, 24.jun.98 */
1218 if (!file_exist(lname) && (strcmp(lname,"-"))) {
1219 d_printf("%s does not exist\n",lname);
1223 return do_put(ctx, rname, lname, False);
1226 /*************************************
1228 *************************************/
1230 static struct file_list {
1231 struct file_list *prev, *next;
1236 /****************************************************************************
1237 Free a file_list structure
1238 ****************************************************************************/
1240 static void free_file_list (struct file_list * list)
1242 struct file_list *tmp;
1247 DLIST_REMOVE(list, list);
1248 SAFE_FREE(tmp->file_path);
1253 /****************************************************************************
1254 seek in a directory/file list until you get something that doesn't start with
1256 ****************************************************************************/
1257 static BOOL seek_list(struct file_list *list, char *name)
1260 trim_string(list->file_path,"./","\n");
1261 if (strncmp(list->file_path, name, strlen(name)) != 0) {
1270 /****************************************************************************
1271 set the file selection mask
1272 ****************************************************************************/
1273 static int cmd_select(struct smbclient_context *ctx, const char **args)
1275 talloc_free(ctx->fileselection);
1276 ctx->fileselection = talloc_strdup(NULL, args[1]);
1281 /*******************************************************************
1282 A readdir wrapper which just returns the file name.
1283 ********************************************************************/
1284 static const char *readdirname(DIR *p)
1292 ptr = (struct dirent *)readdir(p);
1296 dname = ptr->d_name;
1303 #ifdef HAVE_BROKEN_READDIR
1304 /* using /usr/ucb/cc is BAD */
1310 int len = NAMLEN(ptr);
1311 buf = talloc_strndup(NULL, dname, len);
1318 /****************************************************************************
1319 Recursive file matching function act as find
1320 match must be always set to True when calling this function
1321 ****************************************************************************/
1322 static int file_find(struct smbclient_context *ctx, struct file_list **list, const char *directory,
1323 const char *expression, BOOL match)
1326 struct file_list *entry;
1327 struct stat statbuf;
1333 dir = opendir(directory);
1334 if (!dir) return -1;
1336 while ((dname = readdirname(dir))) {
1337 if (ISDOT(dname) || ISDOTDOT(dname)) {
1341 if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
1346 if (!match || !gen_fnmatch(expression, dname)) {
1348 ret = stat(path, &statbuf);
1350 if (S_ISDIR(statbuf.st_mode)) {
1352 ret = file_find(ctx, list, path, expression, False);
1355 d_printf("file_find: cannot stat file %s\n", path);
1364 entry = malloc_p(struct file_list);
1366 d_printf("Out of memory in file_find\n");
1370 entry->file_path = path;
1371 entry->isdir = isdir;
1372 DLIST_ADD(*list, entry);
1382 /****************************************************************************
1384 ****************************************************************************/
1385 static int cmd_mput(struct smbclient_context *ctx, const char **args)
1389 for (i = 1; args[i]; i++) {
1391 struct file_list *temp_list;
1392 char *quest, *lname, *rname;
1394 printf("%s\n", args[i]);
1398 ret = file_find(ctx, &file_list, ".", args[i], True);
1400 free_file_list(file_list);
1408 for (temp_list = file_list; temp_list;
1409 temp_list = temp_list->next) {
1412 if (asprintf(&lname, "%s/", temp_list->file_path) <= 0)
1414 trim_string(lname, "./", "/");
1416 /* check if it's a directory */
1417 if (temp_list->isdir) {
1418 /* if (!recurse) continue; */
1421 if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
1422 if (ctx->prompt && !yesno(quest)) { /* No */
1423 /* Skip the directory */
1424 lname[strlen(lname)-1] = '/';
1425 if (!seek_list(temp_list, lname))
1429 if(asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break;
1431 if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, rname)) &&
1432 NT_STATUS_IS_ERR(do_mkdir(ctx, rname))) {
1433 DEBUG (0, ("Unable to make dir, skipping..."));
1434 /* Skip the directory */
1435 lname[strlen(lname)-1] = '/';
1436 if (!seek_list(temp_list, lname))
1443 if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
1444 if (ctx->prompt && !yesno(quest)) /* No */
1449 if (asprintf(&rname, "%s%s", ctx->remote_cur_dir, lname) < 0) break;
1454 do_put(ctx, rname, lname, False);
1456 free_file_list(file_list);
1466 /****************************************************************************
1468 ****************************************************************************/
1469 static int cmd_print(struct smbclient_context *ctx, const char **args)
1471 char *lname, *rname;
1475 d_printf("print <filename>\n");
1479 lname = talloc_strdup(ctx, args[1]);
1481 rname = talloc_strdup(ctx, lname);
1482 p = strrchr_m(rname,'/');
1484 slprintf(rname, sizeof(rname)-1, "%s-%d", p+1, (int)getpid());
1487 if (strequal(lname,"-")) {
1488 slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)getpid());
1491 return do_put(ctx, rname, lname, False);
1495 static int cmd_rewrite(struct smbclient_context *ctx, const char **args)
1497 d_printf("REWRITE: command not implemented (FIXME!)\n");
1502 /****************************************************************************
1504 ****************************************************************************/
1505 static int cmd_del(struct smbclient_context *ctx, const char **args)
1508 uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
1511 attribute |= FILE_ATTRIBUTE_DIRECTORY;
1514 d_printf("del <filename>\n");
1517 mask = talloc_asprintf(ctx,"%s%s", ctx->remote_cur_dir, args[1]);
1519 if (NT_STATUS_IS_ERR(smbcli_unlink(ctx->cli->tree, mask))) {
1520 d_printf("%s deleting remote file %s\n",smbcli_errstr(ctx->cli->tree),mask);
1527 /****************************************************************************
1528 delete a whole directory tree
1529 ****************************************************************************/
1530 static int cmd_deltree(struct smbclient_context *ctx, const char **args)
1536 d_printf("deltree <dirname>\n");
1540 dname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
1542 ret = smbcli_deltree(ctx->cli->tree, dname);
1545 printf("Failed to delete tree %s - %s\n", dname, smbcli_errstr(ctx->cli->tree));
1549 printf("Deleted %d files in %s\n", ret, dname);
1555 const char *level_name;
1556 enum smb_fsinfo_level level;
1559 fsinfo_level_t fsinfo_levels[] = {
1560 {"dskattr", RAW_QFS_DSKATTR},
1561 {"allocation", RAW_QFS_ALLOCATION},
1562 {"volume", RAW_QFS_VOLUME},
1563 {"volumeinfo", RAW_QFS_VOLUME_INFO},
1564 {"sizeinfo", RAW_QFS_SIZE_INFO},
1565 {"deviceinfo", RAW_QFS_DEVICE_INFO},
1566 {"attributeinfo", RAW_QFS_ATTRIBUTE_INFO},
1567 {"unixinfo", RAW_QFS_UNIX_INFO},
1568 {"volume-information", RAW_QFS_VOLUME_INFORMATION},
1569 {"size-information", RAW_QFS_SIZE_INFORMATION},
1570 {"device-information", RAW_QFS_DEVICE_INFORMATION},
1571 {"attribute-information", RAW_QFS_ATTRIBUTE_INFORMATION},
1572 {"quota-information", RAW_QFS_QUOTA_INFORMATION},
1573 {"fullsize-information", RAW_QFS_FULL_SIZE_INFORMATION},
1574 {"objectid", RAW_QFS_OBJECTID_INFORMATION},
1575 {NULL, RAW_QFS_GENERIC}
1579 static int cmd_fsinfo(struct smbclient_context *ctx, const char **args)
1581 union smb_fsinfo fsinfo;
1583 fsinfo_level_t *fsinfo_level;
1586 d_printf("fsinfo <level>, where level is one of following:\n");
1587 fsinfo_level = fsinfo_levels;
1588 while(fsinfo_level->level_name) {
1589 d_printf("%s\n", fsinfo_level->level_name);
1595 fsinfo_level = fsinfo_levels;
1596 while(fsinfo_level->level_name && !strequal(args[1],fsinfo_level->level_name)) {
1600 if (!fsinfo_level->level_name) {
1601 d_printf("wrong level name!\n");
1605 fsinfo.generic.level = fsinfo_level->level;
1606 status = smb_raw_fsinfo(ctx->cli->tree, ctx, &fsinfo);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 d_printf("fsinfo-level-%s - %s\n", fsinfo_level->level_name, nt_errstr(status));
1612 d_printf("fsinfo-level-%s:\n", fsinfo_level->level_name);
1613 switch(fsinfo.generic.level) {
1614 case RAW_QFS_DSKATTR:
1615 d_printf("\tunits_total: %hu\n",
1616 (unsigned short) fsinfo.dskattr.out.units_total);
1617 d_printf("\tblocks_per_unit: %hu\n",
1618 (unsigned short) fsinfo.dskattr.out.blocks_per_unit);
1619 d_printf("\tblocks_size: %hu\n",
1620 (unsigned short) fsinfo.dskattr.out.block_size);
1621 d_printf("\tunits_free: %hu\n",
1622 (unsigned short) fsinfo.dskattr.out.units_free);
1624 case RAW_QFS_ALLOCATION:
1625 d_printf("\tfs_id: %lu\n",
1626 (unsigned long) fsinfo.allocation.out.fs_id);
1627 d_printf("\tsectors_per_unit: %lu\n",
1628 (unsigned long) fsinfo.allocation.out.sectors_per_unit);
1629 d_printf("\ttotal_alloc_units: %lu\n",
1630 (unsigned long) fsinfo.allocation.out.total_alloc_units);
1631 d_printf("\tavail_alloc_units: %lu\n",
1632 (unsigned long) fsinfo.allocation.out.avail_alloc_units);
1633 d_printf("\tbytes_per_sector: %hu\n",
1634 (unsigned short) fsinfo.allocation.out.bytes_per_sector);
1636 case RAW_QFS_VOLUME:
1637 d_printf("\tserial_number: %lu\n",
1638 (unsigned long) fsinfo.volume.out.serial_number);
1639 d_printf("\tvolume_name: %s\n", fsinfo.volume.out.volume_name.s);
1641 case RAW_QFS_VOLUME_INFO:
1642 case RAW_QFS_VOLUME_INFORMATION:
1643 d_printf("\tcreate_time: %s\n",
1644 nt_time_string(ctx,fsinfo.volume_info.out.create_time));
1645 d_printf("\tserial_number: %lu\n",
1646 (unsigned long) fsinfo.volume_info.out.serial_number);
1647 d_printf("\tvolume_name: %s\n", fsinfo.volume_info.out.volume_name.s);
1649 case RAW_QFS_SIZE_INFO:
1650 case RAW_QFS_SIZE_INFORMATION:
1651 d_printf("\ttotal_alloc_units: %llu\n",
1652 (unsigned long long) fsinfo.size_info.out.total_alloc_units);
1653 d_printf("\tavail_alloc_units: %llu\n",
1654 (unsigned long long) fsinfo.size_info.out.avail_alloc_units);
1655 d_printf("\tsectors_per_unit: %lu\n",
1656 (unsigned long) fsinfo.size_info.out.sectors_per_unit);
1657 d_printf("\tbytes_per_sector: %lu\n",
1658 (unsigned long) fsinfo.size_info.out.bytes_per_sector);
1660 case RAW_QFS_DEVICE_INFO:
1661 case RAW_QFS_DEVICE_INFORMATION:
1662 d_printf("\tdevice_type: %lu\n",
1663 (unsigned long) fsinfo.device_info.out.device_type);
1664 d_printf("\tcharacteristics: 0x%lx\n",
1665 (unsigned long) fsinfo.device_info.out.characteristics);
1667 case RAW_QFS_ATTRIBUTE_INFORMATION:
1668 case RAW_QFS_ATTRIBUTE_INFO:
1669 d_printf("\tfs_attr: 0x%lx\n",
1670 (unsigned long) fsinfo.attribute_info.out.fs_attr);
1671 d_printf("\tmax_file_component_length: %lu\n",
1672 (unsigned long) fsinfo.attribute_info.out.max_file_component_length);
1673 d_printf("\tfs_type: %s\n", fsinfo.attribute_info.out.fs_type.s);
1675 case RAW_QFS_UNIX_INFO:
1676 d_printf("\tmajor_version: %hu\n",
1677 (unsigned short) fsinfo.unix_info.out.major_version);
1678 d_printf("\tminor_version: %hu\n",
1679 (unsigned short) fsinfo.unix_info.out.minor_version);
1680 d_printf("\tcapability: 0x%llx\n",
1681 (unsigned long long) fsinfo.unix_info.out.capability);
1683 case RAW_QFS_QUOTA_INFORMATION:
1684 d_printf("\tunknown[3]: [%llu,%llu,%llu]\n",
1685 (unsigned long long) fsinfo.quota_information.out.unknown[0],
1686 (unsigned long long) fsinfo.quota_information.out.unknown[1],
1687 (unsigned long long) fsinfo.quota_information.out.unknown[2]);
1688 d_printf("\tquota_soft: %llu\n",
1689 (unsigned long long) fsinfo.quota_information.out.quota_soft);
1690 d_printf("\tquota_hard: %llu\n",
1691 (unsigned long long) fsinfo.quota_information.out.quota_hard);
1692 d_printf("\tquota_flags: 0x%llx\n",
1693 (unsigned long long) fsinfo.quota_information.out.quota_flags);
1695 case RAW_QFS_FULL_SIZE_INFORMATION:
1696 d_printf("\ttotal_alloc_units: %llu\n",
1697 (unsigned long long) fsinfo.full_size_information.out.total_alloc_units);
1698 d_printf("\tcall_avail_alloc_units: %llu\n",
1699 (unsigned long long) fsinfo.full_size_information.out.call_avail_alloc_units);
1700 d_printf("\tactual_avail_alloc_units: %llu\n",
1701 (unsigned long long) fsinfo.full_size_information.out.actual_avail_alloc_units);
1702 d_printf("\tsectors_per_unit: %lu\n",
1703 (unsigned long) fsinfo.full_size_information.out.sectors_per_unit);
1704 d_printf("\tbytes_per_sector: %lu\n",
1705 (unsigned long) fsinfo.full_size_information.out.bytes_per_sector);
1707 case RAW_QFS_OBJECTID_INFORMATION:
1708 d_printf("\tGUID: %s\n",
1709 GUID_string(ctx,&fsinfo.objectid_information.out.guid));
1710 d_printf("\tunknown[6]: [%llu,%llu,%llu,%llu,%llu,%llu]\n",
1711 (unsigned long long) fsinfo.objectid_information.out.unknown[0],
1712 (unsigned long long) fsinfo.objectid_information.out.unknown[1],
1713 (unsigned long long) fsinfo.objectid_information.out.unknown[2],
1714 (unsigned long long) fsinfo.objectid_information.out.unknown[3],
1715 (unsigned long long) fsinfo.objectid_information.out.unknown[4],
1716 (unsigned long long) fsinfo.objectid_information.out.unknown[5] );
1718 case RAW_QFS_GENERIC:
1719 d_printf("\twrong level returned\n");
1726 /****************************************************************************
1727 show as much information as possible about a file
1728 ****************************************************************************/
1729 static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
1732 union smb_fileinfo finfo;
1736 d_printf("allinfo <filename>\n");
1739 fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
1741 /* first a ALL_INFO QPATHINFO */
1742 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1743 finfo.generic.in.file.path = fname;
1744 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 d_printf("%s - %s\n", fname, nt_errstr(status));
1750 d_printf("\tcreate_time: %s\n", nt_time_string(ctx, finfo.all_info.out.create_time));
1751 d_printf("\taccess_time: %s\n", nt_time_string(ctx, finfo.all_info.out.access_time));
1752 d_printf("\twrite_time: %s\n", nt_time_string(ctx, finfo.all_info.out.write_time));
1753 d_printf("\tchange_time: %s\n", nt_time_string(ctx, finfo.all_info.out.change_time));
1754 d_printf("\tattrib: 0x%x\n", finfo.all_info.out.attrib);
1755 d_printf("\talloc_size: %lu\n", (unsigned long)finfo.all_info.out.alloc_size);
1756 d_printf("\tsize: %lu\n", (unsigned long)finfo.all_info.out.size);
1757 d_printf("\tnlink: %u\n", finfo.all_info.out.nlink);
1758 d_printf("\tdelete_pending: %u\n", finfo.all_info.out.delete_pending);
1759 d_printf("\tdirectory: %u\n", finfo.all_info.out.directory);
1760 d_printf("\tea_size: %u\n", finfo.all_info.out.ea_size);
1761 d_printf("\tfname: '%s'\n", finfo.all_info.out.fname.s);
1763 /* 8.3 name if any */
1764 finfo.generic.level = RAW_FILEINFO_ALT_NAME_INFO;
1765 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1766 if (NT_STATUS_IS_OK(status)) {
1767 d_printf("\talt_name: %s\n", finfo.alt_name_info.out.fname.s);
1770 /* file_id if available */
1771 finfo.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
1772 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1773 if (NT_STATUS_IS_OK(status)) {
1774 d_printf("\tfile_id %.0f\n",
1775 (double)finfo.internal_information.out.file_id);
1778 /* the EAs, if any */
1779 finfo.generic.level = RAW_FILEINFO_ALL_EAS;
1780 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1781 if (NT_STATUS_IS_OK(status)) {
1783 for (i=0;i<finfo.all_eas.out.num_eas;i++) {
1784 d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
1785 finfo.all_eas.out.eas[i].flags,
1786 (int)finfo.all_eas.out.eas[i].value.length,
1787 finfo.all_eas.out.eas[i].name.s);
1791 /* streams, if available */
1792 finfo.generic.level = RAW_FILEINFO_STREAM_INFO;
1793 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1794 if (NT_STATUS_IS_OK(status)) {
1796 for (i=0;i<finfo.stream_info.out.num_streams;i++) {
1797 d_printf("\tstream %d:\n", i);
1798 d_printf("\t\tsize %ld\n",
1799 (long)finfo.stream_info.out.streams[i].size);
1800 d_printf("\t\talloc size %ld\n",
1801 (long)finfo.stream_info.out.streams[i].alloc_size);
1802 d_printf("\t\tname %s\n", finfo.stream_info.out.streams[i].stream_name.s);
1806 /* dev/inode if available */
1807 finfo.generic.level = RAW_FILEINFO_COMPRESSION_INFORMATION;
1808 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1809 if (NT_STATUS_IS_OK(status)) {
1810 d_printf("\tcompressed size %ld\n", (long)finfo.compression_info.out.compressed_size);
1811 d_printf("\tformat %ld\n", (long)finfo.compression_info.out.format);
1812 d_printf("\tunit_shift %ld\n", (long)finfo.compression_info.out.unit_shift);
1813 d_printf("\tchunk_shift %ld\n", (long)finfo.compression_info.out.chunk_shift);
1814 d_printf("\tcluster_shift %ld\n", (long)finfo.compression_info.out.cluster_shift);
1821 /****************************************************************************
1823 ****************************************************************************/
1824 static int cmd_eainfo(struct smbclient_context *ctx, const char **args)
1827 union smb_fileinfo finfo;
1832 d_printf("eainfo <filename>\n");
1835 fname = talloc_strdup(ctx, args[1]);
1837 finfo.generic.level = RAW_FILEINFO_ALL_EAS;
1838 finfo.generic.in.file.path = fname;
1839 status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 d_printf("RAW_FILEINFO_ALL_EAS - %s\n", nt_errstr(status));
1846 d_printf("%s has %d EAs\n", fname, finfo.all_eas.out.num_eas);
1848 for (i=0;i<finfo.all_eas.out.num_eas;i++) {
1849 d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
1850 finfo.all_eas.out.eas[i].flags,
1851 (int)finfo.all_eas.out.eas[i].value.length,
1852 finfo.all_eas.out.eas[i].name.s);
1855 finfo.all_eas.out.eas[i].value.data,
1856 finfo.all_eas.out.eas[i].value.length);
1863 /****************************************************************************
1864 show any ACL on a file
1865 ****************************************************************************/
1866 static int cmd_acl(struct smbclient_context *ctx, const char **args)
1869 union smb_fileinfo query;
1874 d_printf("acl <filename>\n");
1877 fname = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
1879 fnum = smbcli_nt_create_full(ctx->cli->tree, fname, 0,
1880 SEC_STD_READ_CONTROL,
1882 NTCREATEX_SHARE_ACCESS_DELETE|
1883 NTCREATEX_SHARE_ACCESS_READ|
1884 NTCREATEX_SHARE_ACCESS_WRITE,
1885 NTCREATEX_DISP_OPEN,
1888 d_printf("%s - %s\n", fname, smbcli_errstr(ctx->cli->tree));
1892 query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1893 query.query_secdesc.in.file.fnum = fnum;
1894 query.query_secdesc.in.secinfo_flags = 0x7;
1896 status = smb_raw_fileinfo(ctx->cli->tree, ctx, &query);
1897 if (!NT_STATUS_IS_OK(status)) {
1898 d_printf("%s - %s\n", fname, nt_errstr(status));
1902 NDR_PRINT_DEBUG(security_descriptor, query.query_secdesc.out.sd);
1907 /****************************************************************************
1908 lookup a name or sid
1909 ****************************************************************************/
1910 static int cmd_lookup(struct smbclient_context *ctx, const char **args)
1913 struct dom_sid *sid;
1916 d_printf("lookup <sid|name>\n");
1920 sid = dom_sid_parse_talloc(ctx, args[1]);
1923 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sidstr);
1924 if (!NT_STATUS_IS_OK(status)) {
1925 d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
1929 d_printf("%s\n", sidstr);
1932 status = smblsa_lookup_sid(ctx->cli, args[1], ctx, &name);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 d_printf("lsa_LookupSids - %s\n", nt_errstr(status));
1938 d_printf("%s\n", name);
1944 /****************************************************************************
1945 show privileges for a user
1946 ****************************************************************************/
1947 static int cmd_privileges(struct smbclient_context *ctx, const char **args)
1950 struct dom_sid *sid;
1951 struct lsa_RightSet rights;
1955 d_printf("privileges <sid|name>\n");
1959 sid = dom_sid_parse_talloc(ctx, args[1]);
1961 const char *sid_str;
1962 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
1967 sid = dom_sid_parse_talloc(ctx, sid_str);
1970 status = smblsa_sid_privileges(ctx->cli, sid, ctx, &rights);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 d_printf("lsa_EnumAccountRights - %s\n", nt_errstr(status));
1976 for (i=0;i<rights.count;i++) {
1977 d_printf("\t%s\n", rights.names[i].string);
1984 /****************************************************************************
1985 add privileges for a user
1986 ****************************************************************************/
1987 static int cmd_addprivileges(struct smbclient_context *ctx, const char **args)
1990 struct dom_sid *sid;
1991 struct lsa_RightSet rights;
1995 d_printf("addprivileges <sid|name> <privilege...>\n");
1999 sid = dom_sid_parse_talloc(ctx, args[1]);
2001 const char *sid_str;
2002 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
2003 if (!NT_STATUS_IS_OK(status)) {
2004 d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
2007 sid = dom_sid_parse_talloc(ctx, sid_str);
2010 ZERO_STRUCT(rights);
2011 for (i = 2; args[i]; i++) {
2012 rights.names = talloc_realloc(ctx, rights.names,
2013 struct lsa_StringLarge, rights.count+1);
2014 rights.names[rights.count].string = talloc_strdup(ctx, args[i]);
2019 status = smblsa_sid_add_privileges(ctx->cli, sid, ctx, &rights);
2020 if (!NT_STATUS_IS_OK(status)) {
2021 d_printf("lsa_AddAccountRights - %s\n", nt_errstr(status));
2028 /****************************************************************************
2029 delete privileges for a user
2030 ****************************************************************************/
2031 static int cmd_delprivileges(struct smbclient_context *ctx, const char **args)
2034 struct dom_sid *sid;
2035 struct lsa_RightSet rights;
2039 d_printf("delprivileges <sid|name> <privilege...>\n");
2043 sid = dom_sid_parse_talloc(ctx, args[1]);
2045 const char *sid_str;
2046 status = smblsa_lookup_name(ctx->cli, args[1], ctx, &sid_str);
2047 if (!NT_STATUS_IS_OK(status)) {
2048 d_printf("lsa_LookupNames - %s\n", nt_errstr(status));
2051 sid = dom_sid_parse_talloc(ctx, sid_str);
2054 ZERO_STRUCT(rights);
2055 for (i = 2; args[i]; i++) {
2056 rights.names = talloc_realloc(ctx, rights.names,
2057 struct lsa_StringLarge, rights.count+1);
2058 rights.names[rights.count].string = talloc_strdup(ctx, args[i]);
2063 status = smblsa_sid_del_privileges(ctx->cli, sid, ctx, &rights);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 d_printf("lsa_RemoveAccountRights - %s\n", nt_errstr(status));
2073 /****************************************************************************
2074 ****************************************************************************/
2075 static int cmd_open(struct smbclient_context *ctx, const char **args)
2080 d_printf("open <filename>\n");
2083 mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
2085 smbcli_open(ctx->cli->tree, mask, O_RDWR, DENY_ALL);
2091 /****************************************************************************
2093 ****************************************************************************/
2094 static int cmd_rmdir(struct smbclient_context *ctx, const char **args)
2099 d_printf("rmdir <dirname>\n");
2102 mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
2104 if (NT_STATUS_IS_ERR(smbcli_rmdir(ctx->cli->tree, mask))) {
2105 d_printf("%s removing remote directory file %s\n",
2106 smbcli_errstr(ctx->cli->tree),mask);
2112 /****************************************************************************
2114 ****************************************************************************/
2115 static int cmd_link(struct smbclient_context *ctx, const char **args)
2119 if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
2120 d_printf("Server doesn't support UNIX CIFS calls.\n");
2125 if (!args[1] || !args[2]) {
2126 d_printf("link <src> <dest>\n");
2130 src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
2131 dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
2133 if (NT_STATUS_IS_ERR(smbcli_unix_hardlink(ctx->cli->tree, src, dest))) {
2134 d_printf("%s linking files (%s -> %s)\n", smbcli_errstr(ctx->cli->tree), src, dest);
2141 /****************************************************************************
2143 ****************************************************************************/
2145 static int cmd_symlink(struct smbclient_context *ctx, const char **args)
2149 if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
2150 d_printf("Server doesn't support UNIX CIFS calls.\n");
2154 if (!args[1] || !args[2]) {
2155 d_printf("symlink <src> <dest>\n");
2159 src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
2160 dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
2162 if (NT_STATUS_IS_ERR(smbcli_unix_symlink(ctx->cli->tree, src, dest))) {
2163 d_printf("%s symlinking files (%s -> %s)\n",
2164 smbcli_errstr(ctx->cli->tree), src, dest);
2171 /****************************************************************************
2173 ****************************************************************************/
2175 static int cmd_chmod(struct smbclient_context *ctx, const char **args)
2180 if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
2181 d_printf("Server doesn't support UNIX CIFS calls.\n");
2185 if (!args[1] || !args[2]) {
2186 d_printf("chmod mode file\n");
2190 src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
2192 mode = (mode_t)strtol(args[1], NULL, 8);
2194 if (NT_STATUS_IS_ERR(smbcli_unix_chmod(ctx->cli->tree, src, mode))) {
2195 d_printf("%s chmod file %s 0%o\n",
2196 smbcli_errstr(ctx->cli->tree), src, (mode_t)mode);
2203 /****************************************************************************
2205 ****************************************************************************/
2207 static int cmd_chown(struct smbclient_context *ctx, const char **args)
2213 if (!(ctx->cli->transport->negotiate.capabilities & CAP_UNIX)) {
2214 d_printf("Server doesn't support UNIX CIFS calls.\n");
2218 if (!args[1] || !args[2] || !args[3]) {
2219 d_printf("chown uid gid file\n");
2223 uid = (uid_t)atoi(args[1]);
2224 gid = (gid_t)atoi(args[2]);
2225 src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[3]);
2227 if (NT_STATUS_IS_ERR(smbcli_unix_chown(ctx->cli->tree, src, uid, gid))) {
2228 d_printf("%s chown file %s uid=%d, gid=%d\n",
2229 smbcli_errstr(ctx->cli->tree), src, (int)uid, (int)gid);
2236 /****************************************************************************
2238 ****************************************************************************/
2239 static int cmd_rename(struct smbclient_context *ctx, const char **args)
2243 if (!args[1] || !args[2]) {
2244 d_printf("rename <src> <dest>\n");
2248 src = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
2249 dest = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[2]);
2251 if (NT_STATUS_IS_ERR(smbcli_rename(ctx->cli->tree, src, dest))) {
2252 d_printf("%s renaming files\n",smbcli_errstr(ctx->cli->tree));
2260 /****************************************************************************
2261 toggle the prompt flag
2262 ****************************************************************************/
2263 static int cmd_prompt(struct smbclient_context *ctx, const char **args)
2265 ctx->prompt = !ctx->prompt;
2266 DEBUG(2,("prompting is now %s\n",ctx->prompt?"on":"off"));
2272 /****************************************************************************
2273 set the newer than time
2274 ****************************************************************************/
2275 static int cmd_newer(struct smbclient_context *ctx, const char **args)
2279 if (args[1] && (stat(args[1],&sbuf) == 0)) {
2280 ctx->newer_than = sbuf.st_mtime;
2281 DEBUG(1,("Getting files newer than %s",
2282 asctime(localtime(&ctx->newer_than))));
2284 ctx->newer_than = 0;
2287 if (args[1] && ctx->newer_than == 0) {
2288 d_printf("Error setting newer-than time\n");
2295 /****************************************************************************
2296 set the archive level
2297 ****************************************************************************/
2298 static int cmd_archive(struct smbclient_context *ctx, const char **args)
2301 ctx->archive_level = atoi(args[1]);
2303 d_printf("Archive level is %d\n",ctx->archive_level);
2308 /****************************************************************************
2309 toggle the lowercaseflag
2310 ****************************************************************************/
2311 static int cmd_lowercase(struct smbclient_context *ctx, const char **args)
2313 ctx->lowercase = !ctx->lowercase;
2314 DEBUG(2,("filename lowercasing is now %s\n",ctx->lowercase?"on":"off"));
2322 /****************************************************************************
2323 toggle the recurse flag
2324 ****************************************************************************/
2325 static int cmd_recurse(struct smbclient_context *ctx, const char **args)
2327 ctx->recurse = !ctx->recurse;
2328 DEBUG(2,("directory recursion is now %s\n",ctx->recurse?"on":"off"));
2333 /****************************************************************************
2334 toggle the translate flag
2335 ****************************************************************************/
2336 static int cmd_translate(struct smbclient_context *ctx, const char **args)
2338 ctx->translation = !ctx->translation;
2339 DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
2340 ctx->translation?"on":"off"));
2346 /****************************************************************************
2347 do a printmode command
2348 ****************************************************************************/
2349 static int cmd_printmode(struct smbclient_context *ctx, const char **args)
2352 if (strequal(args[1],"text")) {
2355 if (strequal(args[1],"graphics"))
2358 ctx->printmode = atoi(args[1]);
2362 switch(ctx->printmode)
2365 DEBUG(2,("the printmode is now text\n"));
2368 DEBUG(2,("the printmode is now graphics\n"));
2371 DEBUG(2,("the printmode is now %d\n", ctx->printmode));
2378 /****************************************************************************
2380 ****************************************************************************/
2381 static int cmd_lcd(struct smbclient_context *ctx, const char **args)
2387 DEBUG(2,("the local directory is now %s\n",getcwd(d, PATH_MAX)));
2392 /****************************************************************************
2394 ****************************************************************************/
2395 static int cmd_history(struct smbclient_context *ctx, const char **args)
2397 #if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
2401 hlist = history_list();
2403 for (i = 0; hlist && hlist[i]; i++) {
2404 DEBUG(0, ("%d: %s\n", i, hlist[i]->line));
2407 DEBUG(0,("no history without readline support\n"));
2413 /****************************************************************************
2414 get a file restarting at end of local file
2415 ****************************************************************************/
2416 static int cmd_reget(struct smbclient_context *ctx, const char **args)
2422 d_printf("reget <filename>\n");
2425 remote_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
2426 dos_clean_name(remote_name);
2429 local_name = talloc_strdup(ctx, args[2]);
2431 local_name = talloc_strdup(ctx, args[1]);
2433 return do_get(ctx, remote_name, local_name, True);
2436 /****************************************************************************
2437 put a file restarting at end of local file
2438 ****************************************************************************/
2439 static int cmd_reput(struct smbclient_context *ctx, const char **args)
2445 d_printf("reput <filename>\n");
2448 local_name = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
2450 if (!file_exist(local_name)) {
2451 d_printf("%s does not exist\n", local_name);
2456 remote_name = talloc_strdup(ctx, args[2]);
2458 remote_name = talloc_strdup(ctx, args[1]);
2460 dos_clean_name(remote_name);
2462 return do_put(ctx, remote_name, local_name, True);
2467 return a string representing a share type
2469 static const char *share_type_str(uint32_t type)
2471 switch (type & 0xF) {
2472 case STYPE_DISKTREE:
2487 display a list of shares from a level 1 share enum
2489 static void display_share_result(struct srvsvc_NetShareCtr1 *ctr1)
2493 for (i=0;i<ctr1->count;i++) {
2494 struct srvsvc_NetShareInfo1 *info = ctr1->array+i;
2496 printf("\t%-15s %-10.10s %s\n",
2498 share_type_str(info->type),
2505 /****************************************************************************
2506 try and browse available shares on a host
2507 ****************************************************************************/
2508 static BOOL browse_host(const char *query_host)
2510 struct dcerpc_pipe *p;
2513 struct srvsvc_NetShareEnumAll r;
2514 uint32_t resume_handle = 0;
2515 TALLOC_CTX *mem_ctx = talloc_init("browse_host");
2516 struct srvsvc_NetShareCtr1 ctr1;
2518 binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", query_host);
2520 status = dcerpc_pipe_connect(mem_ctx, &p, binding,
2521 &dcerpc_table_srvsvc,
2522 cmdline_credentials, NULL);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 d_printf("Failed to connect to %s - %s\n",
2525 binding, nt_errstr(status));
2526 talloc_free(mem_ctx);
2530 r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
2532 r.in.ctr.ctr1 = &ctr1;
2533 r.in.max_buffer = ~0;
2534 r.in.resume_handle = &resume_handle;
2536 d_printf("\n\tSharename Type Comment\n");
2537 d_printf("\t--------- ---- -------\n");
2541 status = dcerpc_srvsvc_NetShareEnumAll(p, mem_ctx, &r);
2543 if (NT_STATUS_IS_OK(status) &&
2544 (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA) ||
2545 W_ERROR_IS_OK(r.out.result)) &&
2547 display_share_result(r.out.ctr.ctr1);
2548 resume_handle += r.out.ctr.ctr1->count;
2550 } while (NT_STATUS_IS_OK(status) && W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
2552 talloc_free(mem_ctx);
2554 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2555 d_printf("Failed NetShareEnumAll %s - %s/%s\n",
2556 binding, nt_errstr(status), win_errstr(r.out.result));
2563 /****************************************************************************
2564 try and browse available connections on a host
2565 ****************************************************************************/
2566 static BOOL list_servers(const char *wk_grp)
2568 d_printf("REWRITE: list servers not implemented\n");
2572 /* Some constants for completing filename arguments */
2574 #define COMPL_NONE 0 /* No completions */
2575 #define COMPL_REMOTE 1 /* Complete remote filename */
2576 #define COMPL_LOCAL 2 /* Complete local filename */
2578 static int cmd_help(struct smbclient_context *ctx, const char **args);
2580 /* This defines the commands supported by this client.
2581 * NOTE: The "!" must be the last one in the list because it's fn pointer
2582 * field is NULL, and NULL in that field is used in process_tok()
2583 * (below) to indicate the end of the list. crh
2588 int (*fn)(struct smbclient_context *ctx, const char **args);
2589 const char *description;
2590 char compl_args[2]; /* Completion argument info */
2593 {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
2594 {"addprivileges",cmd_addprivileges,"<sid|name> <privilege...> add privileges for a user",{COMPL_NONE,COMPL_NONE}},
2595 {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
2596 {"acl",cmd_acl,"<file> show file ACL",{COMPL_NONE,COMPL_NONE}},
2597 {"allinfo",cmd_allinfo,"<file> show all possible info about a file",{COMPL_NONE,COMPL_NONE}},
2598 {"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}},
2599 {"cancel",cmd_rewrite,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
2600 {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
2601 {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
2602 {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
2603 {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
2604 {"delprivileges",cmd_delprivileges,"<sid|name> <privilege...> remove privileges for a user",{COMPL_NONE,COMPL_NONE}},
2605 {"deltree",cmd_deltree,"<dir> delete a whole directory tree",{COMPL_REMOTE,COMPL_NONE}},
2606 {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
2607 {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
2608 {"eainfo",cmd_eainfo,"<file> show EA contents for a file",{COMPL_NONE,COMPL_NONE}},
2609 {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
2610 {"fsinfo",cmd_fsinfo,"query file system info",{COMPL_NONE,COMPL_NONE}},
2611 {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
2612 {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
2613 {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
2614 {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
2615 {"link",cmd_link,"<src> <dest> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
2616 {"lookup",cmd_lookup,"<sid|name> show SID for name or name for SID",{COMPL_NONE,COMPL_NONE}},
2617 {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
2618 {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
2619 {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
2620 {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
2621 {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
2622 {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
2623 {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
2624 {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
2625 {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
2626 {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
2627 {"privileges",cmd_privileges,"<user> show privileges for a user",{COMPL_NONE,COMPL_NONE}},
2628 {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
2629 {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
2630 {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
2631 {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
2632 {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
2633 {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
2634 {"queue",cmd_rewrite,"show the print queue",{COMPL_NONE,COMPL_NONE}},
2635 {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
2636 {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
2637 {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
2638 {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
2639 {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
2640 {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
2641 {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
2642 {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
2643 {"symlink",cmd_symlink,"<src> <dest> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
2644 {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
2646 /* Yes, this must be here, see crh's comment above. */
2647 {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
2648 {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
2652 /*******************************************************************
2653 lookup a command string in the list of commands, including
2655 ******************************************************************/
2656 static int process_tok(const char *tok)
2658 int i = 0, matches = 0;
2660 int tok_len = strlen(tok);
2662 while (commands[i].fn != NULL) {
2663 if (strequal(commands[i].name,tok)) {
2667 } else if (strncasecmp(commands[i].name, tok, tok_len) == 0) {
2676 else if (matches == 1)
2682 /****************************************************************************
2684 ****************************************************************************/
2685 static int cmd_help(struct smbclient_context *ctx, const char **args)
2690 if ((i = process_tok(args[1])) >= 0)
2691 d_printf("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);
2693 while (commands[i].description) {
2694 for (j=0; commands[i].description && (j<5); j++) {
2695 d_printf("%-15s",commands[i].name);
2704 static int process_line(struct smbclient_context *ctx, const char *cline);
2705 /****************************************************************************
2706 process a -c command string
2707 ****************************************************************************/
2708 static int process_command_string(struct smbclient_context *ctx, const char *cmd)
2713 lines = str_list_make(NULL, cmd, ";");
2714 for (i = 0; lines[i]; i++) {
2715 rc |= process_line(ctx, lines[i]);
2722 #define MAX_COMPLETIONS 100
2730 } completion_remote_t;
2732 static void completion_remote_filter(struct clilist_file_info *f, const char *mask, void *state)
2734 completion_remote_t *info = (completion_remote_t *)state;
2736 if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (!ISDOT(f->name)) && (!ISDOTDOT(f->name))) {
2737 if ((info->dirmask[0] == 0) && !(f->attrib & FILE_ATTRIBUTE_DIRECTORY))
2738 info->matches[info->count] = strdup(f->name);
2742 if (info->dirmask[0] != 0)
2743 tmp = talloc_asprintf(NULL, "%s/%s", info->dirmask, f->name);
2745 tmp = talloc_strdup(NULL, f->name);
2747 if (f->attrib & FILE_ATTRIBUTE_DIRECTORY)
2748 tmp = talloc_append_string(NULL, tmp, "/");
2749 info->matches[info->count] = tmp;
2751 if (info->matches[info->count] == NULL)
2753 if (f->attrib & FILE_ATTRIBUTE_DIRECTORY)
2754 smb_readline_ca_char(0);
2756 if (info->count == 1)
2757 info->samelen = strlen(info->matches[info->count]);
2759 while (strncmp(info->matches[info->count], info->matches[info->count-1], info->samelen) != 0)
2765 static char **remote_completion(const char *text, int len)
2769 completion_remote_t info;
2775 if (len >= PATH_MAX)
2778 info.matches = malloc_array_p(char *, MAX_COMPLETIONS);
2779 if (!info.matches) return NULL;
2780 info.matches[0] = NULL;
2782 for (i = len-1; i >= 0; i--)
2783 if ((text[i] == '/') || (text[i] == '\\'))
2785 info.text = text+i+1;
2786 info.samelen = info.len = len-i-1;
2789 info.dirmask = talloc_strndup(NULL, text, i+1);
2790 info.dirmask[i+1] = 0;
2791 asprintf(&dirmask, "%s%*s*", rl_ctx->remote_cur_dir, i-1, text);
2793 asprintf(&dirmask, "%s*", rl_ctx->remote_cur_dir);
2795 if (smbcli_list(rl_ctx->cli->tree, dirmask,
2796 FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
2797 completion_remote_filter, &info) < 0)
2800 if (info.count == 2)
2801 info.matches[0] = strdup(info.matches[1]);
2803 info.matches[0] = malloc(info.samelen+1);
2804 if (!info.matches[0])
2806 strncpy(info.matches[0], info.matches[1], info.samelen);
2807 info.matches[0][info.samelen] = 0;
2809 info.matches[info.count] = NULL;
2810 return info.matches;
2813 for (i = 0; i < info.count; i++)
2814 free(info.matches[i]);
2819 static char **completion_fn(const char *text, int start, int end)
2821 smb_readline_ca_char(' ');
2824 const char *buf, *sp;
2828 buf = smb_readline_get_line_buffer();
2832 sp = strchr(buf, ' ');
2836 for (i = 0; commands[i].name; i++)
2837 if ((strncmp(commands[i].name, text, sp - buf) == 0) && (commands[i].name[sp - buf] == 0))
2839 if (commands[i].name == NULL)
2845 if (sp == (buf + start))
2846 compl_type = commands[i].compl_args[0];
2848 compl_type = commands[i].compl_args[1];
2850 if (compl_type == COMPL_REMOTE)
2851 return remote_completion(text, end - start);
2852 else /* fall back to local filename completion */
2856 int i, len, samelen = 0, count=1;
2858 matches = malloc_array_p(char *, MAX_COMPLETIONS);
2859 if (!matches) return NULL;
2863 for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
2864 if (strncmp(text, commands[i].name, len) == 0) {
2865 matches[count] = strdup(commands[i].name);
2866 if (!matches[count])
2869 samelen = strlen(matches[count]);
2871 while (strncmp(matches[count], matches[count-1], samelen) != 0)
2878 case 0: /* should never happen */
2882 matches[0] = strdup(matches[1]);
2885 matches[0] = malloc(samelen+1);
2888 strncpy(matches[0], matches[1], samelen);
2889 matches[0][samelen] = 0;
2891 matches[count] = NULL;
2904 /****************************************************************************
2905 make sure we swallow keepalives during idle time
2906 ****************************************************************************/
2907 static void readline_callback(void)
2909 static time_t last_t;
2914 if (t - last_t < 5) return;
2918 smbcli_transport_process(rl_ctx->cli->transport);
2920 if (rl_ctx->cli->tree) {
2921 smbcli_chkpath(rl_ctx->cli->tree, "\\");
2925 static int process_line(struct smbclient_context *ctx, const char *cline)
2930 /* and get the first part of the command */
2931 args = str_list_make_shell(ctx, cline, NULL);
2932 if (!args || !args[0])
2935 if ((i = process_tok(args[0])) >= 0) {
2936 i = commands[i].fn(ctx, args);
2937 } else if (i == -2) {
2938 d_printf("%s: command abbreviation ambiguous\n",args[0]);
2940 d_printf("%s: command not found\n",args[0]);
2948 /****************************************************************************
2949 process commands on stdin
2950 ****************************************************************************/
2951 static int process_stdin(struct smbclient_context *ctx)
2955 /* display a prompt */
2956 char *the_prompt = talloc_asprintf(ctx, "smb: %s> ", ctx->remote_cur_dir);
2957 char *cline = smb_readline(the_prompt, readline_callback, completion_fn);
2958 talloc_free(the_prompt);
2962 /* special case - first char is ! */
2963 if (*cline == '!') {
2968 rc |= process_command_string(ctx, cline);
2975 /*****************************************************
2976 return a connection to a server
2977 *******************************************************/
2978 static struct smbclient_context *do_connect(TALLOC_CTX *mem_ctx,
2979 const char *specified_server, const char *specified_share, struct cli_credentials *cred)
2982 struct smbclient_context *ctx = talloc_zero(mem_ctx, struct smbclient_context);
2983 char *server, *share;
2989 rl_ctx = ctx; /* Ugly hack */
2991 if (strncmp(specified_share, "\\\\", 2) == 0 ||
2992 strncmp(specified_share, "//", 2) == 0) {
2993 smbcli_parse_unc(specified_share, ctx, &server, &share);
2995 share = talloc_strdup(ctx, specified_share);
2996 server = talloc_strdup(ctx, specified_server);
2999 ctx->remote_cur_dir = talloc_strdup(ctx, "\\");
3001 status = smbcli_full_connection(ctx, &ctx->cli, server,
3002 share, NULL, cred, NULL);
3003 if (!NT_STATUS_IS_OK(status)) {
3004 d_printf("Connection to \\\\%s\\%s failed - %s\n",
3005 server, share, nt_errstr(status));
3013 /****************************************************************************
3015 ****************************************************************************/
3016 static int do_host_query(const char *query_host)
3018 browse_host(query_host);
3019 list_servers(lp_workgroup());
3024 /****************************************************************************
3025 handle a message operation
3026 ****************************************************************************/
3027 static int do_message_op(const char *desthost, const char *destip, int name_type)
3029 struct nbt_name called, calling;
3030 const char *server_name;
3031 struct smbcli_state *cli;
3033 make_nbt_name_client(&calling, lp_netbios_name());
3035 nbt_choose_called_name(NULL, &called, desthost, name_type);
3037 server_name = destip ? destip : desthost;
3039 if (!(cli=smbcli_state_init(NULL)) || !smbcli_socket_connect(cli, server_name)) {
3040 d_printf("Connection to %s failed\n", server_name);
3044 if (!smbcli_transport_establish(cli, &calling, &called)) {
3045 d_printf("session request failed\n");
3050 send_message(cli, desthost);
3057 /****************************************************************************
3059 ****************************************************************************/
3060 int main(int argc,char *argv[])
3062 const char *base_directory = NULL;
3063 const char *dest_ip = NULL;
3065 const char *query_host = NULL;
3066 BOOL message = False;
3067 const char *desthost = NULL;
3069 const char *term_code = KANJI;
3071 const char *term_code = "";
3074 const char *service = NULL;
3078 int name_type = 0x20;
3079 TALLOC_CTX *mem_ctx;
3080 struct smbclient_context *ctx;
3081 const char *cmdstr = NULL;
3083 struct poptOption long_options[] = {
3086 { "message", 'M', POPT_ARG_STRING, NULL, 'M', "Send message", "HOST" },
3087 { "ip-address", 'I', POPT_ARG_STRING, NULL, 'I', "Use this IP to connect to", "IP" },
3088 { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
3089 { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
3090 { "terminal", 't', POPT_ARG_STRING, NULL, 't', "Terminal I/O code {sjis|euc|jis7|jis8|junet|hex}", "CODE" },
3091 { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
3092 { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" },
3093 { "send-buffer", 'b', POPT_ARG_INT, NULL, 'b', "Changes the transmit/send buffer", "BYTES" },
3094 { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
3096 POPT_COMMON_CONNECTION
3097 POPT_COMMON_CREDENTIALS
3102 mem_ctx = talloc_init("client.c/main");
3104 d_printf("\nclient.c: Not enough memory\n");
3108 pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
3109 poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
3111 while ((opt = poptGetNextOpt(pc)) != -1) {
3114 /* Messages are sent to NetBIOS name type 0x3
3115 * (Messenger Service). Make sure we default
3116 * to port 139 instead of port 445. srl,crh
3119 desthost = strdup(poptGetOptArg(pc));
3120 if( 0 == port ) port = 139;
3124 dest_ip = poptGetOptArg(pc);
3127 query_host = strdup(poptGetOptArg(pc));
3130 term_code = strdup(poptGetOptArg(pc));
3133 base_directory = strdup(poptGetOptArg(pc));
3136 io_bufsize = MAX(1, atoi(poptGetOptArg(pc)));
3143 if(poptPeekArg(pc)) {
3144 char *s = strdup(poptGetArg(pc));
3146 /* Convert any '/' characters in the service name to '\' characters */
3147 string_replace(s, '/','\\');
3151 if (count_chars(s,'\\') < 3) {
3152 d_printf("\n%s: Not enough '\\' characters in service\n",s);
3153 poptPrintUsage(pc, stderr, 0);
3158 if (poptPeekArg(pc)) {
3159 cli_credentials_set_password(cmdline_credentials, poptGetArg(pc), CRED_SPECIFIED);
3164 if (!query_host && !service && !message) {
3165 poptPrintUsage(pc, stderr, 0);
3169 poptFreeContext(pc);
3171 DEBUG( 3, ( "Client started (version %s).\n", SAMBA_VERSION_STRING ) );
3173 if (query_host && (p=strchr_m(query_host,'#'))) {
3176 sscanf(p, "%x", &name_type);
3180 return do_host_query(query_host);
3184 return do_message_op(desthost, dest_ip, name_type);
3188 ctx = do_connect(mem_ctx, desthost, service, cmdline_credentials);
3193 do_cd(ctx, base_directory);
3196 rc = process_command_string(ctx, cmdstr);
3198 rc = process_stdin(ctx);
3201 talloc_free(mem_ctx);