libsmbclient: Allow server (NetApp) to return STATUS_INVALID_PARAMETER from an echo.
[nivanova/samba-autobuild/.git] / source3 / client / client.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB client
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
9
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.
14
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.
19
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/>.
22 */
23
24 #include "includes.h"
25 #include "system/filesys.h"
26 #include "popt_common.h"
27 #include "rpc_client/cli_pipe.h"
28 #include "client/client_proto.h"
29 #include "client/clitar_proto.h"
30 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
31 #include "../lib/util/select.h"
32 #include "system/readline.h"
33 #include "../libcli/smbreadline/smbreadline.h"
34 #include "../libcli/security/security.h"
35 #include "system/select.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "include/ntioctl.h"
41 #include "../libcli/smb/smbXcli_base.h"
42
43 #ifndef REGISTER
44 #define REGISTER 0
45 #endif
46
47 extern int do_smb_browse(void); /* mDNS browsing */
48
49 extern bool override_logfile;
50
51 static int port = 0;
52 static char *service;
53 static char *desthost;
54 static bool grepable = false;
55 static char *cmdstr = NULL;
56 const char *cmd_ptr = NULL;
57
58 static int io_bufsize = 0; /* we use the default size */
59 static int io_timeout = (CLIENT_TIMEOUT/1000); /* Per operation timeout (in seconds). */
60
61 static int name_type = 0x20;
62 static int max_protocol = -1;
63
64 static int process_tok(char *tok);
65 static int cmd_help(void);
66
67 #define CREATE_ACCESS_READ READ_CONTROL_ACCESS
68
69 /* value for unused fid field in trans2 secondary request */
70 #define FID_UNUSED (0xFFFF)
71
72 time_t newer_than = 0;
73 static int archive_level = 0;
74
75 static bool translation = false;
76 static bool have_ip;
77
78 static bool prompt = true;
79
80 static bool recurse = false;
81 static bool showacls = false;
82 bool lowercase = false;
83 static bool backup_intent = false;
84
85 static struct sockaddr_storage dest_ss;
86 static char dest_ss_str[INET6_ADDRSTRLEN];
87
88 #define SEPARATORS " \t\n\r"
89
90 static bool abort_mget = true;
91
92 /* timing globals */
93 uint64_t get_total_size = 0;
94 unsigned int get_total_time_ms = 0;
95 static uint64_t put_total_size = 0;
96 static unsigned int put_total_time_ms = 0;
97
98 /* totals globals */
99 static double dir_total;
100
101 /* encrypted state. */
102 static bool smb_encrypt;
103
104 /* root cli_state connection */
105
106 struct cli_state *cli;
107
108 static char CLI_DIRSEP_CHAR = '\\';
109 static char CLI_DIRSEP_STR[] = { '\\', '\0' };
110
111 /* Accessor functions for directory paths. */
112 static char *fileselection;
113 static const char *client_get_fileselection(void)
114 {
115         if (fileselection) {
116                 return fileselection;
117         }
118         return "";
119 }
120
121 static const char *client_set_fileselection(const char *new_fs)
122 {
123         SAFE_FREE(fileselection);
124         if (new_fs) {
125                 fileselection = SMB_STRDUP(new_fs);
126         }
127         return client_get_fileselection();
128 }
129
130 static char *cwd;
131 static const char *client_get_cwd(void)
132 {
133         if (cwd) {
134                 return cwd;
135         }
136         return CLI_DIRSEP_STR;
137 }
138
139 static const char *client_set_cwd(const char *new_cwd)
140 {
141         SAFE_FREE(cwd);
142         if (new_cwd) {
143                 cwd = SMB_STRDUP(new_cwd);
144         }
145         return client_get_cwd();
146 }
147
148 static char *cur_dir;
149 const char *client_get_cur_dir(void)
150 {
151         if (cur_dir) {
152                 return cur_dir;
153         }
154         return CLI_DIRSEP_STR;
155 }
156
157 const char *client_set_cur_dir(const char *newdir)
158 {
159         SAFE_FREE(cur_dir);
160         if (newdir) {
161                 cur_dir = SMB_STRDUP(newdir);
162         }
163         return client_get_cur_dir();
164 }
165
166 /****************************************************************************
167  Put up a yes/no prompt.
168 ****************************************************************************/
169
170 static bool yesno(const char *p)
171 {
172         char ans[20];
173         printf("%s",p);
174
175         if (!fgets(ans,sizeof(ans)-1,stdin))
176                 return(False);
177
178         if (*ans == 'y' || *ans == 'Y')
179                 return(True);
180
181         return(False);
182 }
183
184 /****************************************************************************
185  Write to a local file with CR/LF->LF translation if appropriate. Return the
186  number taken from the buffer. This may not equal the number written.
187 ****************************************************************************/
188
189 static int writefile(int f, char *b, int n)
190 {
191         int i;
192
193         if (!translation) {
194                 return write(f,b,n);
195         }
196
197         i = 0;
198         while (i < n) {
199                 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
200                         b++;i++;
201                 }
202                 if (write(f, b, 1) != 1) {
203                         break;
204                 }
205                 b++;
206                 i++;
207         }
208
209         return(i);
210 }
211
212 /****************************************************************************
213  Read from a file with LF->CR/LF translation if appropriate. Return the
214  number read. read approx n bytes.
215 ****************************************************************************/
216
217 static int readfile(uint8_t *b, int n, FILE *f)
218 {
219         int i;
220         int c;
221
222         if (!translation)
223                 return fread(b,1,n,f);
224
225         i = 0;
226         while (i < (n - 1)) {
227                 if ((c = getc(f)) == EOF) {
228                         break;
229                 }
230
231                 if (c == '\n') { /* change all LFs to CR/LF */
232                         b[i++] = '\r';
233                 }
234
235                 b[i++] = c;
236         }
237
238         return(i);
239 }
240
241 struct push_state {
242         FILE *f;
243         off_t nread;
244 };
245
246 static size_t push_source(uint8_t *buf, size_t n, void *priv)
247 {
248         struct push_state *state = (struct push_state *)priv;
249         int result;
250
251         if (feof(state->f)) {
252                 return 0;
253         }
254
255         result = readfile(buf, n, state->f);
256         state->nread += result;
257         return result;
258 }
259
260 /****************************************************************************
261  Send a message.
262 ****************************************************************************/
263
264 static void send_message(const char *username)
265 {
266         char buf[1600];
267         NTSTATUS status;
268         int i;
269
270         d_printf("Type your message, ending it with a Control-D\n");
271
272         i = 0;
273         while (i<sizeof(buf)-2) {
274                 int c = fgetc(stdin);
275                 if (c == EOF) {
276                         break;
277                 }
278                 if (c == '\n') {
279                         buf[i++] = '\r';
280                 }
281                 buf[i++] = c;
282         }
283         buf[i] = '\0';
284
285         status = cli_message(cli, desthost, username, buf);
286         if (!NT_STATUS_IS_OK(status)) {
287                 d_fprintf(stderr, "cli_message returned %s\n",
288                           nt_errstr(status));
289         }
290 }
291
292 /****************************************************************************
293  Check the space on a device.
294 ****************************************************************************/
295
296 static int do_dskattr(void)
297 {
298         uint64_t total, bsize, avail;
299         struct cli_state *targetcli = NULL;
300         char *targetpath = NULL;
301         TALLOC_CTX *ctx = talloc_tos();
302         NTSTATUS status;
303
304         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(), cli,
305                                   client_get_cur_dir(), &targetcli,
306                                   &targetpath);
307         if (!NT_STATUS_IS_OK(status)) {
308                 d_printf("Error in dskattr: %s\n", nt_errstr(status));
309                 return 1;
310         }
311
312         status = cli_disk_size(targetcli, targetpath, &bsize, &total, &avail);
313         if (!NT_STATUS_IS_OK(status)) {
314                 d_printf("Error in dskattr: %s\n", nt_errstr(status));
315                 return 1;
316         }
317
318         d_printf("\n\t\t%" PRIu64
319                 " blocks of size %" PRIu64
320                 ". %" PRIu64 " blocks available\n",
321                 total, bsize, avail);
322
323         return 0;
324 }
325
326 /****************************************************************************
327  Show cd/pwd.
328 ****************************************************************************/
329
330 static int cmd_pwd(void)
331 {
332         d_printf("Current directory is %s",service);
333         d_printf("%s\n",client_get_cur_dir());
334         return 0;
335 }
336
337 /****************************************************************************
338  Ensure name has correct directory separators.
339 ****************************************************************************/
340
341 static void normalize_name(char *newdir)
342 {
343         if (!(cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
344                 string_replace(newdir,'/','\\');
345         }
346 }
347
348 /****************************************************************************
349  Local name cleanup before sending to server. SMB1 allows relative pathnames,
350  but SMB2 does not, so we need to resolve them locally.
351 ****************************************************************************/
352
353 char *client_clean_name(TALLOC_CTX *ctx, const char *name)
354 {
355         char *newname = NULL;
356         if (name == NULL) {
357                 return NULL;
358         }
359
360         /* First ensure any path separators are correct. */
361         newname = talloc_strdup(ctx, name);
362         if (newname == NULL) {
363                 return NULL;
364         }
365         normalize_name(newname);
366
367         /* Now remove any relative (..) path components. */
368         if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
369                 newname = unix_clean_name(ctx, newname);
370         } else {
371                 newname = clean_name(ctx, newname);
372         }
373         if (newname == NULL) {
374                 return NULL;
375         }
376         return newname;
377 }
378
379 /****************************************************************************
380  Change directory - inner section.
381 ****************************************************************************/
382
383 static int do_cd(const char *new_dir)
384 {
385         char *newdir = NULL;
386         char *saved_dir = NULL;
387         char *new_cd = NULL;
388         char *targetpath = NULL;
389         struct cli_state *targetcli = NULL;
390         SMB_STRUCT_STAT sbuf;
391         uint32_t attributes;
392         int ret = 1;
393         TALLOC_CTX *ctx = talloc_stackframe();
394         NTSTATUS status;
395
396         newdir = talloc_strdup(ctx, new_dir);
397         if (!newdir) {
398                 TALLOC_FREE(ctx);
399                 return 1;
400         }
401
402         normalize_name(newdir);
403
404         /* Save the current directory in case the new directory is invalid */
405
406         saved_dir = talloc_strdup(ctx, client_get_cur_dir());
407         if (!saved_dir) {
408                 TALLOC_FREE(ctx);
409                 return 1;
410         }
411
412         if (*newdir == CLI_DIRSEP_CHAR) {
413                 client_set_cur_dir(newdir);
414                 new_cd = newdir;
415         } else {
416                 new_cd = talloc_asprintf(ctx, "%s%s",
417                                 client_get_cur_dir(),
418                                 newdir);
419                 if (!new_cd) {
420                         goto out;
421                 }
422         }
423
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);
427                 if (!new_cd) {
428                         goto out;
429                 }
430         }
431         client_set_cur_dir(new_cd);
432
433         new_cd = client_clean_name(ctx, new_cd);
434         client_set_cur_dir(new_cd);
435
436         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
437                                 cli, new_cd, &targetcli, &targetpath);
438         if (!NT_STATUS_IS_OK(status)) {
439                 d_printf("cd %s: %s\n", new_cd, nt_errstr(status));
440                 client_set_cur_dir(saved_dir);
441                 goto out;
442         }
443
444         if (strequal(targetpath,CLI_DIRSEP_STR )) {
445                 TALLOC_FREE(ctx);
446                 return 0;
447         }
448
449         /* Use a trans2_qpathinfo to test directories for modern servers.
450            Except Win9x doesn't support the qpathinfo_basic() call..... */
451
452         if (smbXcli_conn_protocol(targetcli->conn) > PROTOCOL_LANMAN2 && !targetcli->win95) {
453
454                 status = cli_qpathinfo_basic(targetcli, targetpath, &sbuf,
455                                              &attributes);
456                 if (!NT_STATUS_IS_OK(status)) {
457                         d_printf("cd %s: %s\n", new_cd, nt_errstr(status));
458                         client_set_cur_dir(saved_dir);
459                         goto out;
460                 }
461
462                 if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
463                         d_printf("cd %s: not a directory\n", new_cd);
464                         client_set_cur_dir(saved_dir);
465                         goto out;
466                 }
467         } else {
468
469                 targetpath = talloc_asprintf(ctx,
470                                 "%s%s",
471                                 targetpath,
472                                 CLI_DIRSEP_STR );
473                 if (!targetpath) {
474                         client_set_cur_dir(saved_dir);
475                         goto out;
476                 }
477                 targetpath = client_clean_name(ctx, targetpath);
478                 if (!targetpath) {
479                         client_set_cur_dir(saved_dir);
480                         goto out;
481                 }
482
483                 status = cli_chkpath(targetcli, targetpath);
484                 if (!NT_STATUS_IS_OK(status)) {
485                         d_printf("cd %s: %s\n", new_cd, nt_errstr(status));
486                         client_set_cur_dir(saved_dir);
487                         goto out;
488                 }
489         }
490
491         ret = 0;
492
493 out:
494
495         TALLOC_FREE(ctx);
496         return ret;
497 }
498
499 /****************************************************************************
500  Change directory.
501 ****************************************************************************/
502
503 static int cmd_cd(void)
504 {
505         char *buf = NULL;
506         int rc = 0;
507
508         if (next_token_talloc(talloc_tos(), &cmd_ptr, &buf,NULL)) {
509                 rc = do_cd(buf);
510         } else {
511                 d_printf("Current directory is %s\n",client_get_cur_dir());
512         }
513
514         return rc;
515 }
516
517 /****************************************************************************
518  Change directory.
519 ****************************************************************************/
520
521 static int cmd_cd_oneup(void)
522 {
523         return do_cd("..");
524 }
525
526 /*******************************************************************
527  Decide if a file should be operated on.
528 ********************************************************************/
529
530 static bool do_this_one(struct file_info *finfo)
531 {
532         if (!finfo->name) {
533                 return false;
534         }
535
536         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
537                 return true;
538         }
539
540         if (*client_get_fileselection() &&
541             !mask_match(finfo->name,client_get_fileselection(),false)) {
542                 DEBUG(3,("mask_match %s failed\n", finfo->name));
543                 return false;
544         }
545
546         if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
547                 DEBUG(3,("newer_than %s failed\n", finfo->name));
548                 return false;
549         }
550
551         if ((archive_level==1 || archive_level==2) && !(finfo->mode & FILE_ATTRIBUTE_ARCHIVE)) {
552                 DEBUG(3,("archive %s failed\n", finfo->name));
553                 return false;
554         }
555
556         return true;
557 }
558
559 /****************************************************************************
560  Display info about a file.
561 ****************************************************************************/
562
563 static NTSTATUS display_finfo(struct cli_state *cli_state, struct file_info *finfo,
564                           const char *dir)
565 {
566         time_t t;
567         TALLOC_CTX *ctx = talloc_tos();
568         NTSTATUS status = NT_STATUS_OK;
569
570         if (!do_this_one(finfo)) {
571                 return NT_STATUS_OK;
572         }
573
574         t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
575         if (!showacls) {
576                 d_printf("  %-30s%7.7s %8.0f  %s",
577                          finfo->name,
578                          attrib_string(talloc_tos(), finfo->mode),
579                         (double)finfo->size,
580                         time_to_asc(t));
581                 dir_total += finfo->size;
582         } else {
583                 char *afname = NULL;
584                 uint16_t fnum;
585
586                 /* skip if this is . or .. */
587                 if ( strequal(finfo->name,"..") || strequal(finfo->name,".") )
588                         return NT_STATUS_OK;
589                 /* create absolute filename for cli_ntcreate() FIXME */
590                 afname = talloc_asprintf(ctx,
591                                         "%s%s%s",
592                                         dir,
593                                         CLI_DIRSEP_STR,
594                                         finfo->name);
595                 if (!afname) {
596                         return NT_STATUS_NO_MEMORY;
597                 }
598                 /* print file meta date header */
599                 d_printf( "FILENAME:%s\n", finfo->name);
600                 d_printf( "MODE:%s\n", attrib_string(talloc_tos(), finfo->mode));
601                 d_printf( "SIZE:%.0f\n", (double)finfo->size);
602                 d_printf( "MTIME:%s", time_to_asc(t));
603                 status = cli_ntcreate(cli_state, afname, 0,
604                                       CREATE_ACCESS_READ, 0,
605                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
606                                       FILE_OPEN, 0x0, 0x0, &fnum, NULL);
607                 if (!NT_STATUS_IS_OK(status)) {
608                         DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
609                                    afname, nt_errstr(status)));
610                 } else {
611                         struct security_descriptor *sd = NULL;
612                         status = cli_query_secdesc(cli_state, fnum,
613                                                    ctx, &sd);
614                         if (!NT_STATUS_IS_OK(status)) {
615                                 DEBUG( 0, ("display_finfo() failed to "
616                                            "get security descriptor: %s",
617                                            nt_errstr(status)));
618                         } else {
619                                 display_sec_desc(sd);
620                         }
621                         TALLOC_FREE(sd);
622                 }
623                 TALLOC_FREE(afname);
624         }
625         return status;
626 }
627
628 /****************************************************************************
629  Accumulate size of a file.
630 ****************************************************************************/
631
632 static NTSTATUS do_du(struct cli_state *cli_state, struct file_info *finfo,
633                   const char *dir)
634 {
635         if (do_this_one(finfo)) {
636                 dir_total += finfo->size;
637         }
638         return NT_STATUS_OK;
639 }
640
641 static bool do_list_recurse;
642 static bool do_list_dirs;
643 static char *do_list_queue = 0;
644 static long do_list_queue_size = 0;
645 static long do_list_queue_start = 0;
646 static long do_list_queue_end = 0;
647 static NTSTATUS (*do_list_fn)(struct cli_state *cli_state, struct file_info *,
648                           const char *dir);
649
650 /****************************************************************************
651  Functions for do_list_queue.
652 ****************************************************************************/
653
654 /*
655  * The do_list_queue is a NUL-separated list of strings stored in a
656  * char*.  Since this is a FIFO, we keep track of the beginning and
657  * ending locations of the data in the queue.  When we overflow, we
658  * double the size of the char*.  When the start of the data passes
659  * the midpoint, we move everything back.  This is logically more
660  * complex than a linked list, but easier from a memory management
661  * angle.  In any memory error condition, do_list_queue is reset.
662  * Functions check to ensure that do_list_queue is non-NULL before
663  * accessing it.
664  */
665
666 static void reset_do_list_queue(void)
667 {
668         SAFE_FREE(do_list_queue);
669         do_list_queue_size = 0;
670         do_list_queue_start = 0;
671         do_list_queue_end = 0;
672 }
673
674 static void init_do_list_queue(void)
675 {
676         reset_do_list_queue();
677         do_list_queue_size = 1024;
678         do_list_queue = (char *)SMB_MALLOC(do_list_queue_size);
679         if (do_list_queue == 0) {
680                 d_printf("malloc fail for size %d\n",
681                          (int)do_list_queue_size);
682                 reset_do_list_queue();
683         } else {
684                 memset(do_list_queue, 0, do_list_queue_size);
685         }
686 }
687
688 static void adjust_do_list_queue(void)
689 {
690         /*
691          * If the starting point of the queue is more than half way through,
692          * move everything toward the beginning.
693          */
694
695         if (do_list_queue == NULL) {
696                 DEBUG(4,("do_list_queue is empty\n"));
697                 do_list_queue_start = do_list_queue_end = 0;
698                 return;
699         }
700
701         if (do_list_queue_start == do_list_queue_end) {
702                 DEBUG(4,("do_list_queue is empty\n"));
703                 do_list_queue_start = do_list_queue_end = 0;
704                 *do_list_queue = '\0';
705         } else if (do_list_queue_start > (do_list_queue_size / 2)) {
706                 DEBUG(4,("sliding do_list_queue backward\n"));
707                 memmove(do_list_queue,
708                         do_list_queue + do_list_queue_start,
709                         do_list_queue_end - do_list_queue_start);
710                 do_list_queue_end -= do_list_queue_start;
711                 do_list_queue_start = 0;
712         }
713 }
714
715 static void add_to_do_list_queue(const char *entry)
716 {
717         long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
718         while (new_end > do_list_queue_size) {
719                 do_list_queue_size *= 2;
720                 DEBUG(4,("enlarging do_list_queue to %d\n",
721                          (int)do_list_queue_size));
722                 do_list_queue = (char *)SMB_REALLOC(do_list_queue, do_list_queue_size);
723                 if (! do_list_queue) {
724                         d_printf("failure enlarging do_list_queue to %d bytes\n",
725                                  (int)do_list_queue_size);
726                         reset_do_list_queue();
727                 } else {
728                         memset(do_list_queue + do_list_queue_size / 2,
729                                0, do_list_queue_size / 2);
730                 }
731         }
732         if (do_list_queue) {
733                 strlcpy_base(do_list_queue + do_list_queue_end,
734                                  entry, do_list_queue, do_list_queue_size);
735                 do_list_queue_end = new_end;
736                 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
737                          entry, (int)do_list_queue_start, (int)do_list_queue_end));
738         }
739 }
740
741 static char *do_list_queue_head(void)
742 {
743         return do_list_queue + do_list_queue_start;
744 }
745
746 static void remove_do_list_queue_head(void)
747 {
748         if (do_list_queue_end > do_list_queue_start) {
749                 do_list_queue_start += strlen(do_list_queue_head()) + 1;
750                 adjust_do_list_queue();
751                 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
752                          (int)do_list_queue_start, (int)do_list_queue_end));
753         }
754 }
755
756 static int do_list_queue_empty(void)
757 {
758         return (! (do_list_queue && *do_list_queue));
759 }
760
761 /****************************************************************************
762  A helper for do_list.
763 ****************************************************************************/
764
765 static NTSTATUS do_list_helper(const char *mntpoint, struct file_info *f,
766                            const char *mask, void *state)
767 {
768         struct cli_state *cli_state = (struct cli_state *)state;
769         TALLOC_CTX *ctx = talloc_tos();
770         char *dir = NULL;
771         char *dir_end = NULL;
772         NTSTATUS status = NT_STATUS_OK;
773
774         /* Work out the directory. */
775         dir = talloc_strdup(ctx, mask);
776         if (!dir) {
777                 return NT_STATUS_NO_MEMORY;
778         }
779         if ((dir_end = strrchr(dir, CLI_DIRSEP_CHAR)) != NULL) {
780                 *dir_end = '\0';
781         }
782
783         if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
784                 if (do_list_dirs && do_this_one(f)) {
785                         status = do_list_fn(cli_state, f, dir);
786                         if (!NT_STATUS_IS_OK(status)) {
787                                 return status;
788                         }
789                 }
790                 if (do_list_recurse &&
791                     f->name &&
792                     !strequal(f->name,".") &&
793                     !strequal(f->name,"..")) {
794                         char *mask2 = NULL;
795                         char *p = NULL;
796
797                         if (!f->name[0]) {
798                                 d_printf("Empty dir name returned. Possible server misconfiguration.\n");
799                                 TALLOC_FREE(dir);
800                                 return NT_STATUS_UNSUCCESSFUL;
801                         }
802
803                         mask2 = talloc_asprintf(ctx,
804                                         "%s%s",
805                                         mntpoint,
806                                         mask);
807                         if (!mask2) {
808                                 TALLOC_FREE(dir);
809                                 return NT_STATUS_NO_MEMORY;
810                         }
811                         p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
812                         if (p) {
813                                 p[1] = 0;
814                         } else {
815                                 mask2[0] = '\0';
816                         }
817                         mask2 = talloc_asprintf_append(mask2,
818                                         "%s%s*",
819                                         f->name,
820                                         CLI_DIRSEP_STR);
821                         if (!mask2) {
822                                 TALLOC_FREE(dir);
823                                 return NT_STATUS_NO_MEMORY;
824                         }
825                         add_to_do_list_queue(mask2);
826                         TALLOC_FREE(mask2);
827                 }
828                 TALLOC_FREE(dir);
829                 return NT_STATUS_OK;
830         }
831
832         if (do_this_one(f)) {
833                 status = do_list_fn(cli_state, f, dir);
834         }
835         TALLOC_FREE(dir);
836         return status;
837 }
838
839 /****************************************************************************
840  A wrapper around cli_list that adds recursion.
841 ****************************************************************************/
842
843 NTSTATUS do_list(const char *mask,
844                         uint16_t attribute,
845                         NTSTATUS (*fn)(struct cli_state *cli_state, struct file_info *,
846                                    const char *dir),
847                         bool rec,
848                         bool dirs)
849 {
850         static int in_do_list = 0;
851         TALLOC_CTX *ctx = talloc_tos();
852         struct cli_state *targetcli = NULL;
853         char *targetpath = NULL;
854         NTSTATUS ret_status = NT_STATUS_OK;
855         NTSTATUS status = NT_STATUS_OK;
856
857         if (in_do_list && rec) {
858                 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
859                 exit(1);
860         }
861
862         in_do_list = 1;
863
864         do_list_recurse = rec;
865         do_list_dirs = dirs;
866         do_list_fn = fn;
867
868         if (rec) {
869                 init_do_list_queue();
870                 add_to_do_list_queue(mask);
871
872                 while (!do_list_queue_empty()) {
873                         /*
874                          * Need to copy head so that it doesn't become
875                          * invalid inside the call to cli_list.  This
876                          * would happen if the list were expanded
877                          * during the call.
878                          * Fix from E. Jay Berkenbilt (ejb@ql.org)
879                          */
880                         char *head = talloc_strdup(ctx, do_list_queue_head());
881
882                         if (!head) {
883                                 return NT_STATUS_NO_MEMORY;
884                         }
885
886                         /* check for dfs */
887
888                         status = cli_resolve_path(ctx, "",
889                                         popt_get_cmdline_auth_info(),
890                                         cli, head, &targetcli, &targetpath);
891                         if (!NT_STATUS_IS_OK(status)) {
892                                 d_printf("do_list: [%s] %s\n", head,
893                                          nt_errstr(status));
894                                 remove_do_list_queue_head();
895                                 continue;
896                         }
897
898                         status = cli_list(targetcli, targetpath, attribute,
899                                  do_list_helper, targetcli);
900                         if (!NT_STATUS_IS_OK(status)) {
901                                 d_printf("%s listing %s\n",
902                                          nt_errstr(status), targetpath);
903                                 ret_status = status;
904                         }
905                         remove_do_list_queue_head();
906                         if ((! do_list_queue_empty()) && (fn == display_finfo)) {
907                                 char *next_file = do_list_queue_head();
908                                 char *save_ch = 0;
909                                 if ((strlen(next_file) >= 2) &&
910                                     (next_file[strlen(next_file) - 1] == '*') &&
911                                     (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
912                                         save_ch = next_file +
913                                                 strlen(next_file) - 2;
914                                         *save_ch = '\0';
915                                         if (showacls) {
916                                                 /* cwd is only used if showacls is on */
917                                                 client_set_cwd(next_file);
918                                         }
919                                 }
920                                 if (!showacls) /* don't disturbe the showacls output */
921                                         d_printf("\n%s\n",next_file);
922                                 if (save_ch) {
923                                         *save_ch = CLI_DIRSEP_CHAR;
924                                 }
925                         }
926                         TALLOC_FREE(head);
927                         TALLOC_FREE(targetpath);
928                 }
929         } else {
930                 /* check for dfs */
931                 status = cli_resolve_path(ctx, "",
932                                 popt_get_cmdline_auth_info(), cli, mask,
933                                   &targetcli, &targetpath);
934                 if (NT_STATUS_IS_OK(status)) {
935                         status = cli_list(targetcli, targetpath, attribute,
936                                           do_list_helper, targetcli);
937                         if (!NT_STATUS_IS_OK(status)) {
938                                 d_printf("%s listing %s\n",
939                                          nt_errstr(status), targetpath);
940                                 ret_status = status;
941                         }
942                         TALLOC_FREE(targetpath);
943                 } else {
944                         d_printf("do_list: [%s] %s\n", mask, nt_errstr(status));
945                         ret_status = status;
946                 }
947         }
948
949         in_do_list = 0;
950         reset_do_list_queue();
951         return ret_status;
952 }
953
954 /****************************************************************************
955  Get a directory listing.
956 ****************************************************************************/
957
958 static int cmd_dir(void)
959 {
960         TALLOC_CTX *ctx = talloc_tos();
961         uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
962         char *mask = NULL;
963         char *buf = NULL;
964         int rc = 1;
965         NTSTATUS status;
966
967         dir_total = 0;
968         mask = talloc_strdup(ctx, client_get_cur_dir());
969         if (!mask) {
970                 return 1;
971         }
972
973         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
974                 normalize_name(buf);
975                 if (*buf == CLI_DIRSEP_CHAR) {
976                         mask = talloc_strdup(ctx, buf);
977                 } else {
978                         mask = talloc_asprintf_append(mask, "%s", buf);
979                 }
980         } else {
981                 mask = talloc_asprintf_append(mask, "*");
982         }
983         if (!mask) {
984                 return 1;
985         }
986
987         mask = client_clean_name(ctx, mask);
988         if (mask == NULL) {
989                 return 1;
990         }
991
992         if (showacls) {
993                 /* cwd is only used if showacls is on */
994                 client_set_cwd(client_get_cur_dir());
995         }
996
997         status = do_list(mask, attribute, display_finfo, recurse, true);
998         if (!NT_STATUS_IS_OK(status)) {
999                 return 1;
1000         }
1001
1002         rc = do_dskattr();
1003
1004         DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
1005
1006         return rc;
1007 }
1008
1009 /****************************************************************************
1010  Get a directory listing.
1011 ****************************************************************************/
1012
1013 static int cmd_du(void)
1014 {
1015         TALLOC_CTX *ctx = talloc_tos();
1016         uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
1017         char *mask = NULL;
1018         char *buf = NULL;
1019         NTSTATUS status;
1020         int rc = 1;
1021
1022         dir_total = 0;
1023         mask = talloc_strdup(ctx, client_get_cur_dir());
1024         if (!mask) {
1025                 return 1;
1026         }
1027         if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
1028                 mask = talloc_asprintf_append(mask, "%s", CLI_DIRSEP_STR);
1029                 if (!mask) {
1030                         return 1;
1031                 }
1032         }
1033
1034         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1035                 normalize_name(buf);
1036                 if (*buf == CLI_DIRSEP_CHAR) {
1037                         mask = talloc_strdup(ctx, buf);
1038                 } else {
1039                         mask = talloc_asprintf_append(mask, "%s", buf);
1040                 }
1041         } else {
1042                 mask = talloc_strdup(ctx, "*");
1043         }
1044         if (!mask) {
1045                 return 1;
1046         }
1047
1048         mask = client_clean_name(ctx, mask);
1049         if (mask == NULL) {
1050                 return 1;
1051         }
1052
1053         status = do_list(mask, attribute, do_du, recurse, true);
1054         if (!NT_STATUS_IS_OK(status)) {
1055                 return 1;
1056         }
1057
1058         rc = do_dskattr();
1059
1060         d_printf("Total number of bytes: %.0f\n", dir_total);
1061
1062         return rc;
1063 }
1064
1065 static int cmd_echo(void)
1066 {
1067         TALLOC_CTX *ctx = talloc_tos();
1068         char *num;
1069         char *data;
1070         NTSTATUS status;
1071
1072         if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
1073             || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
1074                 d_printf("echo <num> <data>\n");
1075                 return 1;
1076         }
1077
1078         status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
1079
1080         if (!NT_STATUS_IS_OK(status)) {
1081                 d_printf("echo failed: %s\n", nt_errstr(status));
1082                 return 1;
1083         }
1084
1085         return 0;
1086 }
1087
1088 /****************************************************************************
1089  Get a file from rname to lname
1090 ****************************************************************************/
1091
1092 static NTSTATUS writefile_sink(char *buf, size_t n, void *priv)
1093 {
1094         int *pfd = (int *)priv;
1095         if (writefile(*pfd, buf, n) == -1) {
1096                 return map_nt_error_from_unix(errno);
1097         }
1098         return NT_STATUS_OK;
1099 }
1100
1101 static int do_get(const char *rname, const char *lname_in, bool reget)
1102 {
1103         TALLOC_CTX *ctx = talloc_tos();
1104         int handle = 0;
1105         uint16_t fnum;
1106         bool newhandle = false;
1107         struct timespec tp_start;
1108         uint16_t attr;
1109         off_t size;
1110         off_t start = 0;
1111         off_t nread = 0;
1112         int rc = 0;
1113         struct cli_state *targetcli = NULL;
1114         char *targetname = NULL;
1115         char *lname = NULL;
1116         NTSTATUS status;
1117
1118         lname = talloc_strdup(ctx, lname_in);
1119         if (!lname) {
1120                 return 1;
1121         }
1122
1123         if (lowercase) {
1124                 if (!strlower_m(lname)) {
1125                         d_printf("strlower_m %s failed\n", lname);
1126                         return 1;
1127                 }
1128         }
1129
1130         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
1131                                 cli, rname, &targetcli, &targetname);
1132         if (!NT_STATUS_IS_OK(status)) {
1133                 d_printf("Failed to open %s: %s\n", rname, nt_errstr(status));
1134                 return 1;
1135         }
1136
1137         clock_gettime_mono(&tp_start);
1138
1139         status = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE, &fnum);
1140         if (!NT_STATUS_IS_OK(status)) {
1141                 d_printf("%s opening remote file %s\n", nt_errstr(status),
1142                          rname);
1143                 return 1;
1144         }
1145
1146         if(!strcmp(lname,"-")) {
1147                 handle = fileno(stdout);
1148         } else {
1149                 if (reget) {
1150                         handle = open(lname, O_WRONLY|O_CREAT, 0644);
1151                         if (handle >= 0) {
1152                                 start = lseek(handle, 0, SEEK_END);
1153                                 if (start == -1) {
1154                                         d_printf("Error seeking local file\n");
1155                                         return 1;
1156                                 }
1157                         }
1158                 } else {
1159                         handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1160                 }
1161                 newhandle = true;
1162         }
1163         if (handle < 0) {
1164                 d_printf("Error opening local file %s\n",lname);
1165                 return 1;
1166         }
1167
1168
1169         status = cli_qfileinfo_basic(targetcli, fnum, &attr, &size, NULL, NULL,
1170                                      NULL, NULL, NULL);
1171         if (!NT_STATUS_IS_OK(status)) {
1172                 status = cli_getattrE(targetcli, fnum, &attr, &size, NULL, NULL,
1173                                       NULL);
1174                 if(!NT_STATUS_IS_OK(status)) {
1175                         d_printf("getattrib: %s\n", nt_errstr(status));
1176                         return 1;
1177                 }
1178         }
1179
1180         DEBUG(1,("getting file %s of size %.0f as %s ",
1181                  rname, (double)size, lname));
1182
1183         status = cli_pull(targetcli, fnum, start, size, io_bufsize,
1184                           writefile_sink, (void *)&handle, &nread);
1185         if (!NT_STATUS_IS_OK(status)) {
1186                 d_fprintf(stderr, "parallel_read returned %s\n",
1187                           nt_errstr(status));
1188                 cli_close(targetcli, fnum);
1189                 return 1;
1190         }
1191
1192         status = cli_close(targetcli, fnum);
1193         if (!NT_STATUS_IS_OK(status)) {
1194                 d_printf("Error %s closing remote file\n", nt_errstr(status));
1195                 rc = 1;
1196         }
1197
1198         if (newhandle) {
1199                 close(handle);
1200         }
1201
1202         if (archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
1203                 cli_setatr(cli, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0);
1204         }
1205
1206         {
1207                 struct timespec tp_end;
1208                 int this_time;
1209
1210                 clock_gettime_mono(&tp_end);
1211                 this_time = nsec_time_diff(&tp_end,&tp_start)/1000000;
1212                 get_total_time_ms += this_time;
1213                 get_total_size += nread;
1214
1215                 DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
1216                          nread / (1.024*this_time + 1.0e-4),
1217                          get_total_size / (1.024*get_total_time_ms)));
1218         }
1219
1220         TALLOC_FREE(targetname);
1221         return rc;
1222 }
1223
1224 /****************************************************************************
1225  Get a file.
1226 ****************************************************************************/
1227
1228 static int cmd_get(void)
1229 {
1230         TALLOC_CTX *ctx = talloc_tos();
1231         char *lname = NULL;
1232         char *rname = NULL;
1233         char *fname = NULL;
1234
1235         rname = talloc_strdup(ctx, client_get_cur_dir());
1236         if (!rname) {
1237                 return 1;
1238         }
1239
1240         if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
1241                 d_printf("get <filename> [localname]\n");
1242                 return 1;
1243         }
1244         rname = talloc_asprintf_append(rname, "%s", fname);
1245         if (!rname) {
1246                 return 1;
1247         }
1248         rname = client_clean_name(ctx, rname);
1249         if (!rname) {
1250                 return 1;
1251         }
1252
1253         next_token_talloc(ctx, &cmd_ptr,&lname,NULL);
1254         if (!lname) {
1255                 lname = fname;
1256         }
1257
1258         return do_get(rname, lname, false);
1259 }
1260
1261 /****************************************************************************
1262  Do an mget operation on one file.
1263 ****************************************************************************/
1264
1265 static NTSTATUS do_mget(struct cli_state *cli_state, struct file_info *finfo,
1266                     const char *dir)
1267 {
1268         TALLOC_CTX *ctx = talloc_tos();
1269         NTSTATUS status = NT_STATUS_OK;
1270         char *rname = NULL;
1271         char *quest = NULL;
1272         char *saved_curdir = NULL;
1273         char *mget_mask = NULL;
1274         char *new_cd = NULL;
1275
1276         if (!finfo->name) {
1277                 return NT_STATUS_OK;
1278         }
1279
1280         if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1281                 return NT_STATUS_OK;
1282
1283         if (abort_mget) {
1284                 d_printf("mget aborted\n");
1285                 return NT_STATUS_UNSUCCESSFUL;
1286         }
1287
1288         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
1289                 if (asprintf(&quest,
1290                          "Get directory %s? ",finfo->name) < 0) {
1291                         return NT_STATUS_NO_MEMORY;
1292                 }
1293         } else {
1294                 if (asprintf(&quest,
1295                          "Get file %s? ",finfo->name) < 0) {
1296                         return NT_STATUS_NO_MEMORY;
1297                 }
1298         }
1299
1300         if (prompt && !yesno(quest)) {
1301                 SAFE_FREE(quest);
1302                 return NT_STATUS_OK;
1303         }
1304         SAFE_FREE(quest);
1305
1306         if (!(finfo->mode & FILE_ATTRIBUTE_DIRECTORY)) {
1307                 rname = talloc_asprintf(ctx,
1308                                 "%s%s",
1309                                 client_get_cur_dir(),
1310                                 finfo->name);
1311                 if (!rname) {
1312                         return NT_STATUS_NO_MEMORY;
1313                 }
1314                 rname = client_clean_name(ctx, rname);
1315                 if (rname == NULL) {
1316                         return NT_STATUS_NO_MEMORY;
1317                 }
1318                 do_get(rname, finfo->name, false);
1319                 TALLOC_FREE(rname);
1320                 return NT_STATUS_OK;
1321         }
1322
1323         /* handle directories */
1324         saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
1325         if (!saved_curdir) {
1326                 return NT_STATUS_NO_MEMORY;
1327         }
1328
1329         new_cd = talloc_asprintf(ctx,
1330                                 "%s%s%s",
1331                                 client_get_cur_dir(),
1332                                 finfo->name,
1333                                 CLI_DIRSEP_STR);
1334         if (!new_cd) {
1335                 return NT_STATUS_NO_MEMORY;
1336         }
1337         new_cd = client_clean_name(ctx, new_cd);
1338         if (new_cd == NULL) {
1339                 return NT_STATUS_NO_MEMORY;
1340         }
1341         client_set_cur_dir(new_cd);
1342
1343         string_replace(finfo->name,'\\','/');
1344         if (lowercase) {
1345                 if (!strlower_m(finfo->name)) {
1346                         return NT_STATUS_INVALID_PARAMETER;
1347                 }
1348         }
1349
1350         if (!directory_exist(finfo->name) &&
1351             mkdir(finfo->name,0777) != 0) {
1352                 d_printf("failed to create directory %s\n",finfo->name);
1353                 client_set_cur_dir(saved_curdir);
1354                 return map_nt_error_from_unix(errno);
1355         }
1356
1357         if (chdir(finfo->name) != 0) {
1358                 d_printf("failed to chdir to directory %s\n",finfo->name);
1359                 client_set_cur_dir(saved_curdir);
1360                 return map_nt_error_from_unix(errno);
1361         }
1362
1363         mget_mask = talloc_asprintf(ctx,
1364                         "%s*",
1365                         client_get_cur_dir());
1366
1367         if (!mget_mask) {
1368                 return NT_STATUS_NO_MEMORY;
1369         }
1370
1371         mget_mask = client_clean_name(ctx, mget_mask);
1372         if (mget_mask == NULL) {
1373                 return NT_STATUS_NO_MEMORY;
1374         }
1375         status = do_list(mget_mask,
1376                          (FILE_ATTRIBUTE_SYSTEM
1377                           | FILE_ATTRIBUTE_HIDDEN
1378                           | FILE_ATTRIBUTE_DIRECTORY),
1379                          do_mget, false, true);
1380         if (!NT_STATUS_IS_OK(status)
1381          && !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1382                 /*
1383                  * Ignore access denied errors to ensure all permitted files are
1384                  * pulled down.
1385                  */
1386                 return status;
1387         }
1388
1389         if (chdir("..") == -1) {
1390                 d_printf("do_mget: failed to chdir to .. (error %s)\n",
1391                         strerror(errno) );
1392                 return map_nt_error_from_unix(errno);
1393         }
1394         client_set_cur_dir(saved_curdir);
1395         TALLOC_FREE(mget_mask);
1396         TALLOC_FREE(saved_curdir);
1397         TALLOC_FREE(new_cd);
1398         return NT_STATUS_OK;
1399 }
1400
1401 /****************************************************************************
1402  View the file using the pager.
1403 ****************************************************************************/
1404
1405 static int cmd_more(void)
1406 {
1407         TALLOC_CTX *ctx = talloc_tos();
1408         char *rname = NULL;
1409         char *fname = NULL;
1410         char *lname = NULL;
1411         char *pager_cmd = NULL;
1412         const char *pager;
1413         int fd;
1414         int rc = 0;
1415         mode_t mask;
1416
1417         rname = talloc_strdup(ctx, client_get_cur_dir());
1418         if (!rname) {
1419                 return 1;
1420         }
1421
1422         lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
1423         if (!lname) {
1424                 return 1;
1425         }
1426         mask = umask(S_IRWXO | S_IRWXG);
1427         fd = mkstemp(lname);
1428         umask(mask);
1429         if (fd == -1) {
1430                 d_printf("failed to create temporary file for more\n");
1431                 return 1;
1432         }
1433         close(fd);
1434
1435         if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
1436                 d_printf("more <filename>\n");
1437                 unlink(lname);
1438                 return 1;
1439         }
1440         rname = talloc_asprintf_append(rname, "%s", fname);
1441         if (!rname) {
1442                 return 1;
1443         }
1444         rname = client_clean_name(ctx,rname);
1445         if (!rname) {
1446                 return 1;
1447         }
1448
1449         rc = do_get(rname, lname, false);
1450
1451         pager=getenv("PAGER");
1452
1453         pager_cmd = talloc_asprintf(ctx,
1454                                 "%s %s",
1455                                 (pager? pager:PAGER),
1456                                 lname);
1457         if (!pager_cmd) {
1458                 return 1;
1459         }
1460         if (system(pager_cmd) == -1) {
1461                 d_printf("system command '%s' returned -1\n",
1462                         pager_cmd);
1463         }
1464         unlink(lname);
1465
1466         return rc;
1467 }
1468
1469 /****************************************************************************
1470  Do a mget command.
1471 ****************************************************************************/
1472
1473 static int cmd_mget(void)
1474 {
1475         TALLOC_CTX *ctx = talloc_tos();
1476         uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
1477         char *mget_mask = NULL;
1478         char *buf = NULL;
1479         NTSTATUS status = NT_STATUS_OK;
1480
1481         if (recurse) {
1482                 attribute |= FILE_ATTRIBUTE_DIRECTORY;
1483         }
1484
1485         abort_mget = false;
1486
1487         while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1488
1489                 mget_mask = talloc_strdup(ctx, client_get_cur_dir());
1490                 if (!mget_mask) {
1491                         return 1;
1492                 }
1493                 if (*buf == CLI_DIRSEP_CHAR) {
1494                         mget_mask = talloc_strdup(ctx, buf);
1495                 } else {
1496                         mget_mask = talloc_asprintf_append(mget_mask,
1497                                                         "%s", buf);
1498                 }
1499                 if (!mget_mask) {
1500                         return 1;
1501                 }
1502                 mget_mask = client_clean_name(ctx, mget_mask);
1503                 if (mget_mask == NULL) {
1504                         return 1;
1505                 }
1506                 status = do_list(mget_mask, attribute, do_mget, false, true);
1507                 if (!NT_STATUS_IS_OK(status)) {
1508                         return 1;
1509                 }
1510         }
1511
1512         if (mget_mask == NULL) {
1513                 d_printf("nothing to mget\n");
1514                 return 0;
1515         }
1516
1517         if (!*mget_mask) {
1518                 mget_mask = talloc_asprintf(ctx,
1519                                         "%s*",
1520                                         client_get_cur_dir());
1521                 if (!mget_mask) {
1522                         return 1;
1523                 }
1524                 mget_mask = client_clean_name(ctx, mget_mask);
1525                 if (mget_mask == NULL) {
1526                         return 1;
1527                 }
1528                 status = do_list(mget_mask, attribute, do_mget, false, true);
1529                 if (!NT_STATUS_IS_OK(status)) {
1530                         return 1;
1531                 }
1532         }
1533
1534         return 0;
1535 }
1536
1537 /****************************************************************************
1538  Make a directory of name "name".
1539 ****************************************************************************/
1540
1541 static bool do_mkdir(const char *name)
1542 {
1543         TALLOC_CTX *ctx = talloc_tos();
1544         struct cli_state *targetcli;
1545         char *targetname = NULL;
1546         NTSTATUS status;
1547
1548         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
1549                                 cli, name, &targetcli, &targetname);
1550         if (!NT_STATUS_IS_OK(status)) {
1551                 d_printf("mkdir %s: %s\n", name, nt_errstr(status));
1552                 return false;
1553         }
1554
1555         status = cli_mkdir(targetcli, targetname);
1556         if (!NT_STATUS_IS_OK(status)) {
1557                 d_printf("%s making remote directory %s\n",
1558                          nt_errstr(status),name);
1559                 return false;
1560         }
1561
1562         return true;
1563 }
1564
1565 /****************************************************************************
1566  Show 8.3 name of a file.
1567 ****************************************************************************/
1568
1569 static bool do_altname(const char *name)
1570 {
1571         fstring altname;
1572         NTSTATUS status;
1573
1574         status = cli_qpathinfo_alt_name(cli, name, altname);
1575         if (!NT_STATUS_IS_OK(status)) {
1576                 d_printf("%s getting alt name for %s\n",
1577                          nt_errstr(status),name);
1578                 return false;
1579         }
1580         d_printf("%s\n", altname);
1581
1582         return true;
1583 }
1584
1585 /****************************************************************************
1586  Exit client.
1587 ****************************************************************************/
1588
1589 static int cmd_quit(void)
1590 {
1591         cli_shutdown(cli);
1592         popt_free_cmdline_auth_info();
1593         exit(0);
1594         /* NOTREACHED */
1595         return 0;
1596 }
1597
1598 /****************************************************************************
1599  Make a directory.
1600 ****************************************************************************/
1601
1602 static int cmd_mkdir(void)
1603 {
1604         TALLOC_CTX *ctx = talloc_tos();
1605         char *mask = NULL;
1606         char *buf = NULL;
1607         NTSTATUS status;
1608
1609         mask = talloc_strdup(ctx, client_get_cur_dir());
1610         if (!mask) {
1611                 return 1;
1612         }
1613
1614         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1615                 if (!recurse) {
1616                         d_printf("mkdir <dirname>\n");
1617                 }
1618                 return 1;
1619         }
1620         mask = talloc_asprintf_append(mask, "%s", buf);
1621         if (!mask) {
1622                 return 1;
1623         }
1624         mask = client_clean_name(ctx, mask);
1625         if (mask == NULL) {
1626                 return 1;
1627         }
1628
1629         if (recurse) {
1630                 char *ddir = NULL;
1631                 char *ddir2 = NULL;
1632                 struct cli_state *targetcli;
1633                 char *targetname = NULL;
1634                 char *p = NULL;
1635                 char *saveptr;
1636
1637                 ddir2 = talloc_strdup(ctx, "");
1638                 if (!ddir2) {
1639                         return 1;
1640                 }
1641
1642                 status = cli_resolve_path(ctx, "",
1643                                 popt_get_cmdline_auth_info(), cli, mask,
1644                                 &targetcli, &targetname);
1645                 if (!NT_STATUS_IS_OK(status)) {
1646                         return 1;
1647                 }
1648
1649                 ddir = talloc_strdup(ctx, targetname);
1650                 if (!ddir) {
1651                         return 1;
1652                 }
1653                 trim_char(ddir,'.','\0');
1654                 p = strtok_r(ddir, "/\\", &saveptr);
1655                 while (p) {
1656                         ddir2 = talloc_asprintf_append(ddir2, "%s", p);
1657                         if (!ddir2) {
1658                                 return 1;
1659                         }
1660                         if (!NT_STATUS_IS_OK(cli_chkpath(targetcli, ddir2))) {
1661                                 do_mkdir(ddir2);
1662                         }
1663                         ddir2 = talloc_asprintf_append(ddir2, "%s", CLI_DIRSEP_STR);
1664                         if (!ddir2) {
1665                                 return 1;
1666                         }
1667                         p = strtok_r(NULL, "/\\", &saveptr);
1668                 }
1669         } else {
1670                 do_mkdir(mask);
1671         }
1672
1673         return 0;
1674 }
1675
1676 /****************************************************************************
1677  Show alt name.
1678 ****************************************************************************/
1679
1680 static int cmd_altname(void)
1681 {
1682         TALLOC_CTX *ctx = talloc_tos();
1683         char *name;
1684         char *buf;
1685
1686         name = talloc_strdup(ctx, client_get_cur_dir());
1687         if (!name) {
1688                 return 1;
1689         }
1690
1691         if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
1692                 d_printf("altname <file>\n");
1693                 return 1;
1694         }
1695         name = talloc_asprintf_append(name, "%s", buf);
1696         if (!name) {
1697                 return 1;
1698         }
1699         name = client_clean_name(ctx, name);
1700         if (name == NULL) {
1701                 return 1;
1702         }
1703         do_altname(name);
1704         return 0;
1705 }
1706
1707 static char *attr_str(TALLOC_CTX *mem_ctx, uint16_t mode)
1708 {
1709         char *attrs = talloc_zero_array(mem_ctx, char, 17);
1710         int i = 0;
1711
1712         if (!(mode & FILE_ATTRIBUTE_NORMAL)) {
1713                 if (mode & FILE_ATTRIBUTE_ENCRYPTED) {
1714                         attrs[i++] = 'E';
1715                 }
1716                 if (mode & FILE_ATTRIBUTE_NONINDEXED) {
1717                         attrs[i++] = 'N';
1718                 }
1719                 if (mode & FILE_ATTRIBUTE_OFFLINE) {
1720                         attrs[i++] = 'O';
1721                 }
1722                 if (mode & FILE_ATTRIBUTE_COMPRESSED) {
1723                         attrs[i++] = 'C';
1724                 }
1725                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1726                         attrs[i++] = 'r';
1727                 }
1728                 if (mode & FILE_ATTRIBUTE_SPARSE) {
1729                         attrs[i++] = 's';
1730                 }
1731                 if (mode & FILE_ATTRIBUTE_TEMPORARY) {
1732                         attrs[i++] = 'T';
1733                 }
1734                 if (mode & FILE_ATTRIBUTE_NORMAL) {
1735                         attrs[i++] = 'N';
1736                 }
1737                 if (mode & FILE_ATTRIBUTE_READONLY) {
1738                         attrs[i++] = 'R';
1739                 }
1740                 if (mode & FILE_ATTRIBUTE_HIDDEN) {
1741                         attrs[i++] = 'H';
1742                 }
1743                 if (mode & FILE_ATTRIBUTE_SYSTEM) {
1744                         attrs[i++] = 'S';
1745                 }
1746                 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1747                         attrs[i++] = 'D';
1748                 }
1749                 if (mode & FILE_ATTRIBUTE_ARCHIVE) {
1750                         attrs[i++] = 'A';
1751                 }
1752         }
1753         return attrs;
1754 }
1755
1756 /****************************************************************************
1757  Show all info we can get
1758 ****************************************************************************/
1759
1760 static int do_allinfo(const char *name)
1761 {
1762         fstring altname;
1763         struct timespec b_time, a_time, m_time, c_time;
1764         off_t size;
1765         uint16_t mode;
1766         NTTIME tmp;
1767         uint16_t fnum;
1768         unsigned int num_streams;
1769         struct stream_struct *streams;
1770         int num_snapshots;
1771         char **snapshots = NULL;
1772         unsigned int i;
1773         NTSTATUS status;
1774
1775         status = cli_qpathinfo_alt_name(cli, name, altname);
1776         if (!NT_STATUS_IS_OK(status)) {
1777                 d_printf("%s getting alt name for %s\n", nt_errstr(status),
1778                          name);
1779                 /*
1780                  * Ignore not supported or not implemented, it does not
1781                  * hurt if we can't list alternate names.
1782                  */
1783                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
1784                     NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1785                         altname[0] = '\0';
1786                 } else {
1787                         return false;
1788                 }
1789         }
1790         d_printf("altname: %s\n", altname);
1791
1792         status = cli_qpathinfo3(cli, name, &b_time, &a_time, &m_time, &c_time,
1793                                 &size, &mode, NULL);
1794         if (!NT_STATUS_IS_OK(status)) {
1795                 d_printf("%s getting pathinfo for %s\n", nt_errstr(status),
1796                          name);
1797                 return false;
1798         }
1799
1800         tmp = unix_timespec_to_nt_time(b_time);
1801         d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1802
1803         tmp = unix_timespec_to_nt_time(a_time);
1804         d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1805
1806         tmp = unix_timespec_to_nt_time(m_time);
1807         d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
1808
1809         tmp = unix_timespec_to_nt_time(c_time);
1810         d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1811
1812         d_printf("attributes: %s (%x)\n", attr_str(talloc_tos(), mode), mode);
1813
1814         status = cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
1815                                        &streams);
1816         if (!NT_STATUS_IS_OK(status)) {
1817                 d_printf("%s getting streams for %s\n", nt_errstr(status),
1818                          name);
1819                 return false;
1820         }
1821
1822         for (i=0; i<num_streams; i++) {
1823                 d_printf("stream: [%s], %lld bytes\n", streams[i].name,
1824                          (unsigned long long)streams[i].size);
1825         }
1826
1827         if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1828                 char *subst, *print;
1829                 uint32_t flags;
1830
1831                 status = cli_readlink(cli, name, talloc_tos(), &subst, &print,
1832                                       &flags);
1833                 if (!NT_STATUS_IS_OK(status)) {
1834                         d_fprintf(stderr, "cli_readlink returned %s\n",
1835                                   nt_errstr(status));
1836                 } else {
1837                         d_printf("symlink: subst=[%s], print=[%s], flags=%x\n",
1838                                  subst, print, flags);
1839                         TALLOC_FREE(subst);
1840                         TALLOC_FREE(print);
1841                 }
1842         }
1843
1844         status = cli_ntcreate(cli, name, 0,
1845                               SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE |
1846                               SEC_STD_SYNCHRONIZE, 0,
1847                               FILE_SHARE_READ|FILE_SHARE_WRITE
1848                               |FILE_SHARE_DELETE,
1849                               FILE_OPEN, 0x0, 0x0, &fnum, NULL);
1850         if (!NT_STATUS_IS_OK(status)) {
1851                 /*
1852                  * Ignore failure, it does not hurt if we can't list
1853                  * snapshots
1854                  */
1855                 return 0;
1856         }
1857         /*
1858          * In order to get shadow copy data over SMB1 we
1859          * must call twice, once with 'get_names = false'
1860          * to get the size, then again with 'get_names = true'
1861          * to get the data or a Windows server fails to return
1862          * valid info. Samba doesn't have this bug. JRA.
1863          */
1864
1865         status = cli_shadow_copy_data(talloc_tos(), cli, fnum,
1866                                       false, &snapshots, &num_snapshots);
1867         if (!NT_STATUS_IS_OK(status)) {
1868                 cli_close(cli, fnum);
1869                 return 0;
1870         }
1871         status = cli_shadow_copy_data(talloc_tos(), cli, fnum,
1872                                       true, &snapshots, &num_snapshots);
1873         if (!NT_STATUS_IS_OK(status)) {
1874                 cli_close(cli, fnum);
1875                 return 0;
1876         }
1877
1878         for (i=0; i<num_snapshots; i++) {
1879                 char *snap_name;
1880
1881                 d_printf("%s\n", snapshots[i]);
1882                 snap_name = talloc_asprintf(talloc_tos(), "%s%s",
1883                                             snapshots[i], name);
1884                 status = cli_qpathinfo3(cli, snap_name, &b_time, &a_time,
1885                                         &m_time, &c_time, &size,
1886                                         NULL, NULL);
1887                 if (!NT_STATUS_IS_OK(status)) {
1888                         d_fprintf(stderr, "pathinfo(%s) failed: %s\n",
1889                                   snap_name, nt_errstr(status));
1890                         TALLOC_FREE(snap_name);
1891                         continue;
1892                 }
1893                 tmp = unix_timespec_to_nt_time(b_time);
1894                 d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1895                 tmp = unix_timespec_to_nt_time(a_time);
1896                 d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1897                 tmp =unix_timespec_to_nt_time(m_time);
1898                 d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
1899                 tmp = unix_timespec_to_nt_time(c_time);
1900                 d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1901                 d_printf("size: %d\n", (int)size);
1902         }
1903
1904         TALLOC_FREE(snapshots);
1905         cli_close(cli, fnum);
1906
1907         return 0;
1908 }
1909
1910 /****************************************************************************
1911  Show all info we can get
1912 ****************************************************************************/
1913
1914 static int cmd_allinfo(void)
1915 {
1916         TALLOC_CTX *ctx = talloc_tos();
1917         char *name;
1918         char *buf;
1919
1920         name = talloc_strdup(ctx, client_get_cur_dir());
1921         if (!name) {
1922                 return 1;
1923         }
1924
1925         if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
1926                 d_printf("allinfo <file>\n");
1927                 return 1;
1928         }
1929         name = talloc_asprintf_append(name, "%s", buf);
1930         if (!name) {
1931                 return 1;
1932         }
1933         name = client_clean_name(ctx, name);
1934         if (name == NULL) {
1935                 return 1;
1936         }
1937         do_allinfo(name);
1938
1939         return 0;
1940 }
1941
1942 /****************************************************************************
1943  Put a single file.
1944 ****************************************************************************/
1945
1946 static int do_put(const char *rname, const char *lname, bool reput)
1947 {
1948         TALLOC_CTX *ctx = talloc_tos();
1949         uint16_t fnum;
1950         FILE *f;
1951         off_t start = 0;
1952         int rc = 0;
1953         struct timespec tp_start;
1954         struct cli_state *targetcli;
1955         char *targetname = NULL;
1956         struct push_state state;
1957         NTSTATUS status;
1958
1959         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
1960                                 cli, rname, &targetcli, &targetname);
1961         if (!NT_STATUS_IS_OK(status)) {
1962                 d_printf("Failed to open %s: %s\n", rname, nt_errstr(status));
1963                 return 1;
1964         }
1965
1966         clock_gettime_mono(&tp_start);
1967
1968         if (reput) {
1969                 status = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
1970                 if (NT_STATUS_IS_OK(status)) {
1971                         if (!NT_STATUS_IS_OK(status = cli_qfileinfo_basic(
1972                                                      targetcli, fnum, NULL,
1973                                                      &start, NULL, NULL,
1974                                                      NULL, NULL, NULL)) &&
1975                             !NT_STATUS_IS_OK(status = cli_getattrE(
1976                                                      targetcli, fnum, NULL,
1977                                                      &start, NULL, NULL,
1978                                                      NULL))) {
1979                                 d_printf("getattrib: %s\n", nt_errstr(status));
1980                                 return 1;
1981                         }
1982                 }
1983         } else {
1984                 status = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
1985         }
1986
1987         if (!NT_STATUS_IS_OK(status)) {
1988                 d_printf("%s opening remote file %s\n", nt_errstr(status),
1989                          rname);
1990                 return 1;
1991         }
1992
1993         /* allow files to be piped into smbclient
1994            jdblair 24.jun.98
1995
1996            Note that in this case this function will exit(0) rather
1997            than returning. */
1998         if (!strcmp(lname, "-")) {
1999                 f = stdin;
2000                 /* size of file is not known */
2001         } else {
2002                 f = fopen(lname, "r");
2003                 if (f && reput) {
2004                         if (fseek(f, start, SEEK_SET) == -1) {
2005                                 d_printf("Error seeking local file\n");
2006                                 fclose(f);
2007                                 return 1;
2008                         }
2009                 }
2010         }
2011
2012         if (!f) {
2013                 d_printf("Error opening local file %s\n",lname);
2014                 return 1;
2015         }
2016
2017         DEBUG(1,("putting file %s as %s ",lname,
2018                  rname));
2019
2020         setvbuf(f, NULL, _IOFBF, io_bufsize);
2021
2022         state.f = f;
2023         state.nread = 0;
2024
2025         status = cli_push(targetcli, fnum, 0, 0, io_bufsize, push_source,
2026                           &state);
2027         if (!NT_STATUS_IS_OK(status)) {
2028                 d_fprintf(stderr, "cli_push returned %s\n", nt_errstr(status));
2029                 rc = 1;
2030         }
2031
2032         status = cli_close(targetcli, fnum);
2033         if (!NT_STATUS_IS_OK(status)) {
2034                 d_printf("%s closing remote file %s\n", nt_errstr(status),
2035                          rname);
2036                 if (f != stdin) {
2037                         fclose(f);
2038                 }
2039                 return 1;
2040         }
2041
2042         if (f != stdin) {
2043                 fclose(f);
2044         }
2045
2046         {
2047                 struct timespec tp_end;
2048                 int this_time;
2049
2050                 clock_gettime_mono(&tp_end);
2051                 this_time = nsec_time_diff(&tp_end,&tp_start)/1000000;
2052                 put_total_time_ms += this_time;
2053                 put_total_size += state.nread;
2054
2055                 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
2056                          state.nread / (1.024*this_time + 1.0e-4),
2057                          put_total_size / (1.024*put_total_time_ms)));
2058         }
2059
2060         if (f == stdin) {
2061                 cli_shutdown(cli);
2062                 popt_free_cmdline_auth_info();
2063                 exit(rc);
2064         }
2065
2066         return rc;
2067 }
2068
2069 /****************************************************************************
2070  Put a file.
2071 ****************************************************************************/
2072
2073 static int cmd_put(void)
2074 {
2075         TALLOC_CTX *ctx = talloc_tos();
2076         char *lname;
2077         char *rname;
2078         char *buf;
2079
2080         rname = talloc_strdup(ctx, client_get_cur_dir());
2081         if (!rname) {
2082                 return 1;
2083         }
2084
2085         if (!next_token_talloc(ctx, &cmd_ptr,&lname,NULL)) {
2086                 d_printf("put <filename>\n");
2087                 return 1;
2088         }
2089
2090         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2091                 rname = talloc_asprintf_append(rname, "%s", buf);
2092         } else {
2093                 rname = talloc_asprintf_append(rname, "%s", lname);
2094         }
2095         if (!rname) {
2096                 return 1;
2097         }
2098
2099         rname = client_clean_name(ctx, rname);
2100         if (!rname) {
2101                 return 1;
2102         }
2103
2104         {
2105                 SMB_STRUCT_STAT st;
2106                 /* allow '-' to represent stdin
2107                    jdblair, 24.jun.98 */
2108                 if (!file_exist_stat(lname, &st, false) &&
2109                     (strcmp(lname,"-"))) {
2110                         d_printf("%s does not exist\n",lname);
2111                         return 1;
2112                 }
2113         }
2114
2115         return do_put(rname, lname, false);
2116 }
2117
2118 /*************************************
2119  File list structure.
2120 *************************************/
2121
2122 static struct file_list {
2123         struct file_list *prev, *next;
2124         char *file_path;
2125         bool isdir;
2126 } *file_list;
2127
2128 /****************************************************************************
2129  Free a file_list structure.
2130 ****************************************************************************/
2131
2132 static void free_file_list (struct file_list *l_head)
2133 {
2134         struct file_list *list, *next;
2135
2136         for (list = l_head; list; list = next) {
2137                 next = list->next;
2138                 DLIST_REMOVE(l_head, list);
2139                 TALLOC_FREE(list);
2140         }
2141 }
2142
2143 /****************************************************************************
2144  Seek in a directory/file list until you get something that doesn't start with
2145  the specified name.
2146 ****************************************************************************/
2147
2148 static bool seek_list(struct file_list *list, char *name)
2149 {
2150         while (list) {
2151                 trim_string(list->file_path,"./","\n");
2152                 if (strncmp(list->file_path, name, strlen(name)) != 0) {
2153                         return true;
2154                 }
2155                 list = list->next;
2156         }
2157
2158         return false;
2159 }
2160
2161 /****************************************************************************
2162  Set the file selection mask.
2163 ****************************************************************************/
2164
2165 static int cmd_select(void)
2166 {
2167         TALLOC_CTX *ctx = talloc_tos();
2168         char *new_fs = NULL;
2169         next_token_talloc(ctx, &cmd_ptr,&new_fs,NULL)
2170                 ;
2171         if (new_fs) {
2172                 client_set_fileselection(new_fs);
2173         } else {
2174                 client_set_fileselection("");
2175         }
2176         return 0;
2177 }
2178
2179 /****************************************************************************
2180   Recursive file matching function act as find
2181   match must be always set to true when calling this function
2182 ****************************************************************************/
2183
2184 static int file_find(TALLOC_CTX *ctx,
2185                         struct file_list **list,
2186                         const char *directory,
2187                         const char *expression,
2188                         bool match)
2189 {
2190         DIR *dir;
2191         struct file_list *entry;
2192         struct stat statbuf;
2193         int ret;
2194         char *path;
2195         bool isdir;
2196         const char *dname;
2197
2198         dir = opendir(directory);
2199         if (!dir)
2200                 return -1;
2201
2202         while ((dname = readdirname(dir))) {
2203                 if (!strcmp("..", dname))
2204                         continue;
2205                 if (!strcmp(".", dname))
2206                         continue;
2207
2208                 path = talloc_asprintf(ctx, "%s/%s", directory, dname);
2209                 if (path == NULL) {
2210                         continue;
2211                 }
2212
2213                 isdir = false;
2214                 if (!match || !gen_fnmatch(expression, dname)) {
2215                         if (recurse) {
2216                                 ret = stat(path, &statbuf);
2217                                 if (ret == 0) {
2218                                         if (S_ISDIR(statbuf.st_mode)) {
2219                                                 isdir = true;
2220                                                 ret = file_find(ctx,
2221                                                                 list,
2222                                                                 path,
2223                                                                 expression,
2224                                                                 false);
2225                                         }
2226                                 } else {
2227                                         d_printf("file_find: cannot stat file %s\n", path);
2228                                 }
2229
2230                                 if (ret == -1) {
2231                                         TALLOC_FREE(path);
2232                                         closedir(dir);
2233                                         return -1;
2234                                 }
2235                         }
2236                         entry = talloc_zero(ctx, struct file_list);
2237                         if (!entry) {
2238                                 d_printf("Out of memory in file_find\n");
2239                                 closedir(dir);
2240                                 return -1;
2241                         }
2242                         entry->file_path = talloc_move(entry, &path);
2243                         entry->isdir = isdir;
2244                         DLIST_ADD(*list, entry);
2245                 } else {
2246                         TALLOC_FREE(path);
2247                 }
2248         }
2249
2250         closedir(dir);
2251         return 0;
2252 }
2253
2254 /****************************************************************************
2255  mput some files.
2256 ****************************************************************************/
2257
2258 static int cmd_mput(void)
2259 {
2260         TALLOC_CTX *ctx = talloc_tos();
2261         char *p = NULL;
2262
2263         while (next_token_talloc(ctx, &cmd_ptr,&p,NULL)) {
2264                 int ret;
2265                 struct file_list *temp_list;
2266                 char *quest, *lname, *rname;
2267
2268                 file_list = NULL;
2269
2270                 ret = file_find(ctx, &file_list, ".", p, true);
2271                 if (ret) {
2272                         free_file_list(file_list);
2273                         continue;
2274                 }
2275
2276                 quest = NULL;
2277                 lname = NULL;
2278                 rname = NULL;
2279
2280                 for (temp_list = file_list; temp_list;
2281                      temp_list = temp_list->next) {
2282
2283                         SAFE_FREE(lname);
2284                         if (asprintf(&lname, "%s/", temp_list->file_path) <= 0) {
2285                                 continue;
2286                         }
2287                         trim_string(lname, "./", "/");
2288
2289                         /* check if it's a directory */
2290                         if (temp_list->isdir) {
2291                                 /* if (!recurse) continue; */
2292
2293                                 SAFE_FREE(quest);
2294                                 if (asprintf(&quest, "Put directory %s? ", lname) < 0) {
2295                                         break;
2296                                 }
2297                                 if (prompt && !yesno(quest)) { /* No */
2298                                         /* Skip the directory */
2299                                         lname[strlen(lname)-1] = '/';
2300                                         if (!seek_list(temp_list, lname))
2301                                                 break;
2302                                 } else { /* Yes */
2303                                         SAFE_FREE(rname);
2304                                         if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
2305                                                 break;
2306                                         }
2307                                         normalize_name(rname);
2308                                         {
2309                                                 char *tmp_rname =
2310                                                         client_clean_name(ctx, rname);
2311                                                 if (tmp_rname == NULL) {
2312                                                         break;
2313                                                 }
2314                                                 SAFE_FREE(rname);
2315                                                 rname = smb_xstrdup(tmp_rname);
2316                                                 TALLOC_FREE(tmp_rname);
2317                                                 if (rname == NULL) {
2318                                                         break;
2319                                                 }
2320                                         }
2321                                         if (!NT_STATUS_IS_OK(cli_chkpath(cli, rname)) &&
2322                                             !do_mkdir(rname)) {
2323                                                 DEBUG (0, ("Unable to make dir, skipping..."));
2324                                                 /* Skip the directory */
2325                                                 lname[strlen(lname)-1] = '/';
2326                                                 if (!seek_list(temp_list, lname)) {
2327                                                         break;
2328                                                 }
2329                                         }
2330                                 }
2331                                 continue;
2332                         } else {
2333                                 SAFE_FREE(quest);
2334                                 if (asprintf(&quest,"Put file %s? ", lname) < 0) {
2335                                         break;
2336                                 }
2337                                 if (prompt && !yesno(quest)) {
2338                                         /* No */
2339                                         continue;
2340                                 }
2341
2342                                 /* Yes */
2343                                 SAFE_FREE(rname);
2344                                 if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
2345                                         break;
2346                                 }
2347                         }
2348
2349                         normalize_name(rname);
2350
2351                         {
2352                                 char *tmp_rname = client_clean_name(ctx, rname);
2353                                 if (tmp_rname == NULL) {
2354                                         break;
2355                                 }
2356                                 SAFE_FREE(rname);
2357                                 rname = smb_xstrdup(tmp_rname);
2358                                 TALLOC_FREE(tmp_rname);
2359                                 if (rname == NULL) {
2360                                         break;
2361                                 }
2362                         }
2363                         do_put(rname, lname, false);
2364                 }
2365                 free_file_list(file_list);
2366                 SAFE_FREE(quest);
2367                 SAFE_FREE(lname);
2368                 SAFE_FREE(rname);
2369         }
2370
2371         return 0;
2372 }
2373
2374 /****************************************************************************
2375  Cancel a print job.
2376 ****************************************************************************/
2377
2378 static int do_cancel(int job)
2379 {
2380         if (cli_printjob_del(cli, job)) {
2381                 d_printf("Job %d cancelled\n",job);
2382                 return 0;
2383         } else {
2384                 NTSTATUS status = cli_nt_error(cli);
2385                 d_printf("Error cancelling job %d : %s\n",
2386                          job, nt_errstr(status));
2387                 return 1;
2388         }
2389 }
2390
2391 /****************************************************************************
2392  Cancel a print job.
2393 ****************************************************************************/
2394
2395 static int cmd_cancel(void)
2396 {
2397         TALLOC_CTX *ctx = talloc_tos();
2398         char *buf = NULL;
2399         int job;
2400
2401         if (!next_token_talloc(ctx, &cmd_ptr, &buf,NULL)) {
2402                 d_printf("cancel <jobid> ...\n");
2403                 return 1;
2404         }
2405         do {
2406                 job = atoi(buf);
2407                 do_cancel(job);
2408         } while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL));
2409
2410         return 0;
2411 }
2412
2413 /****************************************************************************
2414  Print a file.
2415 ****************************************************************************/
2416
2417 static int cmd_print(void)
2418 {
2419         TALLOC_CTX *ctx = talloc_tos();
2420         char *lname = NULL;
2421         char *rname = NULL;
2422         char *p = NULL;
2423
2424         if (!next_token_talloc(ctx, &cmd_ptr, &lname,NULL)) {
2425                 d_printf("print <filename>\n");
2426                 return 1;
2427         }
2428
2429         rname = talloc_strdup(ctx, lname);
2430         if (!rname) {
2431                 return 1;
2432         }
2433         p = strrchr_m(rname,'/');
2434         if (p) {
2435                 rname = talloc_asprintf(ctx,
2436                                         "%s-%d",
2437                                         p+1,
2438                                         (int)getpid());
2439         }
2440         if (strequal(lname,"-")) {
2441                 rname = talloc_asprintf(ctx,
2442                                 "stdin-%d",
2443                                 (int)getpid());
2444         }
2445         if (!rname) {
2446                 return 1;
2447         }
2448
2449         return do_put(rname, lname, false);
2450 }
2451
2452 /****************************************************************************
2453  Show a print queue entry.
2454 ****************************************************************************/
2455
2456 static void queue_fn(struct print_job_info *p)
2457 {
2458         d_printf("%-6d   %-9d    %s\n", (int)p->id, (int)p->size, p->name);
2459 }
2460
2461 /****************************************************************************
2462  Show a print queue.
2463 ****************************************************************************/
2464
2465 static int cmd_queue(void)
2466 {
2467         cli_print_queue(cli, queue_fn);
2468         return 0;
2469 }
2470
2471 /****************************************************************************
2472  Delete some files.
2473 ****************************************************************************/
2474
2475 static NTSTATUS do_del(struct cli_state *cli_state, struct file_info *finfo,
2476                    const char *dir)
2477 {
2478         TALLOC_CTX *ctx = talloc_tos();
2479         char *mask = NULL;
2480         NTSTATUS status;
2481
2482         mask = talloc_asprintf(ctx,
2483                                 "%s%c%s",
2484                                 dir,
2485                                 CLI_DIRSEP_CHAR,
2486                                 finfo->name);
2487         if (!mask) {
2488                 return NT_STATUS_NO_MEMORY;
2489         }
2490
2491         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
2492                 TALLOC_FREE(mask);
2493                 return NT_STATUS_OK;
2494         }
2495
2496         status = cli_unlink(cli_state, mask, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2497         if (!NT_STATUS_IS_OK(status)) {
2498                 d_printf("%s deleting remote file %s\n",
2499                          nt_errstr(status), mask);
2500         }
2501         TALLOC_FREE(mask);
2502         return status;
2503 }
2504
2505 /****************************************************************************
2506  Delete some files.
2507 ****************************************************************************/
2508
2509 static int cmd_del(void)
2510 {
2511         TALLOC_CTX *ctx = talloc_tos();
2512         char *mask = NULL;
2513         char *buf = NULL;
2514         NTSTATUS status = NT_STATUS_OK;
2515         uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
2516
2517         if (recurse) {
2518                 attribute |= FILE_ATTRIBUTE_DIRECTORY;
2519         }
2520
2521         mask = talloc_strdup(ctx, client_get_cur_dir());
2522         if (!mask) {
2523                 return 1;
2524         }
2525         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2526                 d_printf("del <filename>\n");
2527                 return 1;
2528         }
2529         mask = talloc_asprintf_append(mask, "%s", buf);
2530         if (!mask) {
2531                 return 1;
2532         }
2533         mask = client_clean_name(ctx, mask);
2534         if (mask == NULL) {
2535                 return 1;
2536         }
2537
2538         status = do_list(mask,attribute,do_del,false,false);
2539         if (!NT_STATUS_IS_OK(status)) {
2540                 return 1;
2541         }
2542         return 0;
2543 }
2544
2545 /****************************************************************************
2546  Delete some files.
2547 ****************************************************************************/
2548
2549 static NTSTATUS delete_remote_files_list(struct cli_state *cli_state,
2550                                          struct file_list *flist)
2551 {
2552         NTSTATUS status = NT_STATUS_OK;
2553         struct file_list *deltree_list_iter = NULL;
2554
2555         for (deltree_list_iter = flist;
2556                         deltree_list_iter != NULL;
2557                         deltree_list_iter = deltree_list_iter->next) {
2558                 if (CLI_DIRSEP_CHAR == '/') {
2559                         /* POSIX. */
2560                         status = cli_posix_unlink(cli_state,
2561                                         deltree_list_iter->file_path);
2562                 } else if (deltree_list_iter->isdir) {
2563                         status = cli_rmdir(cli_state,
2564                                         deltree_list_iter->file_path);
2565                 } else {
2566                         status = cli_unlink(cli_state,
2567                                         deltree_list_iter->file_path,
2568                                         FILE_ATTRIBUTE_SYSTEM |
2569                                         FILE_ATTRIBUTE_HIDDEN);
2570                 }
2571                 if (!NT_STATUS_IS_OK(status)) {
2572                         d_printf("%s deleting remote %s %s\n",
2573                                 nt_errstr(status),
2574                                 deltree_list_iter->isdir ?
2575                                 "directory" : "file",
2576                                 deltree_list_iter->file_path);
2577                         return status;
2578                 }
2579         }
2580         return NT_STATUS_OK;
2581 }
2582
2583 /****************************************************************************
2584  Save a list of files to delete.
2585 ****************************************************************************/
2586
2587 static struct file_list *deltree_list_head;
2588
2589 static NTSTATUS do_deltree_list(struct cli_state *cli_state,
2590                                 struct file_info *finfo,
2591                                 const char *dir)
2592 {
2593         struct file_list **file_list_head_pp = &deltree_list_head;
2594         struct file_list *dt = NULL;
2595
2596         if (!do_this_one(finfo)) {
2597                 return NT_STATUS_OK;
2598         }
2599
2600         /* skip if this is . or .. */
2601         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
2602                 return NT_STATUS_OK;
2603         }
2604
2605         dt = talloc_zero(NULL, struct file_list);
2606         if (dt == NULL) {
2607                 return NT_STATUS_NO_MEMORY;
2608         }
2609
2610         /* create absolute filename for cli_ntcreate() */
2611         dt->file_path = talloc_asprintf(dt,
2612                                         "%s%s%s",
2613                                         dir,
2614                                         CLI_DIRSEP_STR,
2615                                         finfo->name);
2616         if (dt->file_path == NULL) {
2617                 TALLOC_FREE(dt);
2618                 return NT_STATUS_NO_MEMORY;
2619         }
2620
2621         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
2622                 dt->isdir = true;
2623         }
2624
2625         DLIST_ADD(*file_list_head_pp, dt);
2626         return NT_STATUS_OK;
2627 }
2628
2629 static int cmd_deltree(void)
2630 {
2631         TALLOC_CTX *ctx = talloc_tos();
2632         char *buf = NULL;
2633         NTSTATUS status = NT_STATUS_OK;
2634         struct file_list *deltree_list_norecurse = NULL;
2635         struct file_list *deltree_list_iter = NULL;
2636         uint16_t attribute = FILE_ATTRIBUTE_SYSTEM |
2637                              FILE_ATTRIBUTE_HIDDEN |
2638                              FILE_ATTRIBUTE_DIRECTORY;
2639         bool ok;
2640         char *mask = talloc_strdup(ctx, client_get_cur_dir());
2641         if (mask == NULL) {
2642                 return 1;
2643         }
2644         ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
2645         if (!ok) {
2646                 d_printf("deltree <filename>\n");
2647                 return 1;
2648         }
2649         mask = talloc_asprintf_append(mask, "%s", buf);
2650         if (mask == NULL) {
2651                 return 1;
2652         }
2653         mask = client_clean_name(ctx, mask);
2654         if (mask == NULL) {
2655                 return 1;
2656         }
2657
2658         deltree_list_head = NULL;
2659
2660         /*
2661          * Get the list of directories to
2662          * delete (in case mask has a wildcard).
2663          */
2664         status = do_list(mask, attribute, do_deltree_list, false, true);
2665         if (!NT_STATUS_IS_OK(status)) {
2666                 goto err;
2667         }
2668         deltree_list_norecurse = deltree_list_head;
2669         deltree_list_head = NULL;
2670
2671         for (deltree_list_iter = deltree_list_norecurse;
2672              deltree_list_iter != NULL;
2673              deltree_list_iter = deltree_list_iter->next) {
2674
2675                 if (deltree_list_iter->isdir == false) {
2676                         /* Just a regular file. */
2677                         if (CLI_DIRSEP_CHAR == '/') {
2678                                 /* POSIX. */
2679                                 status = cli_posix_unlink(cli,
2680                                         deltree_list_iter->file_path);
2681                         } else {
2682                                 status = cli_unlink(cli,
2683                                         deltree_list_iter->file_path,
2684                                         FILE_ATTRIBUTE_SYSTEM |
2685                                         FILE_ATTRIBUTE_HIDDEN);
2686                         }
2687                         if (!NT_STATUS_IS_OK(status)) {
2688                                 goto err;
2689                         }
2690                         continue;
2691                 }
2692
2693                 /*
2694                  * Get the list of files or directories to
2695                  * delete in depth order.
2696                  */
2697                 status = do_list(deltree_list_iter->file_path,
2698                                  attribute,
2699                                  do_deltree_list,
2700                                  true,
2701                                  true);
2702                 if (!NT_STATUS_IS_OK(status)) {
2703                         goto err;
2704                 }
2705                 status = delete_remote_files_list(cli, deltree_list_head);
2706                 free_file_list(deltree_list_head);
2707                 deltree_list_head = NULL;
2708                 if (!NT_STATUS_IS_OK(status)) {
2709                         goto err;
2710                 }
2711         }
2712
2713         free_file_list(deltree_list_norecurse);
2714         free_file_list(deltree_list_head);
2715         return 0;
2716
2717   err:
2718
2719         free_file_list(deltree_list_norecurse);
2720         free_file_list(deltree_list_head);
2721         deltree_list_head = NULL;
2722         return 1;
2723 }
2724
2725
2726 /****************************************************************************
2727  Wildcard delete some files.
2728 ****************************************************************************/
2729
2730 static int cmd_wdel(void)
2731 {
2732         TALLOC_CTX *ctx = talloc_tos();
2733         char *mask = NULL;
2734         char *buf = NULL;
2735         uint16_t attribute;
2736         struct cli_state *targetcli;
2737         char *targetname = NULL;
2738         NTSTATUS status;
2739
2740         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2741                 d_printf("wdel 0x<attrib> <wcard>\n");
2742                 return 1;
2743         }
2744
2745         attribute = (uint16_t)strtol(buf, (char **)NULL, 16);
2746
2747         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2748                 d_printf("wdel 0x<attrib> <wcard>\n");
2749                 return 1;
2750         }
2751
2752         mask = talloc_asprintf(ctx, "%s%s",
2753                         client_get_cur_dir(),
2754                         buf);
2755         if (!mask) {
2756                 return 1;
2757         }
2758         mask = client_clean_name(ctx, mask);
2759         if (mask == NULL) {
2760                 return 1;
2761         }
2762
2763         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
2764                                 cli, mask, &targetcli, &targetname);
2765         if (!NT_STATUS_IS_OK(status)) {
2766                 d_printf("cmd_wdel %s: %s\n", mask, nt_errstr(status));
2767                 return 1;
2768         }
2769
2770         status = cli_unlink(targetcli, targetname, attribute);
2771         if (!NT_STATUS_IS_OK(status)) {
2772                 d_printf("%s deleting remote files %s\n", nt_errstr(status),
2773                          targetname);
2774         }
2775         return 0;
2776 }
2777
2778 /****************************************************************************
2779 ****************************************************************************/
2780
2781 static int cmd_open(void)
2782 {
2783         TALLOC_CTX *ctx = talloc_tos();
2784         char *mask = NULL;
2785         char *buf = NULL;
2786         char *targetname = NULL;
2787         struct cli_state *targetcli;
2788         uint16_t fnum = (uint16_t)-1;
2789         NTSTATUS status;
2790
2791         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2792                 d_printf("open <filename>\n");
2793                 return 1;
2794         }
2795         mask = talloc_asprintf(ctx,
2796                         "%s%s",
2797                         client_get_cur_dir(),
2798                         buf);
2799         if (!mask) {
2800                 return 1;
2801         }
2802
2803         mask = client_clean_name(ctx, mask);
2804         if (mask == NULL) {
2805                 return 1;
2806         }
2807
2808         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
2809                         cli, mask, &targetcli, &targetname);
2810         if (!NT_STATUS_IS_OK(status)) {
2811                 d_printf("open %s: %s\n", mask, nt_errstr(status));
2812                 return 1;
2813         }
2814
2815         status = cli_ntcreate(targetcli, targetname, 0,
2816                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
2817                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
2818                         0x0, 0x0, &fnum, NULL);
2819         if (!NT_STATUS_IS_OK(status)) {
2820                 status = cli_ntcreate(targetcli, targetname, 0,
2821                                 FILE_READ_DATA, 0,
2822                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
2823                                 0x0, 0x0, &fnum, NULL);
2824                 if (NT_STATUS_IS_OK(status)) {
2825                         d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
2826                 } else {
2827                         d_printf("Failed to open file %s. %s\n",
2828                                  targetname, nt_errstr(status));
2829                 }
2830         } else {
2831                 d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
2832         }
2833         return 0;
2834 }
2835
2836 static int cmd_posix_encrypt(void)
2837 {
2838         TALLOC_CTX *ctx = talloc_tos();
2839         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2840         char *domain = NULL;
2841         char *user = NULL;
2842         char *password = NULL;
2843         struct cli_credentials *creds = NULL;
2844         struct cli_credentials *lcreds = NULL;
2845
2846         if (next_token_talloc(ctx, &cmd_ptr, &domain, NULL)) {
2847
2848                 if (!next_token_talloc(ctx, &cmd_ptr, &user, NULL)) {
2849                         d_printf("posix_encrypt domain user password\n");
2850                         return 1;
2851                 }
2852
2853                 if (!next_token_talloc(ctx, &cmd_ptr, &password, NULL)) {
2854                         d_printf("posix_encrypt domain user password\n");
2855                         return 1;
2856                 }
2857
2858                 lcreds = cli_session_creds_init(ctx,
2859                                                 user,
2860                                                 domain,
2861                                                 NULL, /* realm */
2862                                                 password,
2863                                                 false, /* use_kerberos */
2864                                                 false, /* fallback_after_kerberos */
2865                                                 false, /* use_ccache */
2866                                                 false); /* password_is_nt_hash */
2867                 if (lcreds == NULL) {
2868                         d_printf("cli_session_creds_init() failed.\n");
2869                         return -1;
2870                 }
2871                 creds = lcreds;
2872         } else {
2873                 bool auth_requested = false;
2874
2875                 creds = get_cmdline_auth_info_creds(
2876                                 popt_get_cmdline_auth_info());
2877
2878                 auth_requested = cli_credentials_authentication_requested(creds);
2879                 if (!auth_requested) {
2880                         d_printf("posix_encrypt domain user password\n");
2881                         return 1;
2882                 }
2883         }
2884
2885         status = cli_smb1_setup_encryption(cli, creds);
2886         /* gensec currently references the creds so we can't free them here */
2887         talloc_unlink(ctx, lcreds);
2888         if (!NT_STATUS_IS_OK(status)) {
2889                 d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
2890         } else {
2891                 d_printf("encryption on\n");
2892                 smb_encrypt = true;
2893         }
2894
2895         return 0;
2896 }
2897
2898 /****************************************************************************
2899 ****************************************************************************/
2900
2901 static int cmd_posix_open(void)
2902 {
2903         TALLOC_CTX *ctx = talloc_tos();
2904         char *mask = NULL;
2905         char *buf = NULL;
2906         char *targetname = NULL;
2907         struct cli_state *targetcli;
2908         mode_t mode;
2909         uint16_t fnum;
2910         NTSTATUS status;
2911
2912         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2913                 d_printf("posix_open <filename> 0<mode>\n");
2914                 return 1;
2915         }
2916         mask = talloc_asprintf(ctx,
2917                         "%s%s",
2918                         client_get_cur_dir(),
2919                         buf);
2920         if (!mask) {
2921                 return 1;
2922         }
2923         mask = client_clean_name(ctx, mask);
2924         if (mask == NULL) {
2925                 return 1;
2926         }
2927
2928         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2929                 d_printf("posix_open <filename> 0<mode>\n");
2930                 return 1;
2931         }
2932         mode = (mode_t)strtol(buf, (char **)NULL, 8);
2933
2934         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
2935                                 cli, mask, &targetcli, &targetname);
2936         if (!NT_STATUS_IS_OK(status)) {
2937                 d_printf("posix_open %s: %s\n", mask, nt_errstr(status));
2938                 return 1;
2939         }
2940
2941         status = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode,
2942                                 &fnum);
2943         if (!NT_STATUS_IS_OK(status)) {
2944                 status = cli_posix_open(targetcli, targetname,
2945                                         O_CREAT|O_RDONLY, mode, &fnum);
2946                 if (!NT_STATUS_IS_OK(status)) {
2947                         d_printf("Failed to open file %s. %s\n", targetname,
2948                                  nt_errstr(status));
2949                 } else {
2950                         d_printf("posix_open file %s: for readonly fnum %d\n",
2951                                  targetname, fnum);
2952                 }
2953         } else {
2954                 d_printf("posix_open file %s: for read/write fnum %d\n",
2955                          targetname, fnum);
2956         }
2957
2958         return 0;
2959 }
2960
2961 static int cmd_posix_mkdir(void)
2962 {
2963         TALLOC_CTX *ctx = talloc_tos();
2964         char *mask = NULL;
2965         char *buf = NULL;
2966         char *targetname = NULL;
2967         struct cli_state *targetcli;
2968         mode_t mode;
2969         NTSTATUS status;
2970
2971         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2972                 d_printf("posix_mkdir <filename> 0<mode>\n");
2973                 return 1;
2974         }
2975         mask = talloc_asprintf(ctx,
2976                         "%s%s",
2977                         client_get_cur_dir(),
2978                         buf);
2979         if (!mask) {
2980                 return 1;
2981         }
2982         mask = client_clean_name(ctx, mask);
2983         if (mask == NULL) {
2984                 return 1;
2985         }
2986
2987         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2988                 d_printf("posix_mkdir <filename> 0<mode>\n");
2989                 return 1;
2990         }
2991         mode = (mode_t)strtol(buf, (char **)NULL, 8);
2992
2993         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
2994                                 cli, mask, &targetcli, &targetname);
2995         if (!NT_STATUS_IS_OK(status)) {
2996                 d_printf("posix_mkdir %s: %s\n", mask, nt_errstr(status));
2997                 return 1;
2998         }
2999
3000         status = cli_posix_mkdir(targetcli, targetname, mode);
3001         if (!NT_STATUS_IS_OK(status)) {
3002                 d_printf("Failed to open file %s. %s\n",
3003                          targetname, nt_errstr(status));
3004         } else {
3005                 d_printf("posix_mkdir created directory %s\n", targetname);
3006         }
3007         return 0;
3008 }
3009
3010 static int cmd_posix_unlink(void)
3011 {
3012         TALLOC_CTX *ctx = talloc_tos();
3013         char *mask = NULL;
3014         char *buf = NULL;
3015         char *targetname = NULL;
3016         struct cli_state *targetcli;
3017         NTSTATUS status;
3018
3019         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3020                 d_printf("posix_unlink <filename>\n");
3021                 return 1;
3022         }
3023         mask = talloc_asprintf(ctx,
3024                         "%s%s",
3025                         client_get_cur_dir(),
3026                         buf);
3027         if (!mask) {
3028                 return 1;
3029         }
3030         mask = client_clean_name(ctx, mask);
3031         if (mask == NULL) {
3032                 return 1;
3033         }
3034
3035         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
3036                                 cli, mask, &targetcli, &targetname);
3037         if (!NT_STATUS_IS_OK(status)) {
3038                 d_printf("posix_unlink %s: %s\n", mask, nt_errstr(status));
3039                 return 1;
3040         }
3041
3042         status = cli_posix_unlink(targetcli, targetname);
3043         if (!NT_STATUS_IS_OK(status)) {
3044                 d_printf("Failed to unlink file %s. %s\n",
3045                          targetname, nt_errstr(status));
3046         } else {
3047                 d_printf("posix_unlink deleted file %s\n", targetname);
3048         }
3049
3050         return 0;
3051 }
3052
3053 static int cmd_posix_rmdir(void)
3054 {
3055         TALLOC_CTX *ctx = talloc_tos();
3056         char *mask = NULL;
3057         char *buf = NULL;
3058         char *targetname = NULL;
3059         struct cli_state *targetcli;
3060         NTSTATUS status;
3061
3062         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3063                 d_printf("posix_rmdir <filename>\n");
3064                 return 1;
3065         }
3066         mask = talloc_asprintf(ctx,
3067                         "%s%s",
3068                         client_get_cur_dir(),
3069                         buf);
3070         if (!mask) {
3071                 return 1;
3072         }
3073         mask = client_clean_name(ctx, mask);
3074         if (mask == NULL) {
3075                 return 1;
3076         }
3077
3078         status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
3079                         cli, mask, &targetcli, &targetname);
3080         if (!NT_STATUS_IS_OK(status)) {
3081                 d_printf("posix_rmdir %s: %s\n", mask, nt_errstr(status));
3082                 return 1;
3083         }
3084
3085         status = cli_posix_rmdir(targetcli, targetname);
3086         if (!NT_STATUS_IS_OK(status)) {
3087