Line data Source code
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 "rpc_client/cli_pipe.h"
27 : #include "client/client_proto.h"
28 : #include "client/clitar_proto.h"
29 : #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
30 : #include "../lib/util/select.h"
31 : #include "system/readline.h"
32 : #include "../libcli/smbreadline/smbreadline.h"
33 : #include "../libcli/security/security.h"
34 : #include "system/select.h"
35 : #include "libsmb/libsmb.h"
36 : #include "libsmb/clirap.h"
37 : #include "trans2.h"
38 : #include "libsmb/nmblib.h"
39 : #include "include/ntioctl.h"
40 : #include "../libcli/smb/smbXcli_base.h"
41 : #include "lib/util/time_basic.h"
42 : #include "lib/util/string_wrappers.h"
43 : #include "lib/cmdline/cmdline.h"
44 :
45 : #ifndef REGISTER
46 : #define REGISTER 0
47 : #endif
48 :
49 : extern int do_smb_browse(void); /* mDNS browsing */
50 :
51 : static int port = 0;
52 : static char *service;
53 : static char *desthost;
54 : static bool grepable = false;
55 : static bool quiet = false;
56 : static char *cmdstr = NULL;
57 : const char *cmd_ptr = NULL;
58 :
59 : static int io_bufsize = 0; /* we use the default size */
60 : static int io_timeout = (CLIENT_TIMEOUT/1000); /* Per operation timeout (in seconds). */
61 :
62 : static int name_type = 0x20;
63 :
64 : static int process_tok(char *tok);
65 : static int cmd_help(void);
66 :
67 : /* value for unused fid field in trans2 secondary request */
68 : #define FID_UNUSED (0xFFFF)
69 :
70 : time_t newer_than = 0;
71 : static int archive_level = 0;
72 :
73 : static bool translation = false;
74 : static bool have_ip;
75 :
76 : static bool prompt = true;
77 :
78 : static bool recurse = false;
79 : static bool showacls = false;
80 : bool lowercase = false;
81 : static bool backup_intent = false;
82 :
83 : static struct sockaddr_storage dest_ss;
84 : static char dest_ss_str[INET6_ADDRSTRLEN];
85 :
86 : #define SEPARATORS " \t\n\r"
87 :
88 : /* timing globals */
89 : uint64_t get_total_size = 0;
90 : unsigned int get_total_time_ms = 0;
91 : static uint64_t put_total_size = 0;
92 : static unsigned int put_total_time_ms = 0;
93 :
94 : /* totals globals */
95 : static double dir_total;
96 :
97 : /* root cli_state connection */
98 :
99 : struct cli_state *cli;
100 :
101 : static char CLI_DIRSEP_CHAR = '\\';
102 : static char CLI_DIRSEP_STR[] = { '\\', '\0' };
103 :
104 : /* Accessor functions for directory paths. */
105 : static char *fileselection;
106 1171 : static const char *client_get_fileselection(void)
107 : {
108 1171 : if (fileselection) {
109 0 : return fileselection;
110 : }
111 1171 : return "";
112 : }
113 :
114 0 : static const char *client_set_fileselection(const char *new_fs)
115 : {
116 0 : SAFE_FREE(fileselection);
117 0 : if (new_fs) {
118 0 : fileselection = SMB_STRDUP(new_fs);
119 : }
120 0 : return client_get_fileselection();
121 : }
122 :
123 : static char *cwd;
124 0 : static const char *client_get_cwd(void)
125 : {
126 0 : if (cwd) {
127 0 : return cwd;
128 : }
129 0 : return CLI_DIRSEP_STR;
130 : }
131 :
132 0 : static const char *client_set_cwd(const char *new_cwd)
133 : {
134 0 : SAFE_FREE(cwd);
135 0 : if (new_cwd) {
136 0 : cwd = SMB_STRDUP(new_cwd);
137 : }
138 0 : return client_get_cwd();
139 : }
140 :
141 : static char *cur_dir;
142 3687 : const char *client_get_cur_dir(void)
143 : {
144 3687 : if (cur_dir) {
145 3687 : return cur_dir;
146 : }
147 0 : return CLI_DIRSEP_STR;
148 : }
149 :
150 1359 : const char *client_set_cur_dir(const char *newdir)
151 : {
152 1359 : SAFE_FREE(cur_dir);
153 1359 : if (newdir) {
154 1359 : cur_dir = SMB_STRDUP(newdir);
155 : }
156 1359 : return client_get_cur_dir();
157 : }
158 :
159 : /****************************************************************************
160 : Put up a yes/no prompt.
161 : ****************************************************************************/
162 :
163 0 : static bool yesno(const char *p)
164 : {
165 : char ans[20];
166 0 : printf("%s",p);
167 :
168 0 : if (!fgets(ans,sizeof(ans)-1,stdin))
169 0 : return(False);
170 :
171 0 : if (*ans == 'y' || *ans == 'Y')
172 0 : return(True);
173 :
174 0 : return(False);
175 : }
176 :
177 : /****************************************************************************
178 : Write to a local file with CR/LF->LF translation if appropriate. Return the
179 : number taken from the buffer. This may not equal the number written.
180 : ****************************************************************************/
181 :
182 19 : static ssize_t writefile(int f, char *b, size_t n)
183 : {
184 19 : size_t i = 0;
185 :
186 19 : if (n == 0) {
187 0 : errno = EINVAL;
188 0 : return -1;
189 : }
190 :
191 19 : if (!translation) {
192 19 : return write(f,b,n);
193 : }
194 :
195 : do {
196 0 : if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
197 0 : b++;i++;
198 : }
199 0 : if (write(f, b, 1) != 1) {
200 0 : break;
201 : }
202 0 : b++;
203 0 : i++;
204 0 : } while (i < n);
205 :
206 0 : return (ssize_t)i;
207 : }
208 :
209 : /****************************************************************************
210 : Read from a file with LF->CR/LF translation if appropriate. Return the
211 : number read. read approx n bytes.
212 : ****************************************************************************/
213 :
214 95 : static int readfile(uint8_t *b, int n, FILE *f)
215 : {
216 : int i;
217 : int c;
218 :
219 95 : if (!translation)
220 95 : return fread(b,1,n,f);
221 :
222 0 : i = 0;
223 0 : while (i < (n - 1)) {
224 0 : if ((c = getc(f)) == EOF) {
225 0 : break;
226 : }
227 :
228 0 : if (c == '\n') { /* change all LFs to CR/LF */
229 0 : b[i++] = '\r';
230 : }
231 :
232 0 : b[i++] = c;
233 : }
234 :
235 0 : return(i);
236 : }
237 :
238 : struct push_state {
239 : FILE *f;
240 : off_t nread;
241 : };
242 :
243 156 : static size_t push_source(uint8_t *buf, size_t n, void *priv)
244 : {
245 156 : struct push_state *state = (struct push_state *)priv;
246 : int result;
247 :
248 156 : if (feof(state->f)) {
249 61 : return 0;
250 : }
251 :
252 95 : result = readfile(buf, n, state->f);
253 95 : state->nread += result;
254 95 : return result;
255 : }
256 :
257 : /****************************************************************************
258 : Send a message.
259 : ****************************************************************************/
260 :
261 8 : static void send_message(const char *username)
262 : {
263 : char buf[1600];
264 : NTSTATUS status;
265 : size_t i;
266 :
267 8 : d_printf("Type your message, ending it with a Control-D\n");
268 :
269 8 : i = 0;
270 228 : while (i<sizeof(buf)-2) {
271 224 : int c = fgetc(stdin);
272 224 : if (c == EOF) {
273 8 : break;
274 : }
275 216 : if (c == '\n') {
276 8 : buf[i++] = '\r';
277 : }
278 216 : buf[i++] = c;
279 : }
280 8 : buf[i] = '\0';
281 :
282 8 : status = cli_message(cli, desthost, username, buf);
283 8 : if (!NT_STATUS_IS_OK(status)) {
284 8 : d_fprintf(stderr, "cli_message returned %s\n",
285 : nt_errstr(status));
286 : }
287 8 : }
288 :
289 : /****************************************************************************
290 : Check the space on a device.
291 : ****************************************************************************/
292 :
293 387 : static int do_dskattr(void)
294 : {
295 : uint64_t total, bsize, avail;
296 387 : struct cli_state *targetcli = NULL;
297 387 : char *targetpath = NULL;
298 387 : TALLOC_CTX *ctx = talloc_tos();
299 387 : struct cli_credentials *creds = samba_cmdline_get_creds();
300 : NTSTATUS status;
301 :
302 387 : status = cli_resolve_path(ctx,
303 : "",
304 : creds,
305 : cli,
306 : client_get_cur_dir(), &targetcli,
307 : &targetpath);
308 387 : if (!NT_STATUS_IS_OK(status)) {
309 0 : d_printf("Error in dskattr: %s\n", nt_errstr(status));
310 0 : return 1;
311 : }
312 :
313 387 : status = cli_disk_size(targetcli, targetpath, &bsize, &total, &avail);
314 387 : if (!NT_STATUS_IS_OK(status)) {
315 0 : d_printf("Error in dskattr: %s\n", nt_errstr(status));
316 0 : return 1;
317 : }
318 :
319 387 : d_printf("\n\t\t%" PRIu64
320 : " blocks of size %" PRIu64
321 : ". %" PRIu64 " blocks available\n",
322 : total, bsize, avail);
323 :
324 387 : return 0;
325 : }
326 :
327 : /****************************************************************************
328 : Show cd/pwd.
329 : ****************************************************************************/
330 :
331 0 : static int cmd_pwd(void)
332 : {
333 0 : d_printf("Current directory is %s",service);
334 0 : d_printf("%s\n",client_get_cur_dir());
335 0 : return 0;
336 : }
337 :
338 : /****************************************************************************
339 : Ensure name has correct directory separators.
340 : ****************************************************************************/
341 :
342 1125 : static void normalize_name(char *newdir)
343 : {
344 1125 : if (!(cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
345 1125 : string_replace(newdir,'/','\\');
346 : }
347 1125 : }
348 :
349 : /****************************************************************************
350 : Local name cleanup before sending to server. SMB1 allows relative pathnames,
351 : but SMB2 does not, so we need to resolve them locally.
352 : ****************************************************************************/
353 :
354 1020 : char *client_clean_name(TALLOC_CTX *ctx, const char *name)
355 : {
356 1020 : char *newname = NULL;
357 1020 : if (name == NULL) {
358 0 : return NULL;
359 : }
360 :
361 : /* First ensure any path separators are correct. */
362 1020 : newname = talloc_strdup(ctx, name);
363 1020 : if (newname == NULL) {
364 0 : return NULL;
365 : }
366 1020 : normalize_name(newname);
367 :
368 : /* Now remove any relative (..) path components. */
369 1020 : if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
370 0 : newname = unix_clean_name(ctx, newname);
371 : } else {
372 1020 : newname = clean_name(ctx, newname);
373 : }
374 1020 : if (newname == NULL) {
375 0 : return NULL;
376 : }
377 1020 : return newname;
378 : }
379 :
380 : /****************************************************************************
381 : Change directory - inner section.
382 : ****************************************************************************/
383 :
384 88 : static int do_cd(const char *new_dir)
385 : {
386 88 : char *newdir = NULL;
387 88 : char *saved_dir = NULL;
388 88 : char *new_cd = NULL;
389 88 : char *targetpath = NULL;
390 88 : struct cli_state *targetcli = NULL;
391 88 : int ret = 1;
392 88 : TALLOC_CTX *ctx = talloc_stackframe();
393 88 : struct cli_credentials *creds = samba_cmdline_get_creds();
394 : NTSTATUS status;
395 :
396 88 : newdir = talloc_strdup(ctx, new_dir);
397 88 : if (!newdir) {
398 0 : TALLOC_FREE(ctx);
399 0 : return 1;
400 : }
401 :
402 88 : normalize_name(newdir);
403 :
404 : /* Save the current directory in case the new directory is invalid */
405 :
406 88 : saved_dir = talloc_strdup(ctx, client_get_cur_dir());
407 88 : if (!saved_dir) {
408 0 : TALLOC_FREE(ctx);
409 0 : return 1;
410 : }
411 :
412 88 : if (*newdir == CLI_DIRSEP_CHAR) {
413 28 : client_set_cur_dir(newdir);
414 28 : new_cd = newdir;
415 : } else {
416 60 : new_cd = talloc_asprintf(ctx, "%s%s",
417 : client_get_cur_dir(),
418 : newdir);
419 60 : if (!new_cd) {
420 0 : goto out;
421 : }
422 : }
423 :
424 : /* Ensure cur_dir ends in a DIRSEP */
425 88 : if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
426 84 : new_cd = talloc_asprintf_append(new_cd, "%s", CLI_DIRSEP_STR);
427 84 : if (!new_cd) {
428 0 : goto out;
429 : }
430 : }
431 88 : client_set_cur_dir(new_cd);
432 :
433 88 : new_cd = client_clean_name(ctx, new_cd);
434 88 : client_set_cur_dir(new_cd);
435 :
436 88 : status = cli_resolve_path(ctx, "",
437 : creds,
438 : cli, new_cd, &targetcli, &targetpath);
439 88 : if (!NT_STATUS_IS_OK(status)) {
440 0 : d_printf("cd %s: %s\n", new_cd, nt_errstr(status));
441 0 : client_set_cur_dir(saved_dir);
442 0 : goto out;
443 : }
444 :
445 88 : if (strequal(targetpath,CLI_DIRSEP_STR )) {
446 24 : TALLOC_FREE(ctx);
447 24 : return 0;
448 : }
449 :
450 :
451 64 : targetpath = talloc_asprintf(
452 : ctx, "%s%s", targetpath, CLI_DIRSEP_STR);
453 64 : if (!targetpath) {
454 0 : client_set_cur_dir(saved_dir);
455 0 : goto out;
456 : }
457 64 : targetpath = client_clean_name(ctx, targetpath);
458 64 : if (!targetpath) {
459 0 : client_set_cur_dir(saved_dir);
460 0 : goto out;
461 : }
462 :
463 64 : status = cli_chkpath(targetcli, targetpath);
464 64 : if (!NT_STATUS_IS_OK(status)) {
465 0 : d_printf("cd %s: %s\n", new_cd, nt_errstr(status));
466 0 : client_set_cur_dir(saved_dir);
467 0 : goto out;
468 : }
469 :
470 64 : ret = 0;
471 :
472 64 : out:
473 :
474 64 : TALLOC_FREE(ctx);
475 64 : return ret;
476 : }
477 :
478 : /****************************************************************************
479 : Change directory.
480 : ****************************************************************************/
481 :
482 88 : static int cmd_cd(void)
483 : {
484 88 : char *buf = NULL;
485 88 : int rc = 0;
486 :
487 88 : if (next_token_talloc(talloc_tos(), &cmd_ptr, &buf,NULL)) {
488 88 : rc = do_cd(buf);
489 : } else {
490 0 : d_printf("Current directory is %s\n",client_get_cur_dir());
491 : }
492 :
493 88 : return rc;
494 : }
495 :
496 : /****************************************************************************
497 : Change directory.
498 : ****************************************************************************/
499 :
500 0 : static int cmd_cd_oneup(void)
501 : {
502 0 : return do_cd("..");
503 : }
504 :
505 : /*******************************************************************
506 : Decide if a file should be operated on.
507 : ********************************************************************/
508 :
509 13427 : static bool do_this_one(struct file_info *finfo)
510 : {
511 13427 : if (!finfo->name) {
512 0 : return false;
513 : }
514 :
515 13427 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
516 12256 : return true;
517 : }
518 :
519 1171 : if (*client_get_fileselection() &&
520 0 : !mask_match(finfo->name,client_get_fileselection(),false)) {
521 0 : DEBUG(3,("mask_match %s failed\n", finfo->name));
522 0 : return false;
523 : }
524 :
525 1171 : if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
526 0 : DEBUG(3,("newer_than %s failed\n", finfo->name));
527 0 : return false;
528 : }
529 :
530 1171 : if ((archive_level==1 || archive_level==2) && !(finfo->attr & FILE_ATTRIBUTE_ARCHIVE)) {
531 0 : DEBUG(3,("archive %s failed\n", finfo->name));
532 0 : return false;
533 : }
534 :
535 1171 : return true;
536 : }
537 :
538 : /****************************************************************************
539 : Display info about a file.
540 : ****************************************************************************/
541 :
542 6049 : static NTSTATUS display_finfo(struct cli_state *cli_state, struct file_info *finfo,
543 : const char *dir)
544 : {
545 : time_t t;
546 6049 : TALLOC_CTX *ctx = talloc_tos();
547 6049 : NTSTATUS status = NT_STATUS_OK;
548 :
549 6049 : if (!do_this_one(finfo)) {
550 0 : return NT_STATUS_OK;
551 : }
552 :
553 6049 : t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
554 6049 : if (!showacls) {
555 12098 : d_printf(" %-30s%7.7s %8.0f %s",
556 : finfo->name,
557 : attrib_string(talloc_tos(), finfo->attr),
558 6049 : (double)finfo->size,
559 : time_to_asc(t));
560 6049 : dir_total += finfo->size;
561 : } else {
562 0 : struct cli_state *targetcli = NULL;
563 0 : char *targetpath = NULL;
564 0 : char *afname = NULL;
565 : uint16_t fnum;
566 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
567 :
568 0 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
569 0 : return NT_STATUS_OK;
570 : }
571 : /* create absolute filename for cli_ntcreate() FIXME */
572 0 : afname = talloc_asprintf(ctx,
573 : "%s%s%s",
574 : dir,
575 : CLI_DIRSEP_STR,
576 : finfo->name);
577 0 : if (!afname) {
578 0 : return NT_STATUS_NO_MEMORY;
579 : }
580 : /* print file meta date header */
581 0 : d_printf( "FILENAME:%s\n", finfo->name);
582 0 : d_printf( "MODE:%s\n", attrib_string(talloc_tos(), finfo->attr));
583 0 : d_printf( "SIZE:%.0f\n", (double)finfo->size);
584 0 : d_printf( "MTIME:%s", time_to_asc(t));
585 :
586 0 : status = cli_resolve_path(
587 : ctx,
588 : "",
589 : creds,
590 : cli_state,
591 : afname,
592 : &targetcli,
593 : &targetpath);
594 0 : if (!NT_STATUS_IS_OK(status)) {
595 0 : DBG_WARNING("display_finfo() Failed to resolve "
596 : "%s: %s\n",
597 : afname, nt_errstr(status));
598 0 : return status;
599 : }
600 :
601 0 : status = cli_ntcreate(
602 : targetcli, /* cli */
603 : targetpath, /* fname */
604 : 0, /* CreatFlags */
605 : READ_CONTROL_ACCESS, /* DesiredAccess */
606 : 0, /* FileAttributes */
607 : FILE_SHARE_READ|
608 : FILE_SHARE_WRITE, /* ShareAccess */
609 : FILE_OPEN, /* CreateDisposition */
610 : 0x0, /* CreateOptions */
611 : 0x0, /* SecurityFlags */
612 : &fnum, /* pfid */
613 : NULL); /* cr */
614 0 : if (!NT_STATUS_IS_OK(status)) {
615 0 : DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
616 : afname, nt_errstr(status)));
617 : } else {
618 0 : struct security_descriptor *sd = NULL;
619 0 : status = cli_query_secdesc(targetcli, fnum,
620 : ctx, &sd);
621 0 : if (!NT_STATUS_IS_OK(status)) {
622 0 : DEBUG( 0, ("display_finfo() failed to "
623 : "get security descriptor: %s",
624 : nt_errstr(status)));
625 : } else {
626 0 : display_sec_desc(sd);
627 : }
628 0 : TALLOC_FREE(sd);
629 0 : cli_close(targetcli, fnum);
630 : }
631 0 : TALLOC_FREE(afname);
632 : }
633 6049 : return status;
634 : }
635 :
636 : /****************************************************************************
637 : Accumulate size of a file.
638 : ****************************************************************************/
639 :
640 376 : static NTSTATUS do_du(struct cli_state *cli_state, struct file_info *finfo,
641 : const char *dir)
642 : {
643 376 : if (do_this_one(finfo)) {
644 376 : dir_total += finfo->size;
645 : }
646 376 : return NT_STATUS_OK;
647 : }
648 :
649 : struct do_list_queue_entry {
650 : struct do_list_queue_entry *prev, *next;
651 : char name[];
652 : };
653 :
654 : struct do_list_queue {
655 : struct do_list_queue_entry *list;
656 : };
657 :
658 : static bool do_list_recurse;
659 : static bool do_list_dirs;
660 : static struct do_list_queue *queue = NULL;
661 : static NTSTATUS (*do_list_fn)(struct cli_state *cli_state, struct file_info *,
662 : const char *dir);
663 :
664 : /****************************************************************************
665 : Functions for do_list_queue.
666 : ****************************************************************************/
667 :
668 548 : static void reset_do_list_queue(void)
669 : {
670 548 : TALLOC_FREE(queue);
671 548 : }
672 :
673 548 : static void init_do_list_queue(void)
674 : {
675 548 : TALLOC_FREE(queue);
676 548 : queue = talloc_zero(NULL, struct do_list_queue);
677 548 : }
678 :
679 972 : static void add_to_do_list_queue(const char *entry)
680 : {
681 972 : struct do_list_queue_entry *e = NULL;
682 972 : size_t entry_str_len = strlen(entry)+1;
683 972 : size_t entry_len = offsetof(struct do_list_queue_entry, name);
684 :
685 972 : entry_len += entry_str_len;
686 972 : SMB_ASSERT(entry_len >= entry_str_len);
687 :
688 972 : e = talloc_size(queue, entry_len);
689 972 : if (e == NULL) {
690 0 : d_printf("talloc failed for entry %s\n", entry);
691 0 : return;
692 : }
693 972 : talloc_set_name_const(e, "struct do_list_queue_entry");
694 :
695 972 : memcpy(e->name, entry, entry_str_len);
696 972 : DLIST_ADD_END(queue->list, e);
697 : }
698 :
699 1324 : static char *do_list_queue_head(void)
700 : {
701 1324 : return queue->list->name;
702 : }
703 :
704 972 : static void remove_do_list_queue_head(void)
705 : {
706 972 : struct do_list_queue_entry *e = queue->list;
707 972 : DLIST_REMOVE(queue->list, e);
708 972 : TALLOC_FREE(e);
709 972 : }
710 :
711 2492 : static int do_list_queue_empty(void)
712 : {
713 2492 : return (queue == NULL) || (queue->list == NULL);
714 : }
715 :
716 : /****************************************************************************
717 : A helper for do_list.
718 : ****************************************************************************/
719 :
720 : struct do_list_helper_state {
721 : const char *mask;
722 : struct cli_state *cli;
723 : };
724 :
725 6734 : static NTSTATUS do_list_helper(
726 : struct file_info *f,
727 : const char *_mask,
728 : void *private_data)
729 : {
730 6734 : struct do_list_helper_state *state = private_data;
731 6734 : TALLOC_CTX *ctx = talloc_tos();
732 6734 : char *dir = NULL;
733 6734 : char *dir_end = NULL;
734 6734 : NTSTATUS status = NT_STATUS_OK;
735 6734 : char *mask2 = NULL;
736 :
737 : /* Work out the directory. */
738 6734 : dir = talloc_strdup(ctx, state->mask);
739 6734 : if (!dir) {
740 0 : return NT_STATUS_NO_MEMORY;
741 : }
742 6734 : if ((dir_end = strrchr(dir, CLI_DIRSEP_CHAR)) != NULL) {
743 6358 : *dir_end = '\0';
744 : }
745 :
746 6734 : if (!(f->attr & FILE_ATTRIBUTE_DIRECTORY)) {
747 606 : if (do_this_one(f)) {
748 606 : status = do_list_fn(state->cli, f, dir);
749 : }
750 606 : TALLOC_FREE(dir);
751 606 : return status;
752 : }
753 :
754 6128 : if (do_list_dirs && do_this_one(f)) {
755 6128 : status = do_list_fn(state->cli, f, dir);
756 6128 : if (!NT_STATUS_IS_OK(status)) {
757 0 : return status;
758 : }
759 : }
760 :
761 6763 : if (!do_list_recurse ||
762 1899 : (f->name == NULL) ||
763 2112 : ISDOT(f->name) ||
764 1057 : ISDOTDOT(f->name)) {
765 5704 : return NT_STATUS_OK;
766 : }
767 :
768 424 : if (!f->name[0]) {
769 0 : d_printf("Empty dir name returned. Possible server misconfiguration.\n");
770 0 : TALLOC_FREE(dir);
771 0 : return NT_STATUS_UNSUCCESSFUL;
772 : }
773 :
774 424 : mask2 = talloc_asprintf(ctx,
775 : "%s%c%s%c*",
776 : dir,
777 : CLI_DIRSEP_CHAR,
778 : f->name,
779 : CLI_DIRSEP_CHAR);
780 424 : if (!mask2) {
781 0 : TALLOC_FREE(dir);
782 0 : return NT_STATUS_NO_MEMORY;
783 : }
784 424 : add_to_do_list_queue(mask2);
785 424 : TALLOC_FREE(mask2);
786 :
787 424 : TALLOC_FREE(dir);
788 424 : return NT_STATUS_OK;
789 : }
790 :
791 : /****************************************************************************
792 : A wrapper around cli_list that adds recursion.
793 : ****************************************************************************/
794 :
795 548 : NTSTATUS do_list(const char *mask,
796 : uint32_t attribute,
797 : NTSTATUS (*fn)(struct cli_state *cli_state, struct file_info *,
798 : const char *dir),
799 : bool rec,
800 : bool dirs)
801 : {
802 548 : struct do_list_helper_state state = { .cli = cli, };
803 : static int in_do_list = 0;
804 548 : TALLOC_CTX *ctx = talloc_tos();
805 548 : struct cli_credentials *creds = samba_cmdline_get_creds();
806 548 : NTSTATUS ret_status = NT_STATUS_OK;
807 548 : NTSTATUS status = NT_STATUS_OK;
808 :
809 548 : if (in_do_list && rec) {
810 0 : fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
811 0 : exit(1);
812 : }
813 :
814 548 : in_do_list = 1;
815 :
816 548 : do_list_recurse = rec;
817 548 : do_list_dirs = dirs;
818 548 : do_list_fn = fn;
819 :
820 548 : init_do_list_queue();
821 548 : add_to_do_list_queue(mask);
822 :
823 1815 : while (!do_list_queue_empty()) {
824 972 : struct cli_state *targetcli = NULL;
825 972 : char *targetpath = NULL;
826 :
827 972 : state.mask = do_list_queue_head();
828 :
829 : /* check for dfs */
830 :
831 972 : status = cli_resolve_path(
832 : ctx,
833 : "",
834 : creds,
835 : cli,
836 : state.mask,
837 : &targetcli,
838 : &targetpath);
839 972 : if (!NT_STATUS_IS_OK(status)) {
840 0 : d_printf("do_list: [%s] %s\n", state.mask,
841 : nt_errstr(status));
842 0 : remove_do_list_queue_head();
843 0 : continue;
844 : }
845 :
846 972 : status = cli_list(
847 : targetcli,
848 : targetpath,
849 : attribute,
850 : do_list_helper,
851 : &state);
852 972 : if (!NT_STATUS_IS_OK(status)) {
853 60 : d_printf("%s listing %s\n",
854 : nt_errstr(status), targetpath);
855 60 : ret_status = status;
856 : }
857 972 : remove_do_list_queue_head();
858 972 : if ((! do_list_queue_empty()) && (fn == display_finfo)) {
859 352 : char *next_file = do_list_queue_head();
860 352 : char *save_ch = 0;
861 529 : if ((strlen(next_file) >= 2) &&
862 529 : (next_file[strlen(next_file) - 1] == '*') &&
863 352 : (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
864 352 : save_ch = next_file +
865 352 : strlen(next_file) - 2;
866 352 : *save_ch = '\0';
867 352 : if (showacls) {
868 : /* cwd is only used if showacls is on */
869 0 : client_set_cwd(next_file);
870 : }
871 : }
872 352 : if (!showacls) /* don't disturbe the showacls output */
873 352 : d_printf("\n%s\n",next_file);
874 352 : if (save_ch) {
875 352 : *save_ch = CLI_DIRSEP_CHAR;
876 : }
877 : }
878 972 : TALLOC_FREE(targetpath);
879 : }
880 :
881 548 : in_do_list = 0;
882 548 : reset_do_list_queue();
883 548 : return ret_status;
884 : }
885 :
886 : /****************************************************************************
887 : Get a directory listing.
888 : ****************************************************************************/
889 :
890 399 : static int cmd_dir(void)
891 : {
892 399 : TALLOC_CTX *ctx = talloc_tos();
893 399 : uint32_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
894 399 : char *mask = NULL;
895 399 : char *buf = NULL;
896 399 : int rc = 1;
897 : NTSTATUS status;
898 :
899 399 : dir_total = 0;
900 399 : mask = talloc_strdup(ctx, client_get_cur_dir());
901 399 : if (!mask) {
902 0 : return 1;
903 : }
904 :
905 399 : if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
906 17 : normalize_name(buf);
907 17 : if (*buf == CLI_DIRSEP_CHAR) {
908 0 : mask = talloc_strdup(ctx, buf);
909 : } else {
910 17 : mask = talloc_asprintf_append(mask, "%s", buf);
911 : }
912 : } else {
913 382 : mask = talloc_asprintf_append(mask, "*");
914 : }
915 399 : if (!mask) {
916 0 : return 1;
917 : }
918 :
919 399 : mask = client_clean_name(ctx, mask);
920 399 : if (mask == NULL) {
921 0 : return 1;
922 : }
923 :
924 399 : if (showacls) {
925 : /* cwd is only used if showacls is on */
926 0 : client_set_cwd(client_get_cur_dir());
927 : }
928 :
929 399 : status = do_list(mask, attribute, display_finfo, recurse, true);
930 399 : if (!NT_STATUS_IS_OK(status)) {
931 28 : return 1;
932 : }
933 :
934 371 : rc = do_dskattr();
935 :
936 371 : DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
937 :
938 371 : return rc;
939 : }
940 :
941 : /****************************************************************************
942 : Get a directory listing.
943 : ****************************************************************************/
944 :
945 16 : static int cmd_du(void)
946 : {
947 16 : TALLOC_CTX *ctx = talloc_tos();
948 16 : uint32_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
949 16 : char *mask = NULL;
950 16 : char *buf = NULL;
951 : NTSTATUS status;
952 16 : int rc = 1;
953 :
954 16 : dir_total = 0;
955 16 : mask = talloc_strdup(ctx, client_get_cur_dir());
956 16 : if (!mask) {
957 0 : return 1;
958 : }
959 16 : if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
960 0 : mask = talloc_asprintf_append(mask, "%s", CLI_DIRSEP_STR);
961 0 : if (!mask) {
962 0 : return 1;
963 : }
964 : }
965 :
966 16 : if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
967 0 : normalize_name(buf);
968 0 : if (*buf == CLI_DIRSEP_CHAR) {
969 0 : mask = talloc_strdup(ctx, buf);
970 : } else {
971 0 : mask = talloc_asprintf_append(mask, "%s", buf);
972 : }
973 : } else {
974 16 : mask = talloc_strdup(ctx, "*");
975 : }
976 16 : if (!mask) {
977 0 : return 1;
978 : }
979 :
980 16 : mask = client_clean_name(ctx, mask);
981 16 : if (mask == NULL) {
982 0 : return 1;
983 : }
984 :
985 16 : status = do_list(mask, attribute, do_du, recurse, true);
986 16 : if (!NT_STATUS_IS_OK(status)) {
987 0 : return 1;
988 : }
989 :
990 16 : rc = do_dskattr();
991 :
992 16 : d_printf("Total number of bytes: %.0f\n", dir_total);
993 :
994 16 : return rc;
995 : }
996 :
997 8 : static int cmd_echo(void)
998 : {
999 8 : TALLOC_CTX *ctx = talloc_tos();
1000 : char *num;
1001 : char *data;
1002 : NTSTATUS status;
1003 :
1004 8 : if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
1005 8 : || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
1006 8 : d_printf("echo <num> <data>\n");
1007 8 : return 1;
1008 : }
1009 :
1010 0 : status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
1011 :
1012 0 : if (!NT_STATUS_IS_OK(status)) {
1013 0 : d_printf("echo failed: %s\n", nt_errstr(status));
1014 0 : return 1;
1015 : }
1016 :
1017 0 : return 0;
1018 : }
1019 :
1020 : /****************************************************************************
1021 : Get a file from rname to lname
1022 : ****************************************************************************/
1023 :
1024 19 : static NTSTATUS writefile_sink(char *buf, size_t n, void *priv)
1025 : {
1026 19 : int *pfd = (int *)priv;
1027 : ssize_t rc;
1028 :
1029 19 : rc = writefile(*pfd, buf, n);
1030 19 : if (rc == -1) {
1031 0 : return map_nt_error_from_unix(errno);
1032 : }
1033 19 : return NT_STATUS_OK;
1034 : }
1035 :
1036 21 : static int do_get(const char *rname, const char *lname_in, bool reget)
1037 : {
1038 21 : TALLOC_CTX *ctx = talloc_tos();
1039 21 : int handle = 0;
1040 : uint16_t fnum;
1041 21 : bool newhandle = false;
1042 : struct timespec tp_start;
1043 : uint32_t attr;
1044 : off_t size;
1045 21 : off_t start = 0;
1046 21 : off_t nread = 0;
1047 21 : int rc = 0;
1048 21 : struct cli_state *targetcli = NULL;
1049 21 : char *targetname = NULL;
1050 21 : char *lname = NULL;
1051 21 : struct cli_credentials *creds = samba_cmdline_get_creds();
1052 : NTSTATUS status;
1053 :
1054 21 : lname = talloc_strdup(ctx, lname_in);
1055 21 : if (!lname) {
1056 0 : return 1;
1057 : }
1058 :
1059 21 : if (lowercase) {
1060 0 : if (!strlower_m(lname)) {
1061 0 : d_printf("strlower_m %s failed\n", lname);
1062 0 : return 1;
1063 : }
1064 : }
1065 :
1066 21 : status = cli_resolve_path(ctx, "",
1067 : creds,
1068 : cli, rname, &targetcli, &targetname);
1069 21 : if (!NT_STATUS_IS_OK(status)) {
1070 0 : d_printf("Failed to open %s: %s\n", rname, nt_errstr(status));
1071 0 : return 1;
1072 : }
1073 :
1074 21 : clock_gettime_mono(&tp_start);
1075 :
1076 21 : status = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE, &fnum);
1077 21 : if (!NT_STATUS_IS_OK(status)) {
1078 12 : d_printf("%s opening remote file %s\n", nt_errstr(status),
1079 : rname);
1080 12 : return 1;
1081 : }
1082 :
1083 9 : if(!strcmp(lname,"-")) {
1084 4 : handle = fileno(stdout);
1085 : } else {
1086 5 : if (reget) {
1087 0 : handle = open(lname, O_WRONLY|O_CREAT, 0644);
1088 0 : if (handle >= 0) {
1089 0 : start = lseek(handle, 0, SEEK_END);
1090 0 : if (start == -1) {
1091 0 : d_printf("Error seeking local file\n");
1092 0 : close(handle);
1093 0 : return 1;
1094 : }
1095 : }
1096 : } else {
1097 5 : handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1098 : }
1099 5 : newhandle = true;
1100 : }
1101 9 : if (handle < 0) {
1102 0 : d_printf("Error opening local file %s\n",lname);
1103 0 : return 1;
1104 : }
1105 :
1106 :
1107 9 : status = cli_qfileinfo_basic(targetcli, fnum, &attr, &size, NULL, NULL,
1108 : NULL, NULL, NULL);
1109 9 : if (!NT_STATUS_IS_OK(status)) {
1110 0 : d_printf("getattrib: %s\n", nt_errstr(status));
1111 0 : if (newhandle) {
1112 0 : close(handle);
1113 : }
1114 0 : return 1;
1115 : }
1116 :
1117 9 : DEBUG(1,("getting file %s of size %.0f as %s ",
1118 : rname, (double)size, lname));
1119 :
1120 9 : status = cli_pull(targetcli, fnum, start, size, io_bufsize,
1121 : writefile_sink, (void *)&handle, &nread);
1122 9 : if (!NT_STATUS_IS_OK(status)) {
1123 0 : d_fprintf(stderr, "parallel_read returned %s\n",
1124 : nt_errstr(status));
1125 0 : if (newhandle) {
1126 0 : close(handle);
1127 : }
1128 0 : cli_close(targetcli, fnum);
1129 0 : return 1;
1130 : }
1131 :
1132 9 : status = cli_close(targetcli, fnum);
1133 9 : if (!NT_STATUS_IS_OK(status)) {
1134 0 : d_printf("Error %s closing remote file\n", nt_errstr(status));
1135 0 : rc = 1;
1136 : }
1137 :
1138 9 : if (newhandle) {
1139 5 : close(handle);
1140 : }
1141 :
1142 9 : if (archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
1143 0 : cli_setatr(cli, rname, attr & ~(uint32_t)FILE_ATTRIBUTE_ARCHIVE, 0);
1144 : }
1145 :
1146 : {
1147 : struct timespec tp_end;
1148 : int this_time;
1149 :
1150 9 : clock_gettime_mono(&tp_end);
1151 9 : this_time = nsec_time_diff(&tp_end,&tp_start)/1000000;
1152 9 : get_total_time_ms += this_time;
1153 9 : get_total_size += nread;
1154 :
1155 9 : DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
1156 : nread / (1.024*this_time + 1.0e-4),
1157 : get_total_size / (1.024*get_total_time_ms)));
1158 : }
1159 :
1160 9 : TALLOC_FREE(targetname);
1161 9 : return rc;
1162 : }
1163 :
1164 : /****************************************************************************
1165 : Get a file.
1166 : ****************************************************************************/
1167 :
1168 21 : static int cmd_get(void)
1169 : {
1170 21 : TALLOC_CTX *ctx = talloc_tos();
1171 21 : char *lname = NULL;
1172 21 : char *rname = NULL;
1173 21 : char *fname = NULL;
1174 :
1175 21 : rname = talloc_strdup(ctx, client_get_cur_dir());
1176 21 : if (!rname) {
1177 0 : return 1;
1178 : }
1179 :
1180 21 : if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
1181 0 : d_printf("get <filename> [localname]\n");
1182 0 : return 1;
1183 : }
1184 21 : rname = talloc_asprintf_append(rname, "%s", fname);
1185 21 : if (!rname) {
1186 0 : return 1;
1187 : }
1188 21 : rname = client_clean_name(ctx, rname);
1189 21 : if (!rname) {
1190 0 : return 1;
1191 : }
1192 :
1193 21 : next_token_talloc(ctx, &cmd_ptr,&lname,NULL);
1194 21 : if (!lname) {
1195 8 : lname = fname;
1196 : }
1197 :
1198 21 : return do_get(rname, lname, false);
1199 : }
1200 :
1201 : /****************************************************************************
1202 : Do an mget operation on one file.
1203 : ****************************************************************************/
1204 :
1205 0 : static NTSTATUS do_mget(struct cli_state *cli_state, struct file_info *finfo,
1206 : const char *dir)
1207 : {
1208 0 : TALLOC_CTX *ctx = talloc_tos();
1209 0 : const char *client_cwd = NULL;
1210 : size_t client_cwd_len;
1211 0 : char *path = NULL;
1212 0 : char *local_path = NULL;
1213 :
1214 0 : if (!finfo->name) {
1215 0 : return NT_STATUS_OK;
1216 : }
1217 :
1218 0 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
1219 0 : return NT_STATUS_OK;
1220 : }
1221 :
1222 0 : if ((finfo->attr & FILE_ATTRIBUTE_DIRECTORY) && !recurse) {
1223 0 : return NT_STATUS_OK;
1224 : }
1225 :
1226 0 : if (prompt) {
1227 0 : const char *object = (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) ?
1228 0 : "directory" : "file";
1229 0 : char *quest = NULL;
1230 : bool ok;
1231 :
1232 0 : quest = talloc_asprintf(
1233 : ctx, "Get %s %s? ", object, finfo->name);
1234 0 : if (quest == NULL) {
1235 0 : return NT_STATUS_NO_MEMORY;
1236 : }
1237 :
1238 0 : ok = yesno(quest);
1239 0 : TALLOC_FREE(quest);
1240 0 : if (!ok) {
1241 0 : return NT_STATUS_OK;
1242 : }
1243 : }
1244 :
1245 0 : path = talloc_asprintf(
1246 : ctx, "%s%c%s", dir, CLI_DIRSEP_CHAR, finfo->name);
1247 0 : if (path == NULL) {
1248 0 : return NT_STATUS_NO_MEMORY;
1249 : }
1250 0 : path = client_clean_name(ctx, path);
1251 0 : if (path == NULL) {
1252 0 : return NT_STATUS_NO_MEMORY;
1253 : }
1254 :
1255 : /*
1256 : * Skip the path prefix if we've done a remote "cd" when
1257 : * creating the local path
1258 : */
1259 0 : client_cwd = client_get_cur_dir();
1260 0 : client_cwd_len = strlen(client_cwd);
1261 :
1262 0 : local_path = talloc_strdup(ctx, path + client_cwd_len);
1263 0 : if (local_path == NULL) {
1264 0 : TALLOC_FREE(path);
1265 0 : return NT_STATUS_NO_MEMORY;
1266 : }
1267 0 : string_replace(local_path, CLI_DIRSEP_CHAR, '/');
1268 :
1269 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
1270 0 : int ret = mkdir(local_path, 0777);
1271 :
1272 0 : if ((ret == -1) && (errno != EEXIST)) {
1273 0 : return map_nt_error_from_unix(errno);
1274 : }
1275 : } else {
1276 0 : do_get(path, local_path, false);
1277 : }
1278 :
1279 0 : return NT_STATUS_OK;
1280 : }
1281 :
1282 : /****************************************************************************
1283 : View the file using the pager.
1284 : ****************************************************************************/
1285 :
1286 0 : static int cmd_more(void)
1287 : {
1288 0 : TALLOC_CTX *ctx = talloc_tos();
1289 0 : char *rname = NULL;
1290 0 : char *fname = NULL;
1291 0 : char *lname = NULL;
1292 0 : char *pager_cmd = NULL;
1293 : const char *pager;
1294 : int fd;
1295 0 : int rc = 0;
1296 : mode_t mask;
1297 :
1298 0 : rname = talloc_strdup(ctx, client_get_cur_dir());
1299 0 : if (!rname) {
1300 0 : return 1;
1301 : }
1302 :
1303 0 : lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
1304 0 : if (!lname) {
1305 0 : return 1;
1306 : }
1307 0 : mask = umask(S_IRWXO | S_IRWXG);
1308 0 : fd = mkstemp(lname);
1309 0 : umask(mask);
1310 0 : if (fd == -1) {
1311 0 : d_printf("failed to create temporary file for more\n");
1312 0 : return 1;
1313 : }
1314 0 : close(fd);
1315 :
1316 0 : if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
1317 0 : d_printf("more <filename>\n");
1318 0 : unlink(lname);
1319 0 : return 1;
1320 : }
1321 0 : rname = talloc_asprintf_append(rname, "%s", fname);
1322 0 : if (!rname) {
1323 0 : return 1;
1324 : }
1325 0 : rname = client_clean_name(ctx,rname);
1326 0 : if (!rname) {
1327 0 : return 1;
1328 : }
1329 :
1330 0 : rc = do_get(rname, lname, false);
1331 :
1332 0 : pager=getenv("PAGER");
1333 :
1334 0 : pager_cmd = talloc_asprintf(ctx,
1335 : "%s %s",
1336 : (pager? pager:PAGER),
1337 : lname);
1338 0 : if (!pager_cmd) {
1339 0 : return 1;
1340 : }
1341 0 : if (system(pager_cmd) == -1) {
1342 0 : d_printf("system command '%s' returned -1\n",
1343 : pager_cmd);
1344 : }
1345 0 : unlink(lname);
1346 :
1347 0 : return rc;
1348 : }
1349 :
1350 : /****************************************************************************
1351 : Do a mget command.
1352 : ****************************************************************************/
1353 :
1354 0 : static int cmd_mget(void)
1355 : {
1356 0 : TALLOC_CTX *ctx = talloc_tos();
1357 0 : uint32_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
1358 0 : char *mget_mask = NULL;
1359 0 : char *buf = NULL;
1360 0 : NTSTATUS status = NT_STATUS_OK;
1361 :
1362 0 : if (recurse) {
1363 0 : attribute |= FILE_ATTRIBUTE_DIRECTORY;
1364 : }
1365 :
1366 0 : while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1367 :
1368 0 : mget_mask = talloc_strdup(ctx, client_get_cur_dir());
1369 0 : if (!mget_mask) {
1370 0 : return 1;
1371 : }
1372 0 : if (*buf == CLI_DIRSEP_CHAR) {
1373 0 : mget_mask = talloc_strdup(ctx, buf);
1374 : } else {
1375 0 : mget_mask = talloc_asprintf_append(mget_mask,
1376 : "%s", buf);
1377 : }
1378 0 : if (!mget_mask) {
1379 0 : return 1;
1380 : }
1381 0 : mget_mask = client_clean_name(ctx, mget_mask);
1382 0 : if (mget_mask == NULL) {
1383 0 : return 1;
1384 : }
1385 0 : status = do_list(mget_mask, attribute, do_mget, recurse, true);
1386 0 : if (!NT_STATUS_IS_OK(status)) {
1387 0 : return 1;
1388 : }
1389 : }
1390 :
1391 0 : if (mget_mask == NULL) {
1392 0 : d_printf("nothing to mget\n");
1393 0 : return 0;
1394 : }
1395 :
1396 0 : if (!*mget_mask) {
1397 0 : mget_mask = talloc_asprintf(ctx,
1398 : "%s*",
1399 : client_get_cur_dir());
1400 0 : if (!mget_mask) {
1401 0 : return 1;
1402 : }
1403 0 : mget_mask = client_clean_name(ctx, mget_mask);
1404 0 : if (mget_mask == NULL) {
1405 0 : return 1;
1406 : }
1407 0 : status = do_list(mget_mask, attribute, do_mget, recurse, true);
1408 0 : if (!NT_STATUS_IS_OK(status)) {
1409 0 : return 1;
1410 : }
1411 : }
1412 :
1413 0 : return 0;
1414 : }
1415 :
1416 : /****************************************************************************
1417 : Make a directory of name "name".
1418 : ****************************************************************************/
1419 :
1420 92 : static bool do_mkdir(const char *name)
1421 : {
1422 92 : TALLOC_CTX *ctx = talloc_tos();
1423 : struct cli_state *targetcli;
1424 92 : char *targetname = NULL;
1425 92 : struct cli_credentials *creds = samba_cmdline_get_creds();
1426 : NTSTATUS status;
1427 :
1428 92 : status = cli_resolve_path(ctx, "",
1429 : creds,
1430 : cli, name, &targetcli, &targetname);
1431 92 : if (!NT_STATUS_IS_OK(status)) {
1432 0 : d_printf("mkdir %s: %s\n", name, nt_errstr(status));
1433 0 : return false;
1434 : }
1435 :
1436 92 : status = cli_mkdir(targetcli, targetname);
1437 92 : if (!NT_STATUS_IS_OK(status)) {
1438 0 : d_printf("%s making remote directory %s\n",
1439 : nt_errstr(status),name);
1440 0 : return false;
1441 : }
1442 :
1443 92 : return true;
1444 : }
1445 :
1446 : /****************************************************************************
1447 : Show 8.3 name of a file.
1448 : ****************************************************************************/
1449 :
1450 0 : static bool do_altname(const char *name)
1451 : {
1452 : fstring altname;
1453 : NTSTATUS status;
1454 :
1455 0 : status = cli_qpathinfo_alt_name(cli, name, altname);
1456 0 : if (!NT_STATUS_IS_OK(status)) {
1457 0 : d_printf("%s getting alt name for %s\n",
1458 : nt_errstr(status),name);
1459 0 : return false;
1460 : }
1461 0 : d_printf("%s\n", altname);
1462 :
1463 0 : return true;
1464 : }
1465 :
1466 : /****************************************************************************
1467 : Exit client.
1468 : ****************************************************************************/
1469 :
1470 498 : static int cmd_quit(void)
1471 : {
1472 498 : cli_shutdown(cli);
1473 498 : exit(0);
1474 : /* NOTREACHED */
1475 : return 0;
1476 : }
1477 :
1478 : /****************************************************************************
1479 : Make a directory.
1480 : ****************************************************************************/
1481 :
1482 92 : static int cmd_mkdir(void)
1483 : {
1484 92 : TALLOC_CTX *ctx = talloc_tos();
1485 92 : char *mask = NULL;
1486 92 : char *buf = NULL;
1487 92 : struct cli_credentials *creds = samba_cmdline_get_creds();
1488 : NTSTATUS status;
1489 :
1490 92 : mask = talloc_strdup(ctx, client_get_cur_dir());
1491 92 : if (!mask) {
1492 0 : return 1;
1493 : }
1494 :
1495 92 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1496 0 : if (!recurse) {
1497 0 : d_printf("mkdir <dirname>\n");
1498 : }
1499 0 : return 1;
1500 : }
1501 92 : mask = talloc_asprintf_append(mask, "%s", buf);
1502 92 : if (!mask) {
1503 0 : return 1;
1504 : }
1505 92 : mask = client_clean_name(ctx, mask);
1506 92 : if (mask == NULL) {
1507 0 : return 1;
1508 : }
1509 :
1510 92 : if (recurse) {
1511 0 : char *ddir = NULL;
1512 0 : char *ddir2 = NULL;
1513 : struct cli_state *targetcli;
1514 0 : char *targetname = NULL;
1515 0 : char *p = NULL;
1516 : char *saveptr;
1517 :
1518 0 : ddir2 = talloc_strdup(ctx, "");
1519 0 : if (!ddir2) {
1520 0 : return 1;
1521 : }
1522 :
1523 0 : status = cli_resolve_path(ctx, "",
1524 : creds,
1525 : cli, mask,
1526 : &targetcli, &targetname);
1527 0 : if (!NT_STATUS_IS_OK(status)) {
1528 0 : return 1;
1529 : }
1530 :
1531 0 : ddir = talloc_strdup(ctx, targetname);
1532 0 : if (!ddir) {
1533 0 : return 1;
1534 : }
1535 0 : trim_char(ddir,'.','\0');
1536 0 : p = strtok_r(ddir, "/\\", &saveptr);
1537 0 : while (p) {
1538 0 : ddir2 = talloc_asprintf_append(ddir2, "%s", p);
1539 0 : if (!ddir2) {
1540 0 : return 1;
1541 : }
1542 0 : if (!NT_STATUS_IS_OK(cli_chkpath(targetcli, ddir2))) {
1543 0 : do_mkdir(ddir2);
1544 : }
1545 0 : ddir2 = talloc_asprintf_append(ddir2, "%s", CLI_DIRSEP_STR);
1546 0 : if (!ddir2) {
1547 0 : return 1;
1548 : }
1549 0 : p = strtok_r(NULL, "/\\", &saveptr);
1550 : }
1551 : } else {
1552 92 : do_mkdir(mask);
1553 : }
1554 :
1555 92 : return 0;
1556 : }
1557 :
1558 : /****************************************************************************
1559 : Show alt name.
1560 : ****************************************************************************/
1561 :
1562 0 : static int cmd_altname(void)
1563 : {
1564 0 : TALLOC_CTX *ctx = talloc_tos();
1565 : char *name;
1566 : char *buf;
1567 :
1568 0 : name = talloc_strdup(ctx, client_get_cur_dir());
1569 0 : if (!name) {
1570 0 : return 1;
1571 : }
1572 :
1573 0 : if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
1574 0 : d_printf("altname <file>\n");
1575 0 : return 1;
1576 : }
1577 0 : name = talloc_asprintf_append(name, "%s", buf);
1578 0 : if (!name) {
1579 0 : return 1;
1580 : }
1581 0 : name = client_clean_name(ctx, name);
1582 0 : if (name == NULL) {
1583 0 : return 1;
1584 : }
1585 0 : do_altname(name);
1586 0 : return 0;
1587 : }
1588 :
1589 52 : static char *attr_str(TALLOC_CTX *mem_ctx, uint32_t attr)
1590 : {
1591 52 : char *attrs = talloc_zero_array(mem_ctx, char, 17);
1592 52 : int i = 0;
1593 :
1594 52 : if (!(attr & FILE_ATTRIBUTE_NORMAL)) {
1595 40 : if (attr & FILE_ATTRIBUTE_ENCRYPTED) {
1596 0 : attrs[i++] = 'E';
1597 : }
1598 40 : if (attr & FILE_ATTRIBUTE_NONINDEXED) {
1599 0 : attrs[i++] = 'N';
1600 : }
1601 40 : if (attr & FILE_ATTRIBUTE_OFFLINE) {
1602 0 : attrs[i++] = 'O';
1603 : }
1604 40 : if (attr & FILE_ATTRIBUTE_COMPRESSED) {
1605 0 : attrs[i++] = 'C';
1606 : }
1607 40 : if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
1608 0 : attrs[i++] = 'r';
1609 : }
1610 40 : if (attr & FILE_ATTRIBUTE_SPARSE) {
1611 0 : attrs[i++] = 's';
1612 : }
1613 40 : if (attr & FILE_ATTRIBUTE_TEMPORARY) {
1614 0 : attrs[i++] = 'T';
1615 : }
1616 40 : if (attr & FILE_ATTRIBUTE_NORMAL) {
1617 0 : attrs[i++] = 'N';
1618 : }
1619 40 : if (attr & FILE_ATTRIBUTE_READONLY) {
1620 4 : attrs[i++] = 'R';
1621 : }
1622 40 : if (attr & FILE_ATTRIBUTE_HIDDEN) {
1623 4 : attrs[i++] = 'H';
1624 : }
1625 40 : if (attr & FILE_ATTRIBUTE_SYSTEM) {
1626 4 : attrs[i++] = 'S';
1627 : }
1628 40 : if (attr & FILE_ATTRIBUTE_DIRECTORY) {
1629 16 : attrs[i++] = 'D';
1630 : }
1631 40 : if (attr & FILE_ATTRIBUTE_ARCHIVE) {
1632 32 : attrs[i++] = 'A';
1633 : }
1634 : }
1635 52 : return attrs;
1636 : }
1637 :
1638 : /****************************************************************************
1639 : Show all info we can get
1640 : ****************************************************************************/
1641 :
1642 56 : static int do_allinfo(const char *name)
1643 : {
1644 : fstring altname;
1645 : struct timespec b_time, a_time, m_time, c_time;
1646 : off_t size;
1647 : uint32_t attr;
1648 : NTTIME tmp;
1649 : uint16_t fnum;
1650 : unsigned int num_streams;
1651 : struct stream_struct *streams;
1652 : int j, num_snapshots;
1653 56 : char **snapshots = NULL;
1654 : unsigned int i;
1655 : NTSTATUS status;
1656 :
1657 56 : status = cli_qpathinfo_alt_name(cli, name, altname);
1658 56 : if (!NT_STATUS_IS_OK(status)) {
1659 4 : d_printf("%s getting alt name for %s\n", nt_errstr(status),
1660 : name);
1661 : /*
1662 : * Ignore not supported or not implemented, it does not
1663 : * hurt if we can't list alternate names.
1664 : */
1665 6 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
1666 4 : NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1667 0 : altname[0] = '\0';
1668 : } else {
1669 4 : return false;
1670 : }
1671 : }
1672 52 : d_printf("altname: %s\n", altname);
1673 :
1674 52 : status = cli_qpathinfo3(cli, name, &b_time, &a_time, &m_time, &c_time,
1675 : &size, &attr, NULL);
1676 52 : if (!NT_STATUS_IS_OK(status)) {
1677 0 : d_printf("%s getting pathinfo for %s\n", nt_errstr(status),
1678 : name);
1679 0 : return false;
1680 : }
1681 :
1682 52 : tmp = full_timespec_to_nt_time(&b_time);
1683 52 : d_printf("create_time: %s\n", nt_time_string(talloc_tos(), tmp));
1684 :
1685 52 : tmp = full_timespec_to_nt_time(&a_time);
1686 52 : d_printf("access_time: %s\n", nt_time_string(talloc_tos(), tmp));
1687 :
1688 52 : tmp = full_timespec_to_nt_time(&m_time);
1689 52 : d_printf("write_time: %s\n", nt_time_string(talloc_tos(), tmp));
1690 :
1691 52 : tmp = full_timespec_to_nt_time(&c_time);
1692 52 : d_printf("change_time: %s\n", nt_time_string(talloc_tos(), tmp));
1693 :
1694 52 : d_printf("attributes: %s (%x)\n", attr_str(talloc_tos(), attr), attr);
1695 :
1696 52 : status = cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
1697 : &streams);
1698 52 : if (!NT_STATUS_IS_OK(status)) {
1699 8 : d_printf("%s getting streams for %s\n", nt_errstr(status),
1700 : name);
1701 8 : return false;
1702 : }
1703 :
1704 80 : for (i=0; i<num_streams; i++) {
1705 36 : d_printf("stream: [%s], %lld bytes\n", streams[i].name,
1706 36 : (unsigned long long)streams[i].size);
1707 : }
1708 :
1709 44 : if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
1710 : char *subst, *print;
1711 : uint32_t flags;
1712 :
1713 0 : status = cli_readlink(cli, name, talloc_tos(), &subst, &print,
1714 : &flags);
1715 0 : if (!NT_STATUS_IS_OK(status)) {
1716 0 : d_fprintf(stderr, "cli_readlink returned %s\n",
1717 : nt_errstr(status));
1718 : } else {
1719 0 : d_printf("symlink: subst=[%s], print=[%s], flags=%x\n",
1720 : subst, print, flags);
1721 0 : TALLOC_FREE(subst);
1722 0 : TALLOC_FREE(print);
1723 : }
1724 : }
1725 :
1726 44 : status = cli_ntcreate(cli, name, 0,
1727 : SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE |
1728 : SEC_STD_SYNCHRONIZE, 0,
1729 : FILE_SHARE_READ|FILE_SHARE_WRITE
1730 : |FILE_SHARE_DELETE,
1731 : FILE_OPEN, 0x0, 0x0, &fnum, NULL);
1732 44 : if (!NT_STATUS_IS_OK(status)) {
1733 : /*
1734 : * Ignore failure, it does not hurt if we can't list
1735 : * snapshots
1736 : */
1737 0 : return 0;
1738 : }
1739 : /*
1740 : * In order to get shadow copy data over SMB1 we
1741 : * must call twice, once with 'get_names = false'
1742 : * to get the size, then again with 'get_names = true'
1743 : * to get the data or a Windows server fails to return
1744 : * valid info. Samba doesn't have this bug. JRA.
1745 : */
1746 :
1747 44 : status = cli_shadow_copy_data(talloc_tos(), cli, fnum,
1748 : false, &snapshots, &num_snapshots);
1749 44 : if (!NT_STATUS_IS_OK(status)) {
1750 44 : cli_close(cli, fnum);
1751 44 : return 0;
1752 : }
1753 0 : status = cli_shadow_copy_data(talloc_tos(), cli, fnum,
1754 : true, &snapshots, &num_snapshots);
1755 0 : if (!NT_STATUS_IS_OK(status)) {
1756 0 : cli_close(cli, fnum);
1757 0 : return 0;
1758 : }
1759 :
1760 0 : for (j=0; j<num_snapshots; j++) {
1761 : char *snap_name;
1762 :
1763 0 : d_printf("%s\n", snapshots[j]);
1764 0 : snap_name = talloc_asprintf(talloc_tos(), "%s%s",
1765 0 : snapshots[j], name);
1766 0 : status = cli_qpathinfo3(cli, snap_name, &b_time, &a_time,
1767 : &m_time, &c_time, &size,
1768 : NULL, NULL);
1769 0 : if (!NT_STATUS_IS_OK(status)) {
1770 0 : d_fprintf(stderr, "pathinfo(%s) failed: %s\n",
1771 : snap_name, nt_errstr(status));
1772 0 : TALLOC_FREE(snap_name);
1773 0 : continue;
1774 : }
1775 0 : tmp = unix_timespec_to_nt_time(b_time);
1776 0 : d_printf("create_time: %s\n", nt_time_string(talloc_tos(), tmp));
1777 0 : tmp = unix_timespec_to_nt_time(a_time);
1778 0 : d_printf("access_time: %s\n", nt_time_string(talloc_tos(), tmp));
1779 0 : tmp =unix_timespec_to_nt_time(m_time);
1780 0 : d_printf("write_time: %s\n", nt_time_string(talloc_tos(), tmp));
1781 0 : tmp = unix_timespec_to_nt_time(c_time);
1782 0 : d_printf("change_time: %s\n", nt_time_string(talloc_tos(), tmp));
1783 0 : d_printf("size: %d\n", (int)size);
1784 : }
1785 :
1786 0 : TALLOC_FREE(snapshots);
1787 0 : cli_close(cli, fnum);
1788 :
1789 0 : return 0;
1790 : }
1791 :
1792 : /****************************************************************************
1793 : Show all info we can get
1794 : ****************************************************************************/
1795 :
1796 56 : static int cmd_allinfo(void)
1797 : {
1798 56 : TALLOC_CTX *ctx = talloc_tos();
1799 : char *name;
1800 : char *buf;
1801 :
1802 56 : name = talloc_strdup(ctx, client_get_cur_dir());
1803 56 : if (!name) {
1804 0 : return 1;
1805 : }
1806 :
1807 56 : if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
1808 0 : d_printf("allinfo <file>\n");
1809 0 : return 1;
1810 : }
1811 56 : name = talloc_asprintf_append(name, "%s", buf);
1812 56 : if (!name) {
1813 0 : return 1;
1814 : }
1815 56 : name = client_clean_name(ctx, name);
1816 56 : if (name == NULL) {
1817 0 : return 1;
1818 : }
1819 56 : do_allinfo(name);
1820 :
1821 56 : return 0;
1822 : }
1823 :
1824 : /****************************************************************************
1825 : Put a single file.
1826 : ****************************************************************************/
1827 :
1828 89 : static int do_put(const char *rname, const char *lname, bool reput)
1829 : {
1830 89 : TALLOC_CTX *ctx = talloc_tos();
1831 : uint16_t fnum;
1832 : FILE *f;
1833 89 : off_t start = 0;
1834 89 : int rc = 0;
1835 : struct timespec tp_start;
1836 : struct cli_state *targetcli;
1837 89 : char *targetname = NULL;
1838 : struct push_state state;
1839 89 : struct cli_credentials *creds = samba_cmdline_get_creds();
1840 : NTSTATUS status;
1841 :
1842 89 : status = cli_resolve_path(ctx, "",
1843 : creds,
1844 : cli, rname, &targetcli, &targetname);
1845 89 : if (!NT_STATUS_IS_OK(status)) {
1846 0 : d_printf("Failed to open %s: %s\n", rname, nt_errstr(status));
1847 0 : return 1;
1848 : }
1849 :
1850 89 : clock_gettime_mono(&tp_start);
1851 :
1852 89 : if (reput) {
1853 0 : status = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
1854 0 : if (NT_STATUS_IS_OK(status)) {
1855 0 : if (!NT_STATUS_IS_OK(status = cli_qfileinfo_basic(
1856 : targetcli, fnum, NULL,
1857 : &start, NULL, NULL,
1858 : NULL, NULL, NULL))) {
1859 0 : d_printf("getattrib: %s\n", nt_errstr(status));
1860 0 : return 1;
1861 : }
1862 : }
1863 : } else {
1864 89 : status = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
1865 : }
1866 :
1867 89 : if (!NT_STATUS_IS_OK(status)) {
1868 4 : d_printf("%s opening remote file %s\n", nt_errstr(status),
1869 : rname);
1870 4 : return 1;
1871 : }
1872 :
1873 : /* allow files to be piped into smbclient
1874 : jdblair 24.jun.98
1875 :
1876 : Note that in this case this function will exit(0) rather
1877 : than returning. */
1878 85 : if (!strcmp(lname, "-")) {
1879 0 : f = stdin;
1880 : /* size of file is not known */
1881 : } else {
1882 85 : f = fopen(lname, "r");
1883 85 : if (f && reput) {
1884 0 : if (fseek(f, start, SEEK_SET) == -1) {
1885 0 : d_printf("Error seeking local file\n");
1886 0 : fclose(f);
1887 0 : return 1;
1888 : }
1889 : }
1890 : }
1891 :
1892 85 : if (!f) {
1893 0 : d_printf("Error opening local file %s\n",lname);
1894 0 : return 1;
1895 : }
1896 :
1897 85 : DEBUG(1,("putting file %s as %s ",lname,
1898 : rname));
1899 :
1900 85 : setvbuf(f, NULL, _IOFBF, io_bufsize);
1901 :
1902 85 : state.f = f;
1903 85 : state.nread = 0;
1904 :
1905 85 : status = cli_push(targetcli, fnum, 0, 0, io_bufsize, push_source,
1906 : &state);
1907 85 : if (!NT_STATUS_IS_OK(status)) {
1908 0 : d_fprintf(stderr, "cli_push returned %s\n", nt_errstr(status));
1909 0 : rc = 1;
1910 : }
1911 :
1912 85 : status = cli_close(targetcli, fnum);
1913 85 : if (!NT_STATUS_IS_OK(status)) {
1914 0 : d_printf("%s closing remote file %s\n", nt_errstr(status),
1915 : rname);
1916 0 : if (f != stdin) {
1917 0 : fclose(f);
1918 : }
1919 0 : return 1;
1920 : }
1921 :
1922 85 : if (f != stdin) {
1923 85 : fclose(f);
1924 : }
1925 :
1926 : {
1927 : struct timespec tp_end;
1928 : int this_time;
1929 :
1930 85 : clock_gettime_mono(&tp_end);
1931 85 : this_time = nsec_time_diff(&tp_end,&tp_start)/1000000;
1932 85 : put_total_time_ms += this_time;
1933 85 : put_total_size += state.nread;
1934 :
1935 85 : DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
1936 : state.nread / (1.024*this_time + 1.0e-4),
1937 : put_total_size / (1.024*put_total_time_ms)));
1938 : }
1939 :
1940 85 : if (f == stdin) {
1941 0 : cli_shutdown(cli);
1942 0 : exit(rc);
1943 : }
1944 :
1945 85 : return rc;
1946 : }
1947 :
1948 : /****************************************************************************
1949 : Put a file.
1950 : ****************************************************************************/
1951 :
1952 89 : static int cmd_put(void)
1953 : {
1954 89 : TALLOC_CTX *ctx = talloc_tos();
1955 : char *lname;
1956 : char *rname;
1957 : char *buf;
1958 :
1959 89 : rname = talloc_strdup(ctx, client_get_cur_dir());
1960 89 : if (!rname) {
1961 0 : return 1;
1962 : }
1963 :
1964 89 : if (!next_token_talloc(ctx, &cmd_ptr,&lname,NULL)) {
1965 0 : d_printf("put <filename>\n");
1966 0 : return 1;
1967 : }
1968 :
1969 89 : if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1970 45 : rname = talloc_asprintf_append(rname, "%s", buf);
1971 : } else {
1972 44 : rname = talloc_asprintf_append(rname, "%s", lname);
1973 : }
1974 89 : if (!rname) {
1975 0 : return 1;
1976 : }
1977 :
1978 89 : rname = client_clean_name(ctx, rname);
1979 89 : if (!rname) {
1980 0 : return 1;
1981 : }
1982 :
1983 : {
1984 : SMB_STRUCT_STAT st;
1985 : /* allow '-' to represent stdin
1986 : jdblair, 24.jun.98 */
1987 89 : if (!file_exist_stat(lname, &st, false) &&
1988 0 : (strcmp(lname,"-"))) {
1989 0 : d_printf("%s does not exist\n",lname);
1990 0 : return 1;
1991 : }
1992 : }
1993 :
1994 89 : return do_put(rname, lname, false);
1995 : }
1996 :
1997 : /*************************************
1998 : File list structure.
1999 : *************************************/
2000 :
2001 : static struct file_list {
2002 : struct file_list *prev, *next;
2003 : char *file_path;
2004 : bool isdir;
2005 : } *file_list;
2006 :
2007 : /****************************************************************************
2008 : Free a file_list structure.
2009 : ****************************************************************************/
2010 :
2011 120 : static void free_file_list (struct file_list *l_head)
2012 : {
2013 : struct file_list *list, *next;
2014 :
2015 244 : for (list = l_head; list; list = next) {
2016 124 : next = list->next;
2017 124 : DLIST_REMOVE(l_head, list);
2018 124 : TALLOC_FREE(list);
2019 : }
2020 120 : }
2021 :
2022 : /****************************************************************************
2023 : Seek in a directory/file list until you get something that doesn't start with
2024 : the specified name.
2025 : ****************************************************************************/
2026 :
2027 0 : static bool seek_list(struct file_list *list, char *name)
2028 : {
2029 0 : while (list) {
2030 0 : trim_string(list->file_path,"./","\n");
2031 0 : if (strncmp(list->file_path, name, strlen(name)) != 0) {
2032 0 : return true;
2033 : }
2034 0 : list = list->next;
2035 : }
2036 :
2037 0 : return false;
2038 : }
2039 :
2040 : /****************************************************************************
2041 : Set the file selection mask.
2042 : ****************************************************************************/
2043 :
2044 0 : static int cmd_select(void)
2045 : {
2046 0 : TALLOC_CTX *ctx = talloc_tos();
2047 0 : char *new_fs = NULL;
2048 0 : next_token_talloc(ctx, &cmd_ptr,&new_fs,NULL)
2049 : ;
2050 0 : if (new_fs) {
2051 0 : client_set_fileselection(new_fs);
2052 : } else {
2053 0 : client_set_fileselection("");
2054 : }
2055 0 : return 0;
2056 : }
2057 :
2058 : /****************************************************************************
2059 : Recursive file matching function act as find
2060 : match must be always set to true when calling this function
2061 : ****************************************************************************/
2062 :
2063 0 : static int file_find(TALLOC_CTX *ctx,
2064 : struct file_list **list,
2065 : const char *directory,
2066 : const char *expression,
2067 : bool match)
2068 : {
2069 : DIR *dir;
2070 : struct file_list *entry;
2071 : struct stat statbuf;
2072 : int ret;
2073 : char *path;
2074 : bool isdir;
2075 : const char *dname;
2076 :
2077 0 : dir = opendir(directory);
2078 0 : if (!dir)
2079 0 : return -1;
2080 :
2081 0 : while ((dname = readdirname(dir))) {
2082 0 : if (ISDOT(dname) || ISDOTDOT(dname)) {
2083 0 : continue;
2084 : }
2085 :
2086 0 : path = talloc_asprintf(ctx, "%s/%s", directory, dname);
2087 0 : if (path == NULL) {
2088 0 : continue;
2089 : }
2090 :
2091 0 : isdir = false;
2092 0 : if (!match || !gen_fnmatch(expression, dname)) {
2093 0 : if (recurse) {
2094 0 : ret = stat(path, &statbuf);
2095 0 : if (ret == 0) {
2096 0 : if (S_ISDIR(statbuf.st_mode)) {
2097 0 : isdir = true;
2098 0 : ret = file_find(ctx,
2099 : list,
2100 : path,
2101 : expression,
2102 : false);
2103 : }
2104 : } else {
2105 0 : d_printf("file_find: cannot stat file %s\n", path);
2106 : }
2107 :
2108 0 : if (ret == -1) {
2109 0 : TALLOC_FREE(path);
2110 0 : closedir(dir);
2111 0 : return -1;
2112 : }
2113 : }
2114 0 : entry = talloc_zero(ctx, struct file_list);
2115 0 : if (!entry) {
2116 0 : d_printf("Out of memory in file_find\n");
2117 0 : closedir(dir);
2118 0 : return -1;
2119 : }
2120 0 : entry->file_path = talloc_move(entry, &path);
2121 0 : entry->isdir = isdir;
2122 0 : DLIST_ADD(*list, entry);
2123 : } else {
2124 0 : TALLOC_FREE(path);
2125 : }
2126 : }
2127 :
2128 0 : closedir(dir);
2129 0 : return 0;
2130 : }
2131 :
2132 : /****************************************************************************
2133 : mput some files.
2134 : ****************************************************************************/
2135 :
2136 0 : static int cmd_mput(void)
2137 : {
2138 0 : TALLOC_CTX *ctx = talloc_tos();
2139 0 : char *p = NULL;
2140 :
2141 0 : while (next_token_talloc(ctx, &cmd_ptr,&p,NULL)) {
2142 : int ret;
2143 : struct file_list *temp_list;
2144 : char *quest, *lname, *rname;
2145 :
2146 0 : file_list = NULL;
2147 :
2148 0 : ret = file_find(ctx, &file_list, ".", p, true);
2149 0 : if (ret) {
2150 0 : free_file_list(file_list);
2151 0 : continue;
2152 : }
2153 :
2154 0 : quest = NULL;
2155 0 : lname = NULL;
2156 0 : rname = NULL;
2157 :
2158 0 : for (temp_list = file_list; temp_list;
2159 0 : temp_list = temp_list->next) {
2160 :
2161 0 : SAFE_FREE(lname);
2162 0 : if (asprintf(&lname, "%s/", temp_list->file_path) <= 0) {
2163 0 : continue;
2164 : }
2165 0 : trim_string(lname, "./", "/");
2166 :
2167 : /* check if it's a directory */
2168 0 : if (temp_list->isdir) {
2169 : /* if (!recurse) continue; */
2170 :
2171 0 : SAFE_FREE(quest);
2172 0 : if (asprintf(&quest, "Put directory %s? ", lname) < 0) {
2173 0 : break;
2174 : }
2175 0 : if (prompt && !yesno(quest)) { /* No */
2176 : /* Skip the directory */
2177 0 : lname[strlen(lname)-1] = '/';
2178 0 : if (!seek_list(temp_list, lname))
2179 0 : break;
2180 : } else { /* Yes */
2181 0 : SAFE_FREE(rname);
2182 0 : if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
2183 0 : break;
2184 : }
2185 0 : normalize_name(rname);
2186 : {
2187 0 : char *tmp_rname =
2188 0 : client_clean_name(ctx, rname);
2189 0 : if (tmp_rname == NULL) {
2190 0 : break;
2191 : }
2192 0 : SAFE_FREE(rname);
2193 0 : rname = smb_xstrdup(tmp_rname);
2194 0 : TALLOC_FREE(tmp_rname);
2195 0 : if (rname == NULL) {
2196 0 : break;
2197 : }
2198 : }
2199 0 : if (!NT_STATUS_IS_OK(cli_chkpath(cli, rname)) &&
2200 0 : !do_mkdir(rname)) {
2201 0 : DEBUG (0, ("Unable to make dir, skipping..."));
2202 : /* Skip the directory */
2203 0 : lname[strlen(lname)-1] = '/';
2204 0 : if (!seek_list(temp_list, lname)) {
2205 0 : break;
2206 : }
2207 : }
2208 : }
2209 0 : continue;
2210 : } else {
2211 0 : SAFE_FREE(quest);
2212 0 : if (asprintf(&quest,"Put file %s? ", lname) < 0) {
2213 0 : break;
2214 : }
2215 0 : if (prompt && !yesno(quest)) {
2216 : /* No */
2217 0 : continue;
2218 : }
2219 :
2220 : /* Yes */
2221 0 : SAFE_FREE(rname);
2222 0 : if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
2223 0 : break;
2224 : }
2225 : }
2226 :
2227 0 : normalize_name(rname);
2228 :
2229 : {
2230 0 : char *tmp_rname = client_clean_name(ctx, rname);
2231 0 : if (tmp_rname == NULL) {
2232 0 : break;
2233 : }
2234 0 : SAFE_FREE(rname);
2235 0 : rname = smb_xstrdup(tmp_rname);
2236 0 : TALLOC_FREE(tmp_rname);
2237 0 : if (rname == NULL) {
2238 0 : break;
2239 : }
2240 : }
2241 0 : do_put(rname, lname, false);
2242 : }
2243 0 : free_file_list(file_list);
2244 0 : SAFE_FREE(quest);
2245 0 : SAFE_FREE(lname);
2246 0 : SAFE_FREE(rname);
2247 : }
2248 :
2249 0 : return 0;
2250 : }
2251 :
2252 : /****************************************************************************
2253 : Cancel a print job.
2254 : ****************************************************************************/
2255 :
2256 0 : static int do_cancel(int job)
2257 : {
2258 0 : if (cli_printjob_del(cli, job)) {
2259 0 : d_printf("Job %d cancelled\n",job);
2260 0 : return 0;
2261 : } else {
2262 0 : NTSTATUS status = cli_nt_error(cli);
2263 0 : d_printf("Error cancelling job %d : %s\n",
2264 : job, nt_errstr(status));
2265 0 : return 1;
2266 : }
2267 : }
2268 :
2269 : /****************************************************************************
2270 : Cancel a print job.
2271 : ****************************************************************************/
2272 :
2273 0 : static int cmd_cancel(void)
2274 : {
2275 0 : TALLOC_CTX *ctx = talloc_tos();
2276 0 : char *buf = NULL;
2277 : int job;
2278 :
2279 0 : if (!next_token_talloc(ctx, &cmd_ptr, &buf,NULL)) {
2280 0 : d_printf("cancel <jobid> ...\n");
2281 0 : return 1;
2282 : }
2283 : do {
2284 0 : job = atoi(buf);
2285 0 : do_cancel(job);
2286 0 : } while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL));
2287 :
2288 0 : return 0;
2289 : }
2290 :
2291 : /****************************************************************************
2292 : Print a file.
2293 : ****************************************************************************/
2294 :
2295 0 : static int cmd_print(void)
2296 : {
2297 0 : TALLOC_CTX *ctx = talloc_tos();
2298 0 : char *lname = NULL;
2299 0 : char *rname = NULL;
2300 0 : char *p = NULL;
2301 :
2302 0 : if (!next_token_talloc(ctx, &cmd_ptr, &lname,NULL)) {
2303 0 : d_printf("print <filename>\n");
2304 0 : return 1;
2305 : }
2306 :
2307 0 : rname = talloc_strdup(ctx, lname);
2308 0 : if (!rname) {
2309 0 : return 1;
2310 : }
2311 0 : p = strrchr_m(rname,'/');
2312 0 : if (p) {
2313 0 : rname = talloc_asprintf(ctx,
2314 : "%s-%d",
2315 : p+1,
2316 0 : (int)getpid());
2317 : }
2318 0 : if (strequal(lname,"-")) {
2319 0 : rname = talloc_asprintf(ctx,
2320 : "stdin-%d",
2321 0 : (int)getpid());
2322 : }
2323 0 : if (!rname) {
2324 0 : return 1;
2325 : }
2326 :
2327 0 : return do_put(rname, lname, false);
2328 : }
2329 :
2330 : /****************************************************************************
2331 : Show a print queue entry.
2332 : ****************************************************************************/
2333 :
2334 0 : static void queue_fn(struct print_job_info *p)
2335 : {
2336 0 : d_printf("%-6d %-9d %s\n", (int)p->id, (int)p->size, p->name);
2337 0 : }
2338 :
2339 : /****************************************************************************
2340 : Show a print queue.
2341 : ****************************************************************************/
2342 :
2343 0 : static int cmd_queue(void)
2344 : {
2345 0 : cli_print_queue(cli, queue_fn);
2346 0 : return 0;
2347 : }
2348 :
2349 : /****************************************************************************
2350 : Delete some files.
2351 : ****************************************************************************/
2352 :
2353 41 : static NTSTATUS do_del(struct cli_state *cli_state, struct file_info *finfo,
2354 : const char *dir)
2355 : {
2356 41 : TALLOC_CTX *ctx = talloc_tos();
2357 41 : char *mask = NULL;
2358 41 : struct cli_state *targetcli = NULL;
2359 41 : char *targetname = NULL;
2360 41 : struct cli_credentials *creds = samba_cmdline_get_creds();
2361 : NTSTATUS status;
2362 :
2363 41 : mask = talloc_asprintf(ctx,
2364 : "%s%c%s",
2365 : dir,
2366 : CLI_DIRSEP_CHAR,
2367 : finfo->name);
2368 41 : if (!mask) {
2369 0 : return NT_STATUS_NO_MEMORY;
2370 : }
2371 :
2372 41 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
2373 0 : TALLOC_FREE(mask);
2374 0 : return NT_STATUS_OK;
2375 : }
2376 :
2377 41 : status = cli_resolve_path(ctx, "",
2378 : creds,
2379 : cli, mask, &targetcli, &targetname);
2380 41 : if (!NT_STATUS_IS_OK(status)) {
2381 0 : goto out;
2382 : }
2383 :
2384 41 : status = cli_unlink(targetcli, targetname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2385 41 : out:
2386 41 : if (!NT_STATUS_IS_OK(status)) {
2387 0 : d_printf("%s deleting remote file %s\n",
2388 : nt_errstr(status), mask);
2389 : }
2390 41 : TALLOC_FREE(mask);
2391 41 : return status;
2392 : }
2393 :
2394 : /****************************************************************************
2395 : Delete some files.
2396 : ****************************************************************************/
2397 :
2398 57 : static int cmd_del(void)
2399 : {
2400 57 : TALLOC_CTX *ctx = talloc_tos();
2401 57 : char *mask = NULL;
2402 57 : char *buf = NULL;
2403 57 : NTSTATUS status = NT_STATUS_OK;
2404 57 : uint32_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
2405 :
2406 57 : if (recurse) {
2407 0 : attribute |= FILE_ATTRIBUTE_DIRECTORY;
2408 : }
2409 :
2410 57 : mask = talloc_strdup(ctx, client_get_cur_dir());
2411 57 : if (!mask) {
2412 0 : return 1;
2413 : }
2414 57 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2415 0 : d_printf("del <filename>\n");
2416 0 : return 1;
2417 : }
2418 57 : mask = talloc_asprintf_append(mask, "%s", buf);
2419 57 : if (!mask) {
2420 0 : return 1;
2421 : }
2422 57 : mask = client_clean_name(ctx, mask);
2423 57 : if (mask == NULL) {
2424 0 : return 1;
2425 : }
2426 :
2427 57 : status = do_list(mask,attribute,do_del,false,false);
2428 57 : if (!NT_STATUS_IS_OK(status)) {
2429 16 : return 1;
2430 : }
2431 41 : return 0;
2432 : }
2433 :
2434 : /****************************************************************************
2435 : Delete some files.
2436 : ****************************************************************************/
2437 :
2438 32 : static NTSTATUS delete_remote_files_list(struct cli_state *cli_state,
2439 : struct file_list *flist)
2440 : {
2441 32 : NTSTATUS status = NT_STATUS_OK;
2442 32 : struct file_list *deltree_list_iter = NULL;
2443 32 : char *targetname = NULL;
2444 32 : struct cli_state *targetcli = NULL;
2445 32 : struct cli_credentials *creds = samba_cmdline_get_creds();
2446 32 : TALLOC_CTX *ctx = talloc_tos();
2447 :
2448 94 : for (deltree_list_iter = flist;
2449 62 : deltree_list_iter != NULL;
2450 92 : deltree_list_iter = deltree_list_iter->next) {
2451 92 : status = cli_resolve_path(ctx,
2452 : "",
2453 : creds,
2454 : cli_state,
2455 92 : deltree_list_iter->file_path,
2456 : &targetcli,
2457 : &targetname);
2458 92 : if (!NT_STATUS_IS_OK(status)) {
2459 0 : d_printf("delete_remote_files %s: %s\n",
2460 : deltree_list_iter->file_path,
2461 : nt_errstr(status));
2462 0 : return status;
2463 : }
2464 92 : if (CLI_DIRSEP_CHAR == '/') {
2465 : /* POSIX. */
2466 0 : status = cli_posix_unlink(targetcli,
2467 : targetname);
2468 92 : } else if (deltree_list_iter->isdir) {
2469 72 : status = cli_rmdir(targetcli,
2470 : targetname);
2471 : } else {
2472 20 : status = cli_unlink(targetcli,
2473 : targetname,
2474 : FILE_ATTRIBUTE_SYSTEM |
2475 : FILE_ATTRIBUTE_HIDDEN);
2476 : }
2477 92 : if (!NT_STATUS_IS_OK(status)) {
2478 0 : d_printf("%s deleting remote %s %s\n",
2479 : nt_errstr(status),
2480 0 : deltree_list_iter->isdir ?
2481 : "directory" : "file",
2482 : deltree_list_iter->file_path);
2483 0 : return status;
2484 : }
2485 : }
2486 32 : return NT_STATUS_OK;
2487 : }
2488 :
2489 : /****************************************************************************
2490 : Save a list of files to delete.
2491 : ****************************************************************************/
2492 :
2493 : static struct file_list *deltree_list_head;
2494 :
2495 268 : static NTSTATUS do_deltree_list(struct cli_state *cli_state,
2496 : struct file_info *finfo,
2497 : const char *dir)
2498 : {
2499 268 : struct file_list **file_list_head_pp = &deltree_list_head;
2500 268 : struct file_list *dt = NULL;
2501 :
2502 268 : if (!do_this_one(finfo)) {
2503 0 : return NT_STATUS_OK;
2504 : }
2505 :
2506 : /* skip if this is . or .. */
2507 268 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
2508 144 : return NT_STATUS_OK;
2509 : }
2510 :
2511 124 : dt = talloc_zero(NULL, struct file_list);
2512 124 : if (dt == NULL) {
2513 0 : return NT_STATUS_NO_MEMORY;
2514 : }
2515 :
2516 : /* create absolute filename for cli_ntcreate() */
2517 124 : dt->file_path = talloc_asprintf(dt,
2518 : "%s%s%s",
2519 : dir,
2520 : CLI_DIRSEP_STR,
2521 : finfo->name);
2522 124 : if (dt->file_path == NULL) {
2523 0 : TALLOC_FREE(dt);
2524 0 : return NT_STATUS_NO_MEMORY;
2525 : }
2526 :
2527 124 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
2528 104 : dt->isdir = true;
2529 : }
2530 :
2531 124 : DLIST_ADD(*file_list_head_pp, dt);
2532 124 : return NT_STATUS_OK;
2533 : }
2534 :
2535 44 : static int cmd_deltree(void)
2536 : {
2537 44 : TALLOC_CTX *ctx = talloc_tos();
2538 44 : char *buf = NULL;
2539 44 : NTSTATUS status = NT_STATUS_OK;
2540 44 : struct file_list *deltree_list_norecurse = NULL;
2541 44 : struct file_list *deltree_list_iter = NULL;
2542 44 : uint32_t attribute = FILE_ATTRIBUTE_SYSTEM |
2543 : FILE_ATTRIBUTE_HIDDEN |
2544 : FILE_ATTRIBUTE_DIRECTORY;
2545 : bool ok;
2546 44 : char *mask = talloc_strdup(ctx, client_get_cur_dir());
2547 44 : if (mask == NULL) {
2548 0 : return 1;
2549 : }
2550 44 : ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
2551 44 : if (!ok) {
2552 0 : d_printf("deltree <filename>\n");
2553 0 : return 1;
2554 : }
2555 44 : mask = talloc_asprintf_append(mask, "%s", buf);
2556 44 : if (mask == NULL) {
2557 0 : return 1;
2558 : }
2559 44 : mask = client_clean_name(ctx, mask);
2560 44 : if (mask == NULL) {
2561 0 : return 1;
2562 : }
2563 :
2564 44 : deltree_list_head = NULL;
2565 :
2566 : /*
2567 : * Get the list of directories to
2568 : * delete (in case mask has a wildcard).
2569 : */
2570 44 : status = do_list(mask, attribute, do_deltree_list, false, true);
2571 44 : if (!NT_STATUS_IS_OK(status)) {
2572 12 : goto err;
2573 : }
2574 32 : deltree_list_norecurse = deltree_list_head;
2575 32 : deltree_list_head = NULL;
2576 :
2577 64 : for (deltree_list_iter = deltree_list_norecurse;
2578 32 : deltree_list_iter != NULL;
2579 32 : deltree_list_iter = deltree_list_iter->next) {
2580 :
2581 32 : if (deltree_list_iter->isdir == false) {
2582 0 : char *targetname = NULL;
2583 0 : struct cli_state *targetcli = NULL;
2584 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
2585 0 : status = cli_resolve_path(ctx,
2586 : "",
2587 : creds,
2588 : cli,
2589 0 : deltree_list_iter->file_path,
2590 : &targetcli,
2591 : &targetname);
2592 0 : if (!NT_STATUS_IS_OK(status)) {
2593 0 : goto err;
2594 : }
2595 : /* Just a regular file. */
2596 0 : if (CLI_DIRSEP_CHAR == '/') {
2597 : /* POSIX. */
2598 0 : status = cli_posix_unlink(targetcli,
2599 : targetname);
2600 : } else {
2601 0 : status = cli_unlink(targetcli,
2602 : targetname,
2603 : FILE_ATTRIBUTE_SYSTEM |
2604 : FILE_ATTRIBUTE_HIDDEN);
2605 : }
2606 0 : if (!NT_STATUS_IS_OK(status)) {
2607 0 : goto err;
2608 : }
2609 0 : continue;
2610 : }
2611 :
2612 : /*
2613 : * Get the list of files or directories to
2614 : * delete in depth order.
2615 : */
2616 32 : status = do_list(deltree_list_iter->file_path,
2617 : attribute,
2618 : do_deltree_list,
2619 : true,
2620 : true);
2621 32 : if (!NT_STATUS_IS_OK(status)) {
2622 0 : goto err;
2623 : }
2624 32 : status = delete_remote_files_list(cli, deltree_list_head);
2625 32 : free_file_list(deltree_list_head);
2626 32 : deltree_list_head = NULL;
2627 32 : if (!NT_STATUS_IS_OK(status)) {
2628 0 : goto err;
2629 : }
2630 : }
2631 :
2632 32 : free_file_list(deltree_list_norecurse);
2633 32 : free_file_list(deltree_list_head);
2634 32 : return 0;
2635 :
2636 12 : err:
2637 :
2638 12 : free_file_list(deltree_list_norecurse);
2639 12 : free_file_list(deltree_list_head);
2640 12 : deltree_list_head = NULL;
2641 12 : return 1;
2642 : }
2643 :
2644 :
2645 : /****************************************************************************
2646 : Wildcard delete some files.
2647 : ****************************************************************************/
2648 :
2649 0 : static int cmd_wdel(void)
2650 : {
2651 0 : TALLOC_CTX *ctx = talloc_tos();
2652 0 : char *mask = NULL;
2653 0 : char *buf = NULL;
2654 : uint32_t attribute;
2655 : struct cli_state *targetcli;
2656 0 : char *targetname = NULL;
2657 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
2658 : NTSTATUS status;
2659 :
2660 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2661 0 : d_printf("wdel 0x<attrib> <wcard>\n");
2662 0 : return 1;
2663 : }
2664 :
2665 0 : attribute = (uint32_t)strtol(buf, (char **)NULL, 16);
2666 :
2667 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2668 0 : d_printf("wdel 0x<attrib> <wcard>\n");
2669 0 : return 1;
2670 : }
2671 :
2672 0 : mask = talloc_asprintf(ctx, "%s%s",
2673 : client_get_cur_dir(),
2674 : buf);
2675 0 : if (!mask) {
2676 0 : return 1;
2677 : }
2678 0 : mask = client_clean_name(ctx, mask);
2679 0 : if (mask == NULL) {
2680 0 : return 1;
2681 : }
2682 :
2683 0 : status = cli_resolve_path(ctx, "",
2684 : creds,
2685 : cli, mask, &targetcli, &targetname);
2686 0 : if (!NT_STATUS_IS_OK(status)) {
2687 0 : d_printf("cmd_wdel %s: %s\n", mask, nt_errstr(status));
2688 0 : return 1;
2689 : }
2690 :
2691 0 : status = cli_unlink(targetcli, targetname, attribute);
2692 0 : if (!NT_STATUS_IS_OK(status)) {
2693 0 : d_printf("%s deleting remote files %s\n", nt_errstr(status),
2694 : targetname);
2695 : }
2696 0 : return 0;
2697 : }
2698 :
2699 : /****************************************************************************
2700 : ****************************************************************************/
2701 :
2702 0 : static int cmd_open(void)
2703 : {
2704 0 : TALLOC_CTX *ctx = talloc_tos();
2705 0 : char *mask = NULL;
2706 0 : char *buf = NULL;
2707 0 : char *targetname = NULL;
2708 : struct cli_state *targetcli;
2709 0 : uint16_t fnum = (uint16_t)-1;
2710 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
2711 : NTSTATUS status;
2712 :
2713 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2714 0 : d_printf("open <filename>\n");
2715 0 : return 1;
2716 : }
2717 0 : mask = talloc_asprintf(ctx,
2718 : "%s%s",
2719 : client_get_cur_dir(),
2720 : buf);
2721 0 : if (!mask) {
2722 0 : return 1;
2723 : }
2724 :
2725 0 : mask = client_clean_name(ctx, mask);
2726 0 : if (mask == NULL) {
2727 0 : return 1;
2728 : }
2729 :
2730 0 : status = cli_resolve_path(ctx, "",
2731 : creds,
2732 : cli, mask, &targetcli, &targetname);
2733 0 : if (!NT_STATUS_IS_OK(status)) {
2734 0 : d_printf("open %s: %s\n", mask, nt_errstr(status));
2735 0 : return 1;
2736 : }
2737 :
2738 0 : status = cli_ntcreate(targetcli, targetname, 0,
2739 : FILE_READ_DATA|FILE_WRITE_DATA, 0,
2740 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
2741 : 0x0, 0x0, &fnum, NULL);
2742 0 : if (!NT_STATUS_IS_OK(status)) {
2743 0 : status = cli_ntcreate(targetcli, targetname, 0,
2744 : FILE_READ_DATA, 0,
2745 : FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
2746 : 0x0, 0x0, &fnum, NULL);
2747 0 : if (NT_STATUS_IS_OK(status)) {
2748 0 : d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
2749 : } else {
2750 0 : d_printf("Failed to open file %s. %s\n",
2751 : targetname, nt_errstr(status));
2752 : }
2753 : } else {
2754 0 : d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
2755 : }
2756 0 : return 0;
2757 : }
2758 :
2759 0 : static int cmd_posix_encrypt(void)
2760 : {
2761 0 : TALLOC_CTX *ctx = talloc_tos();
2762 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2763 0 : char *domain = NULL;
2764 0 : char *user = NULL;
2765 0 : char *password = NULL;
2766 0 : struct cli_credentials *creds = NULL;
2767 0 : struct cli_credentials *lcreds = NULL;
2768 :
2769 0 : if (next_token_talloc(ctx, &cmd_ptr, &domain, NULL)) {
2770 :
2771 0 : if (!next_token_talloc(ctx, &cmd_ptr, &user, NULL)) {
2772 0 : d_printf("posix_encrypt domain user password\n");
2773 0 : return 1;
2774 : }
2775 :
2776 0 : if (!next_token_talloc(ctx, &cmd_ptr, &password, NULL)) {
2777 0 : d_printf("posix_encrypt domain user password\n");
2778 0 : return 1;
2779 : }
2780 :
2781 0 : lcreds = cli_session_creds_init(ctx,
2782 : user,
2783 : domain,
2784 : NULL, /* realm */
2785 : password,
2786 : false, /* use_kerberos */
2787 : false, /* fallback_after_kerberos */
2788 : false, /* use_ccache */
2789 : false); /* password_is_nt_hash */
2790 0 : if (lcreds == NULL) {
2791 0 : d_printf("cli_session_creds_init() failed.\n");
2792 0 : return -1;
2793 : }
2794 0 : creds = lcreds;
2795 : } else {
2796 0 : bool auth_requested = false;
2797 :
2798 0 : creds = samba_cmdline_get_creds();
2799 :
2800 0 : auth_requested = cli_credentials_authentication_requested(creds);
2801 0 : if (!auth_requested) {
2802 0 : d_printf("posix_encrypt domain user password\n");
2803 0 : return 1;
2804 : }
2805 : }
2806 :
2807 0 : status = cli_smb1_setup_encryption(cli, creds);
2808 : /* gensec currently references the creds so we can't free them here */
2809 0 : talloc_unlink(ctx, lcreds);
2810 0 : if (!NT_STATUS_IS_OK(status)) {
2811 0 : d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
2812 : } else {
2813 : bool ok;
2814 :
2815 0 : d_printf("encryption on\n");
2816 0 : ok = cli_credentials_set_smb_encryption(creds,
2817 : SMB_ENCRYPTION_REQUIRED,
2818 : CRED_SPECIFIED);
2819 0 : SMB_ASSERT(ok);
2820 : }
2821 :
2822 0 : return 0;
2823 : }
2824 :
2825 : /****************************************************************************
2826 : ****************************************************************************/
2827 :
2828 0 : static int cmd_posix_open(void)
2829 : {
2830 0 : TALLOC_CTX *ctx = talloc_tos();
2831 0 : char *mask = NULL;
2832 0 : char *buf = NULL;
2833 0 : char *targetname = NULL;
2834 : struct cli_state *targetcli;
2835 : mode_t mode;
2836 : uint16_t fnum;
2837 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
2838 : NTSTATUS status;
2839 :
2840 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2841 0 : d_printf("posix_open <filename> 0<mode>\n");
2842 0 : return 1;
2843 : }
2844 0 : mask = talloc_asprintf(ctx,
2845 : "%s%s",
2846 : client_get_cur_dir(),
2847 : buf);
2848 0 : if (!mask) {
2849 0 : return 1;
2850 : }
2851 0 : mask = client_clean_name(ctx, mask);
2852 0 : if (mask == NULL) {
2853 0 : return 1;
2854 : }
2855 :
2856 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2857 0 : d_printf("posix_open <filename> 0<mode>\n");
2858 0 : return 1;
2859 : }
2860 0 : if (CLI_DIRSEP_CHAR != '/') {
2861 0 : d_printf("Command \"posix\" must be issued before "
2862 : "the \"posix_open\" command can be used.\n");
2863 0 : return 1;
2864 : }
2865 0 : mode = (mode_t)strtol(buf, (char **)NULL, 8);
2866 :
2867 0 : status = cli_resolve_path(ctx, "",
2868 : creds,
2869 : cli, mask, &targetcli, &targetname);
2870 0 : if (!NT_STATUS_IS_OK(status)) {
2871 0 : d_printf("posix_open %s: %s\n", mask, nt_errstr(status));
2872 0 : return 1;
2873 : }
2874 :
2875 0 : status = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode,
2876 : &fnum);
2877 0 : if (!NT_STATUS_IS_OK(status)) {
2878 0 : status = cli_posix_open(targetcli, targetname,
2879 : O_CREAT|O_RDONLY, mode, &fnum);
2880 0 : if (!NT_STATUS_IS_OK(status)) {
2881 0 : d_printf("Failed to open file %s. %s\n", targetname,
2882 : nt_errstr(status));
2883 : } else {
2884 0 : d_printf("posix_open file %s: for readonly fnum %d\n",
2885 : targetname, fnum);
2886 : }
2887 : } else {
2888 0 : d_printf("posix_open file %s: for read/write fnum %d\n",
2889 : targetname, fnum);
2890 : }
2891 :
2892 0 : return 0;
2893 : }
2894 :
2895 0 : static int cmd_posix_mkdir(void)
2896 : {
2897 0 : TALLOC_CTX *ctx = talloc_tos();
2898 0 : char *mask = NULL;
2899 0 : char *buf = NULL;
2900 0 : char *targetname = NULL;
2901 : struct cli_state *targetcli;
2902 : mode_t mode;
2903 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
2904 : NTSTATUS status;
2905 :
2906 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2907 0 : d_printf("posix_mkdir <filename> 0<mode>\n");
2908 0 : return 1;
2909 : }
2910 0 : mask = talloc_asprintf(ctx,
2911 : "%s%s",
2912 : client_get_cur_dir(),
2913 : buf);
2914 0 : if (!mask) {
2915 0 : return 1;
2916 : }
2917 0 : mask = client_clean_name(ctx, mask);
2918 0 : if (mask == NULL) {
2919 0 : return 1;
2920 : }
2921 :
2922 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2923 0 : d_printf("posix_mkdir <filename> 0<mode>\n");
2924 0 : return 1;
2925 : }
2926 0 : if (CLI_DIRSEP_CHAR != '/') {
2927 0 : d_printf("Command \"posix\" must be issued before "
2928 : "the \"posix_mkdir\" command can be used.\n");
2929 0 : return 1;
2930 : }
2931 0 : mode = (mode_t)strtol(buf, (char **)NULL, 8);
2932 :
2933 0 : status = cli_resolve_path(ctx, "",
2934 : creds,
2935 : cli, mask, &targetcli, &targetname);
2936 0 : if (!NT_STATUS_IS_OK(status)) {
2937 0 : d_printf("posix_mkdir %s: %s\n", mask, nt_errstr(status));
2938 0 : return 1;
2939 : }
2940 :
2941 0 : status = cli_posix_mkdir(targetcli, targetname, mode);
2942 0 : if (!NT_STATUS_IS_OK(status)) {
2943 0 : d_printf("Failed to open file %s. %s\n",
2944 : targetname, nt_errstr(status));
2945 : } else {
2946 0 : d_printf("posix_mkdir created directory %s\n", targetname);
2947 : }
2948 0 : return 0;
2949 : }
2950 :
2951 8 : static int cmd_posix_unlink(void)
2952 : {
2953 8 : TALLOC_CTX *ctx = talloc_tos();
2954 8 : char *mask = NULL;
2955 8 : char *buf = NULL;
2956 8 : char *targetname = NULL;
2957 : struct cli_state *targetcli;
2958 8 : struct cli_credentials *creds = samba_cmdline_get_creds();
2959 : NTSTATUS status;
2960 :
2961 8 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2962 0 : d_printf("posix_unlink <filename>\n");
2963 0 : return 1;
2964 : }
2965 8 : if (CLI_DIRSEP_CHAR != '/') {
2966 8 : d_printf("Command \"posix\" must be issued before "
2967 : "the \"posix_unlink\" command can be used.\n");
2968 8 : return 1;
2969 : }
2970 0 : mask = talloc_asprintf(ctx,
2971 : "%s%s",
2972 : client_get_cur_dir(),
2973 : buf);
2974 0 : if (!mask) {
2975 0 : return 1;
2976 : }
2977 0 : mask = client_clean_name(ctx, mask);
2978 0 : if (mask == NULL) {
2979 0 : return 1;
2980 : }
2981 :
2982 0 : status = cli_resolve_path(ctx, "",
2983 : creds,
2984 : cli, mask, &targetcli, &targetname);
2985 0 : if (!NT_STATUS_IS_OK(status)) {
2986 0 : d_printf("posix_unlink %s: %s\n", mask, nt_errstr(status));
2987 0 : return 1;
2988 : }
2989 :
2990 0 : status = cli_posix_unlink(targetcli, targetname);
2991 0 : if (!NT_STATUS_IS_OK(status)) {
2992 0 : d_printf("Failed to unlink file %s. %s\n",
2993 : targetname, nt_errstr(status));
2994 : } else {
2995 0 : d_printf("posix_unlink deleted file %s\n", targetname);
2996 : }
2997 :
2998 0 : return 0;
2999 : }
3000 :
3001 0 : static int cmd_posix_rmdir(void)
3002 : {
3003 0 : TALLOC_CTX *ctx = talloc_tos();
3004 0 : char *mask = NULL;
3005 0 : char *buf = NULL;
3006 0 : char *targetname = NULL;
3007 : struct cli_state *targetcli;
3008 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3009 : NTSTATUS status;
3010 :
3011 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3012 0 : d_printf("posix_rmdir <filename>\n");
3013 0 : return 1;
3014 : }
3015 0 : if (CLI_DIRSEP_CHAR != '/') {
3016 0 : d_printf("Command \"posix\" must be issued before "
3017 : "the \"posix_rmdir\" command can be used.\n");
3018 0 : return 1;
3019 : }
3020 0 : mask = talloc_asprintf(ctx,
3021 : "%s%s",
3022 : client_get_cur_dir(),
3023 : buf);
3024 0 : if (!mask) {
3025 0 : return 1;
3026 : }
3027 0 : mask = client_clean_name(ctx, mask);
3028 0 : if (mask == NULL) {
3029 0 : return 1;
3030 : }
3031 :
3032 0 : status = cli_resolve_path(ctx, "",
3033 : creds,
3034 : cli, mask, &targetcli, &targetname);
3035 0 : if (!NT_STATUS_IS_OK(status)) {
3036 0 : d_printf("posix_rmdir %s: %s\n", mask, nt_errstr(status));
3037 0 : return 1;
3038 : }
3039 :
3040 0 : status = cli_posix_rmdir(targetcli, targetname);
3041 0 : if (!NT_STATUS_IS_OK(status)) {
3042 0 : d_printf("Failed to unlink directory %s. %s\n",
3043 : targetname, nt_errstr(status));
3044 : } else {
3045 0 : d_printf("posix_rmdir deleted directory %s\n", targetname);
3046 : }
3047 :
3048 0 : return 0;
3049 : }
3050 :
3051 0 : static int cmd_close(void)
3052 : {
3053 0 : TALLOC_CTX *ctx = talloc_tos();
3054 0 : char *buf = NULL;
3055 : int fnum;
3056 : NTSTATUS status;
3057 :
3058 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3059 0 : d_printf("close <fnum>\n");
3060 0 : return 1;
3061 : }
3062 :
3063 0 : fnum = atoi(buf);
3064 : /* We really should use the targetcli here.... */
3065 0 : status = cli_close(cli, fnum);
3066 0 : if (!NT_STATUS_IS_OK(status)) {
3067 0 : d_printf("close %d: %s\n", fnum, nt_errstr(status));
3068 0 : return 1;
3069 : }
3070 0 : return 0;
3071 : }
3072 :
3073 9 : static int cmd_posix(void)
3074 : {
3075 9 : TALLOC_CTX *ctx = talloc_tos();
3076 : uint16_t major, minor;
3077 : uint32_t caplow, caphigh;
3078 : char *caps;
3079 : NTSTATUS status;
3080 :
3081 9 : if (!SERVER_HAS_UNIX_CIFS(cli)) {
3082 9 : d_printf("Server doesn't support UNIX CIFS extensions.\n");
3083 9 : return 1;
3084 : }
3085 :
3086 0 : status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
3087 : &caphigh);
3088 0 : if (!NT_STATUS_IS_OK(status)) {
3089 0 : d_printf("Can't get UNIX CIFS extensions version from "
3090 : "server: %s\n", nt_errstr(status));
3091 0 : return 1;
3092 : }
3093 :
3094 0 : d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor);
3095 :
3096 0 : caps = talloc_strdup(ctx, "");
3097 0 : if (!caps) {
3098 0 : return 1;
3099 : }
3100 0 : if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) {
3101 0 : caps = talloc_asprintf_append(caps, "locks ");
3102 0 : if (!caps) {
3103 0 : return 1;
3104 : }
3105 : }
3106 0 : if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) {
3107 0 : caps = talloc_asprintf_append(caps, "acls ");
3108 0 : if (!caps) {
3109 0 : return 1;
3110 : }
3111 : }
3112 0 : if (caplow & CIFS_UNIX_XATTTR_CAP) {
3113 0 : caps = talloc_asprintf_append(caps, "eas ");
3114 0 : if (!caps) {
3115 0 : return 1;
3116 : }
3117 : }
3118 0 : if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3119 0 : caps = talloc_asprintf_append(caps, "pathnames ");
3120 0 : if (!caps) {
3121 0 : return 1;
3122 : }
3123 : }
3124 0 : if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
3125 0 : caps = talloc_asprintf_append(caps, "posix_path_operations ");
3126 0 : if (!caps) {
3127 0 : return 1;
3128 : }
3129 : }
3130 0 : if (caplow & CIFS_UNIX_LARGE_READ_CAP) {
3131 0 : caps = talloc_asprintf_append(caps, "large_read ");
3132 0 : if (!caps) {
3133 0 : return 1;
3134 : }
3135 : }
3136 0 : if (caplow & CIFS_UNIX_LARGE_WRITE_CAP) {
3137 0 : caps = talloc_asprintf_append(caps, "large_write ");
3138 0 : if (!caps) {
3139 0 : return 1;
3140 : }
3141 : }
3142 0 : if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) {
3143 0 : caps = talloc_asprintf_append(caps, "posix_encrypt ");
3144 0 : if (!caps) {
3145 0 : return 1;
3146 : }
3147 : }
3148 0 : if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) {
3149 0 : caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt ");
3150 0 : if (!caps) {
3151 0 : return 1;
3152 : }
3153 : }
3154 :
3155 0 : if (*caps && caps[strlen(caps)-1] == ' ') {
3156 0 : caps[strlen(caps)-1] = '\0';
3157 : }
3158 :
3159 0 : d_printf("Server supports CIFS capabilities %s\n", caps);
3160 :
3161 0 : status = cli_set_unix_extensions_capabilities(cli, major, minor,
3162 : caplow, caphigh);
3163 0 : if (!NT_STATUS_IS_OK(status)) {
3164 0 : d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n",
3165 : nt_errstr(status));
3166 0 : return 1;
3167 : }
3168 :
3169 0 : if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3170 0 : CLI_DIRSEP_CHAR = '/';
3171 0 : *CLI_DIRSEP_STR = '/';
3172 0 : client_set_cur_dir(CLI_DIRSEP_STR);
3173 : }
3174 :
3175 0 : return 0;
3176 : }
3177 :
3178 0 : static int cmd_lock(void)
3179 : {
3180 0 : TALLOC_CTX *ctx = talloc_tos();
3181 0 : char *buf = NULL;
3182 : uint64_t start, len;
3183 : enum brl_type lock_type;
3184 : int fnum;
3185 : NTSTATUS status;
3186 :
3187 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3188 0 : d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3189 0 : return 1;
3190 : }
3191 0 : fnum = atoi(buf);
3192 :
3193 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3194 0 : d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3195 0 : return 1;
3196 : }
3197 :
3198 0 : if (*buf == 'r' || *buf == 'R') {
3199 0 : lock_type = READ_LOCK;
3200 0 : } else if (*buf == 'w' || *buf == 'W') {
3201 0 : lock_type = WRITE_LOCK;
3202 : } else {
3203 0 : d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3204 0 : return 1;
3205 : }
3206 :
3207 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3208 0 : d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3209 0 : return 1;
3210 : }
3211 :
3212 0 : start = (uint64_t)strtol(buf, (char **)NULL, 16);
3213 :
3214 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3215 0 : d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
3216 0 : return 1;
3217 : }
3218 :
3219 0 : if (CLI_DIRSEP_CHAR != '/') {
3220 0 : d_printf("Command \"posix\" must be issued before "
3221 : "the \"lock\" command can be used.\n");
3222 0 : return 1;
3223 : }
3224 :
3225 0 : len = (uint64_t)strtol(buf, (char **)NULL, 16);
3226 :
3227 0 : status = cli_posix_lock(cli, fnum, start, len, true, lock_type);
3228 0 : if (!NT_STATUS_IS_OK(status)) {
3229 0 : d_printf("lock failed %d: %s\n", fnum, nt_errstr(status));
3230 : }
3231 :
3232 0 : return 0;
3233 : }
3234 :
3235 0 : static int cmd_unlock(void)
3236 : {
3237 0 : TALLOC_CTX *ctx = talloc_tos();
3238 0 : char *buf = NULL;
3239 : uint64_t start, len;
3240 : int fnum;
3241 : NTSTATUS status;
3242 :
3243 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3244 0 : d_printf("unlock <fnum> <hex-start> <hex-len>\n");
3245 0 : return 1;
3246 : }
3247 0 : fnum = atoi(buf);
3248 :
3249 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3250 0 : d_printf("unlock <fnum> <hex-start> <hex-len>\n");
3251 0 : return 1;
3252 : }
3253 :
3254 0 : start = (uint64_t)strtol(buf, (char **)NULL, 16);
3255 :
3256 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3257 0 : d_printf("unlock <fnum> <hex-start> <hex-len>\n");
3258 0 : return 1;
3259 : }
3260 :
3261 0 : if (CLI_DIRSEP_CHAR != '/') {
3262 0 : d_printf("Command \"posix\" must be issued before "
3263 : "the \"unlock\" command can be used.\n");
3264 0 : return 1;
3265 : }
3266 :
3267 0 : len = (uint64_t)strtol(buf, (char **)NULL, 16);
3268 :
3269 0 : status = cli_posix_unlock(cli, fnum, start, len);
3270 0 : if (!NT_STATUS_IS_OK(status)) {
3271 0 : d_printf("unlock failed %d: %s\n", fnum, nt_errstr(status));
3272 : }
3273 :
3274 0 : return 0;
3275 : }
3276 :
3277 0 : static int cmd_posix_whoami(void)
3278 : {
3279 0 : TALLOC_CTX *ctx = talloc_tos();
3280 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
3281 0 : uint64_t uid = 0;
3282 0 : uint64_t gid = 0;
3283 0 : uint32_t num_gids = 0;
3284 0 : uint32_t num_sids = 0;
3285 0 : uint64_t *gids = NULL;
3286 0 : struct dom_sid *sids = NULL;
3287 0 : bool guest = false;
3288 : uint32_t i;
3289 :
3290 0 : if (CLI_DIRSEP_CHAR != '/') {
3291 0 : d_printf("Command \"posix\" must be issued before "
3292 : "the \"posix_whoami\" command can be used.\n");
3293 0 : return 1;
3294 : }
3295 :
3296 0 : status = cli_posix_whoami(cli,
3297 : ctx,
3298 : &uid,
3299 : &gid,
3300 : &num_gids,
3301 : &gids,
3302 : &num_sids,
3303 : &sids,
3304 : &guest);
3305 :
3306 0 : if (!NT_STATUS_IS_OK(status)) {
3307 0 : d_printf("posix_whoami failed with error %s\n", nt_errstr(status));
3308 0 : return 1;
3309 : }
3310 :
3311 0 : d_printf("GUEST:%s\n", guest ? "True" : "False");
3312 0 : d_printf("UID:%" PRIu64 "\n", uid);
3313 0 : d_printf("GID:%" PRIu64 "\n", gid);
3314 0 : d_printf("NUM_GIDS:%" PRIu32 "\n", num_gids);
3315 0 : for (i = 0; i < num_gids; i++) {
3316 0 : d_printf("GIDS[%" PRIu32 "]:%" PRIu64 "\n", i, gids[i]);
3317 : }
3318 0 : d_printf("NUM_SIDS:%" PRIu32 "\n", num_sids);
3319 0 : for (i = 0; i < num_sids; i++) {
3320 : struct dom_sid_buf buf;
3321 0 : d_printf("SIDS[%" PRIu32 "]:%s\n",
3322 : i,
3323 0 : dom_sid_str_buf(&sids[i], &buf));
3324 : }
3325 0 : return 0;
3326 : }
3327 :
3328 :
3329 : /****************************************************************************
3330 : Remove a directory.
3331 : ****************************************************************************/
3332 :
3333 4 : static int cmd_rmdir(void)
3334 : {
3335 4 : TALLOC_CTX *ctx = talloc_tos();
3336 4 : char *mask = NULL;
3337 4 : char *buf = NULL;
3338 4 : char *targetname = NULL;
3339 : struct cli_state *targetcli;
3340 4 : struct cli_credentials *creds = samba_cmdline_get_creds();
3341 : NTSTATUS status;
3342 :
3343 4 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3344 0 : d_printf("rmdir <dirname>\n");
3345 0 : return 1;
3346 : }
3347 4 : mask = talloc_asprintf(ctx,
3348 : "%s%s",
3349 : client_get_cur_dir(),
3350 : buf);
3351 4 : if (!mask) {
3352 0 : return 1;
3353 : }
3354 4 : mask = client_clean_name(ctx, mask);
3355 4 : if (mask == NULL) {
3356 0 : return 1;
3357 : }
3358 :
3359 4 : status = cli_resolve_path(ctx, "",
3360 : creds,
3361 : cli, mask, &targetcli, &targetname);
3362 4 : if (!NT_STATUS_IS_OK(status)) {
3363 0 : d_printf("rmdir %s: %s\n", mask, nt_errstr(status));
3364 0 : return 1;
3365 : }
3366 :
3367 4 : status = cli_rmdir(targetcli, targetname);
3368 4 : if (!NT_STATUS_IS_OK(status)) {
3369 4 : d_printf("%s removing remote directory file %s\n",
3370 : nt_errstr(status), mask);
3371 : }
3372 :
3373 4 : return 0;
3374 : }
3375 :
3376 : /****************************************************************************
3377 : UNIX hardlink.
3378 : ****************************************************************************/
3379 :
3380 0 : static int cmd_link(void)
3381 : {
3382 0 : TALLOC_CTX *ctx = talloc_tos();
3383 0 : char *oldname = NULL;
3384 0 : char *newname = NULL;
3385 0 : char *buf = NULL;
3386 0 : char *buf2 = NULL;
3387 0 : char *targetname = NULL;
3388 : struct cli_state *targetcli;
3389 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3390 : NTSTATUS status;
3391 :
3392 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
3393 0 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
3394 0 : d_printf("link <oldname> <newname>\n");
3395 0 : return 1;
3396 : }
3397 0 : oldname = talloc_asprintf(ctx,
3398 : "%s%s",
3399 : client_get_cur_dir(),
3400 : buf);
3401 0 : if (!oldname) {
3402 0 : return 1;
3403 : }
3404 0 : oldname = client_clean_name(ctx, oldname);
3405 0 : if (oldname == NULL) {
3406 0 : return 1;
3407 : }
3408 0 : newname = talloc_asprintf(ctx,
3409 : "%s%s",
3410 : client_get_cur_dir(),
3411 : buf2);
3412 0 : if (!newname) {
3413 0 : return 1;
3414 : }
3415 0 : newname = client_clean_name(ctx, newname);
3416 0 : if (newname == NULL) {
3417 0 : return 1;
3418 : }
3419 :
3420 0 : status = cli_resolve_path(ctx, "",
3421 : creds,
3422 : cli, oldname, &targetcli, &targetname);
3423 0 : if (!NT_STATUS_IS_OK(status)) {
3424 0 : d_printf("link %s: %s\n", oldname, nt_errstr(status));
3425 0 : return 1;
3426 : }
3427 :
3428 0 : if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3429 0 : d_printf("Server doesn't support UNIX CIFS calls.\n");
3430 0 : return 1;
3431 : }
3432 :
3433 0 : if (CLI_DIRSEP_CHAR != '/') {
3434 0 : d_printf("Command \"posix\" must be issued before "
3435 : "the \"link\" command can be used.\n");
3436 0 : return 1;
3437 : }
3438 :
3439 0 : status = cli_posix_hardlink(targetcli, targetname, newname);
3440 0 : if (!NT_STATUS_IS_OK(status)) {
3441 0 : d_printf("%s linking files (%s -> %s)\n",
3442 : nt_errstr(status), newname, oldname);
3443 0 : return 1;
3444 : }
3445 0 : return 0;
3446 : }
3447 :
3448 : /****************************************************************************
3449 : UNIX readlink.
3450 : ****************************************************************************/
3451 :
3452 0 : static int cmd_readlink(void)
3453 : {
3454 0 : TALLOC_CTX *ctx = talloc_tos();
3455 0 : char *name= NULL;
3456 0 : char *buf = NULL;
3457 0 : char *targetname = NULL;
3458 0 : char *linkname = NULL;
3459 : struct cli_state *targetcli;
3460 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3461 : NTSTATUS status;
3462 :
3463 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3464 0 : d_printf("readlink <name>\n");
3465 0 : return 1;
3466 : }
3467 0 : name = talloc_asprintf(ctx,
3468 : "%s%s",
3469 : client_get_cur_dir(),
3470 : buf);
3471 0 : if (!name) {
3472 0 : return 1;
3473 : }
3474 0 : name = client_clean_name(ctx, name);
3475 0 : if (name == NULL) {
3476 0 : return 1;
3477 : }
3478 :
3479 0 : status = cli_resolve_path(ctx, "",
3480 : creds,
3481 : cli, name, &targetcli, &targetname);
3482 0 : if (!NT_STATUS_IS_OK(status)) {
3483 0 : d_printf("readlink %s: %s\n", name, nt_errstr(status));
3484 0 : return 1;
3485 : }
3486 :
3487 0 : if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3488 0 : d_printf("Server doesn't support UNIX CIFS calls.\n");
3489 0 : return 1;
3490 : }
3491 :
3492 0 : if (CLI_DIRSEP_CHAR != '/') {
3493 0 : d_printf("Command \"posix\" must be issued before "
3494 : "the \"readlink\" command can be used.\n");
3495 0 : return 1;
3496 : }
3497 :
3498 0 : status = cli_posix_readlink(targetcli, name, talloc_tos(), &linkname);
3499 0 : if (!NT_STATUS_IS_OK(status)) {
3500 0 : d_printf("%s readlink on file %s\n",
3501 : nt_errstr(status), name);
3502 0 : return 1;
3503 : }
3504 :
3505 0 : d_printf("%s -> %s\n", name, linkname);
3506 :
3507 0 : TALLOC_FREE(linkname);
3508 :
3509 0 : return 0;
3510 : }
3511 :
3512 :
3513 : /****************************************************************************
3514 : UNIX symlink.
3515 : ****************************************************************************/
3516 :
3517 4 : static int cmd_symlink(void)
3518 : {
3519 4 : TALLOC_CTX *ctx = talloc_tos();
3520 4 : char *link_target = NULL;
3521 4 : char *newname = NULL;
3522 4 : char *buf = NULL;
3523 4 : char *buf2 = NULL;
3524 : struct cli_state *newcli;
3525 4 : struct cli_credentials *creds = samba_cmdline_get_creds();
3526 : NTSTATUS status;
3527 :
3528 6 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
3529 4 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
3530 0 : d_printf("symlink <link_target> <newname>\n");
3531 0 : return 1;
3532 : }
3533 : /* Oldname (link target) must be an untouched blob. */
3534 4 : link_target = buf;
3535 :
3536 4 : if (SERVER_HAS_UNIX_CIFS(cli)) {
3537 0 : if (CLI_DIRSEP_CHAR != '/') {
3538 0 : d_printf("Command \"posix\" must be issued before "
3539 : "the \"symlink\" command can be used.\n");
3540 0 : return 1;
3541 : }
3542 0 : newname = talloc_asprintf(ctx, "%s%s", client_get_cur_dir(),
3543 : buf2);
3544 0 : if (!newname) {
3545 0 : return 1;
3546 : }
3547 0 : newname = client_clean_name(ctx, newname);
3548 0 : if (newname == NULL) {
3549 0 : return 1;
3550 : }
3551 : /* New name must be present in share namespace. */
3552 0 : status = cli_resolve_path(ctx, "",
3553 : creds,
3554 : cli, newname,
3555 : &newcli, &newname);
3556 0 : if (!NT_STATUS_IS_OK(status)) {
3557 0 : d_printf("link %s: %s\n", newname,
3558 : nt_errstr(status));
3559 0 : return 1;
3560 : }
3561 0 : status = cli_posix_symlink(newcli, link_target, newname);
3562 : } else {
3563 4 : status = cli_symlink(
3564 : cli, link_target, buf2,
3565 4 : buf2[0] == '\\' ? 0 : SYMLINK_FLAG_RELATIVE);
3566 : }
3567 :
3568 4 : if (!NT_STATUS_IS_OK(status)) {
3569 4 : d_printf("%s symlinking files (%s -> %s)\n",
3570 : nt_errstr(status), newname, link_target);
3571 4 : return 1;
3572 : }
3573 :
3574 0 : return 0;
3575 : }
3576 :
3577 : /****************************************************************************
3578 : UNIX chmod.
3579 : ****************************************************************************/
3580 :
3581 0 : static int cmd_chmod(void)
3582 : {
3583 0 : TALLOC_CTX *ctx = talloc_tos();
3584 0 : char *src = NULL;
3585 0 : char *buf = NULL;
3586 0 : char *buf2 = NULL;
3587 0 : char *targetname = NULL;
3588 : struct cli_state *targetcli;
3589 : mode_t mode;
3590 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3591 : NTSTATUS status;
3592 :
3593 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
3594 0 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
3595 0 : d_printf("chmod mode file\n");
3596 0 : return 1;
3597 : }
3598 0 : src = talloc_asprintf(ctx,
3599 : "%s%s",
3600 : client_get_cur_dir(),
3601 : buf2);
3602 0 : if (!src) {
3603 0 : return 1;
3604 : }
3605 0 : src = client_clean_name(ctx, src);
3606 0 : if (src == NULL) {
3607 0 : return 1;
3608 : }
3609 :
3610 0 : mode = (mode_t)strtol(buf, NULL, 8);
3611 :
3612 0 : status = cli_resolve_path(ctx, "",
3613 : creds,
3614 : cli, src, &targetcli, &targetname);
3615 0 : if (!NT_STATUS_IS_OK(status)) {
3616 0 : d_printf("chmod %s: %s\n", src, nt_errstr(status));
3617 0 : return 1;
3618 : }
3619 :
3620 0 : if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3621 0 : d_printf("Server doesn't support UNIX CIFS calls.\n");
3622 0 : return 1;
3623 : }
3624 :
3625 0 : if (CLI_DIRSEP_CHAR != '/') {
3626 0 : d_printf("Command \"posix\" must be issued before "
3627 : "the \"chmod\" command can be used.\n");
3628 0 : return 1;
3629 : }
3630 :
3631 0 : status = cli_posix_chmod(targetcli, targetname, mode);
3632 0 : if (!NT_STATUS_IS_OK(status)) {
3633 0 : d_printf("%s chmod file %s 0%o\n",
3634 : nt_errstr(status), src, (unsigned int)mode);
3635 0 : return 1;
3636 : }
3637 :
3638 0 : return 0;
3639 : }
3640 :
3641 0 : static const char *filetype_to_str(mode_t mode)
3642 : {
3643 0 : if (S_ISREG(mode)) {
3644 0 : return "regular file";
3645 0 : } else if (S_ISDIR(mode)) {
3646 0 : return "directory";
3647 : } else
3648 : #ifdef S_ISCHR
3649 0 : if (S_ISCHR(mode)) {
3650 0 : return "character device";
3651 : } else
3652 : #endif
3653 : #ifdef S_ISBLK
3654 0 : if (S_ISBLK(mode)) {
3655 0 : return "block device";
3656 : } else
3657 : #endif
3658 : #ifdef S_ISFIFO
3659 0 : if (S_ISFIFO(mode)) {
3660 0 : return "fifo";
3661 : } else
3662 : #endif
3663 : #ifdef S_ISLNK
3664 0 : if (S_ISLNK(mode)) {
3665 0 : return "symbolic link";
3666 : } else
3667 : #endif
3668 : #ifdef S_ISSOCK
3669 0 : if (S_ISSOCK(mode)) {
3670 0 : return "socket";
3671 : } else
3672 : #endif
3673 0 : return "";
3674 : }
3675 :
3676 0 : static char rwx_to_str(mode_t m, mode_t bt, char ret)
3677 : {
3678 0 : if (m & bt) {
3679 0 : return ret;
3680 : } else {
3681 0 : return '-';
3682 : }
3683 : }
3684 :
3685 0 : static char *unix_mode_to_str(char *s, mode_t m)
3686 : {
3687 0 : char *p = s;
3688 0 : const char *str = filetype_to_str(m);
3689 :
3690 0 : switch(str[0]) {
3691 0 : case 'd':
3692 0 : *p++ = 'd';
3693 0 : break;
3694 0 : case 'c':
3695 0 : *p++ = 'c';
3696 0 : break;
3697 0 : case 'b':
3698 0 : *p++ = 'b';
3699 0 : break;
3700 0 : case 'f':
3701 0 : *p++ = 'p';
3702 0 : break;
3703 0 : case 's':
3704 0 : *p++ = str[1] == 'y' ? 'l' : 's';
3705 0 : break;
3706 0 : case 'r':
3707 : default:
3708 0 : *p++ = '-';
3709 0 : break;
3710 : }
3711 0 : *p++ = rwx_to_str(m, S_IRUSR, 'r');
3712 0 : *p++ = rwx_to_str(m, S_IWUSR, 'w');
3713 0 : *p++ = rwx_to_str(m, S_IXUSR, 'x');
3714 0 : *p++ = rwx_to_str(m, S_IRGRP, 'r');
3715 0 : *p++ = rwx_to_str(m, S_IWGRP, 'w');
3716 0 : *p++ = rwx_to_str(m, S_IXGRP, 'x');
3717 0 : *p++ = rwx_to_str(m, S_IROTH, 'r');
3718 0 : *p++ = rwx_to_str(m, S_IWOTH, 'w');
3719 0 : *p++ = rwx_to_str(m, S_IXOTH, 'x');
3720 0 : *p++ = '\0';
3721 0 : return s;
3722 : }
3723 :
3724 : /****************************************************************************
3725 : Utility function for UNIX getfacl.
3726 : ****************************************************************************/
3727 :
3728 0 : static char *perms_to_string(fstring permstr, unsigned char perms)
3729 : {
3730 0 : fstrcpy(permstr, "---");
3731 0 : if (perms & SMB_POSIX_ACL_READ) {
3732 0 : permstr[0] = 'r';
3733 : }
3734 0 : if (perms & SMB_POSIX_ACL_WRITE) {
3735 0 : permstr[1] = 'w';
3736 : }
3737 0 : if (perms & SMB_POSIX_ACL_EXECUTE) {
3738 0 : permstr[2] = 'x';
3739 : }
3740 0 : return permstr;
3741 : }
3742 :
3743 : /****************************************************************************
3744 : UNIX getfacl.
3745 : ****************************************************************************/
3746 :
3747 0 : static int cmd_getfacl(void)
3748 : {
3749 0 : TALLOC_CTX *ctx = talloc_tos();
3750 0 : char *src = NULL;
3751 0 : char *name = NULL;
3752 0 : char *targetname = NULL;
3753 : struct cli_state *targetcli;
3754 : uint16_t major, minor;
3755 : uint32_t caplow, caphigh;
3756 0 : char *retbuf = NULL;
3757 0 : size_t rb_size = 0;
3758 : SMB_STRUCT_STAT sbuf;
3759 0 : size_t num_file_acls = 0;
3760 0 : size_t num_dir_acls = 0;
3761 : size_t expected_buflen;
3762 : uint16_t i;
3763 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3764 : NTSTATUS status;
3765 :
3766 0 : if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
3767 0 : d_printf("getfacl filename\n");
3768 0 : return 1;
3769 : }
3770 0 : src = talloc_asprintf(ctx,
3771 : "%s%s",
3772 : client_get_cur_dir(),
3773 : name);
3774 0 : if (!src) {
3775 0 : return 1;
3776 : }
3777 0 : src = client_clean_name(ctx, src);
3778 0 : if (src == NULL) {
3779 0 : return 1;
3780 : }
3781 :
3782 0 : status = cli_resolve_path(ctx, "",
3783 : creds,
3784 : cli, src, &targetcli, &targetname);
3785 0 : if (!NT_STATUS_IS_OK(status)) {
3786 0 : d_printf("stat %s: %s\n", src, nt_errstr(status));
3787 0 : return 1;
3788 : }
3789 :
3790 0 : if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3791 0 : d_printf("Server doesn't support UNIX CIFS calls.\n");
3792 0 : return 1;
3793 : }
3794 :
3795 0 : if (CLI_DIRSEP_CHAR != '/') {
3796 0 : d_printf("Command \"posix\" must be issued before "
3797 : "the \"getfacl\" command can be used.\n");
3798 0 : return 1;
3799 : }
3800 :
3801 0 : status = cli_unix_extensions_version(targetcli, &major, &minor,
3802 : &caplow, &caphigh);
3803 0 : if (!NT_STATUS_IS_OK(status)) {
3804 0 : d_printf("Can't get UNIX CIFS version from server: %s.\n",
3805 : nt_errstr(status));
3806 0 : return 1;
3807 : }
3808 :
3809 0 : if (!(caplow & CIFS_UNIX_POSIX_ACLS_CAP)) {
3810 0 : d_printf("This server supports UNIX extensions "
3811 : "but doesn't support POSIX ACLs.\n");
3812 0 : return 1;
3813 : }
3814 :
3815 0 : status = cli_posix_stat(targetcli, targetname, &sbuf);
3816 0 : if (!NT_STATUS_IS_OK(status)) {
3817 0 : d_printf("%s getfacl doing a stat on file %s\n",
3818 : nt_errstr(status), src);
3819 0 : return 1;
3820 : }
3821 :
3822 0 : status = cli_posix_getacl(targetcli, targetname, ctx, &rb_size, &retbuf);
3823 0 : if (!NT_STATUS_IS_OK(status)) {
3824 0 : d_printf("%s getfacl file %s\n",
3825 : nt_errstr(status), src);
3826 0 : return 1;
3827 : }
3828 :
3829 : /* ToDo : Print out the ACL values. */
3830 0 : if (rb_size < 6 || SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION) {
3831 0 : d_printf("getfacl file %s, unknown POSIX acl version %u.\n",
3832 0 : src, (unsigned int)CVAL(retbuf,0) );
3833 0 : return 1;
3834 : }
3835 :
3836 0 : num_file_acls = SVAL(retbuf,2);
3837 0 : num_dir_acls = SVAL(retbuf,4);
3838 :
3839 : /*
3840 : * No overflow check, num_*_acls comes from a 16-bit value,
3841 : * and we expect expected_buflen (size_t) to be of at least 32
3842 : * bit.
3843 : */
3844 0 : expected_buflen = SMB_POSIX_ACL_HEADER_SIZE +
3845 0 : SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls);
3846 :
3847 0 : if (rb_size != expected_buflen) {
3848 0 : d_printf("getfacl file %s, incorrect POSIX acl buffer size "
3849 : "(should be %zu, was %zu).\n",
3850 : src,
3851 : expected_buflen,
3852 : rb_size);
3853 0 : return 1;
3854 : }
3855 :
3856 0 : d_printf("# file: %s\n", src);
3857 0 : d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_ex_uid, (unsigned int)sbuf.st_ex_gid);
3858 :
3859 0 : if (num_file_acls == 0 && num_dir_acls == 0) {
3860 0 : d_printf("No acls found.\n");
3861 : }
3862 :
3863 0 : for (i = 0; i < num_file_acls; i++) {
3864 : uint32_t uorg;
3865 : fstring permstring;
3866 0 : unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE));
3867 0 : unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+1);
3868 :
3869 0 : switch(tagtype) {
3870 0 : case SMB_POSIX_ACL_USER_OBJ:
3871 0 : d_printf("user::");
3872 0 : break;
3873 0 : case SMB_POSIX_ACL_USER:
3874 0 : uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3875 0 : d_printf("user:%u:", uorg);
3876 0 : break;
3877 0 : case SMB_POSIX_ACL_GROUP_OBJ:
3878 0 : d_printf("group::");
3879 0 : break;
3880 0 : case SMB_POSIX_ACL_GROUP:
3881 0 : uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3882 0 : d_printf("group:%u:", uorg);
3883 0 : break;
3884 0 : case SMB_POSIX_ACL_MASK:
3885 0 : d_printf("mask::");
3886 0 : break;
3887 0 : case SMB_POSIX_ACL_OTHER:
3888 0 : d_printf("other::");
3889 0 : break;
3890 0 : default:
3891 0 : d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
3892 : src, (unsigned int)tagtype );
3893 0 : SAFE_FREE(retbuf);
3894 0 : return 1;
3895 : }
3896 :
3897 0 : d_printf("%s\n", perms_to_string(permstring, perms));
3898 : }
3899 :
3900 0 : for (i = 0; i < num_dir_acls; i++) {
3901 : uint32_t uorg;
3902 : fstring permstring;
3903 0 : unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE));
3904 0 : unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+1);
3905 :
3906 0 : switch(tagtype) {
3907 0 : case SMB_POSIX_ACL_USER_OBJ:
3908 0 : d_printf("default:user::");
3909 0 : break;
3910 0 : case SMB_POSIX_ACL_USER:
3911 0 : uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3912 0 : d_printf("default:user:%u:", uorg);
3913 0 : break;
3914 0 : case SMB_POSIX_ACL_GROUP_OBJ:
3915 0 : d_printf("default:group::");
3916 0 : break;
3917 0 : case SMB_POSIX_ACL_GROUP:
3918 0 : uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3919 0 : d_printf("default:group:%u:", uorg);
3920 0 : break;
3921 0 : case SMB_POSIX_ACL_MASK:
3922 0 : d_printf("default:mask::");
3923 0 : break;
3924 0 : case SMB_POSIX_ACL_OTHER:
3925 0 : d_printf("default:other::");
3926 0 : break;
3927 0 : default:
3928 0 : d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
3929 : src, (unsigned int)tagtype );
3930 0 : SAFE_FREE(retbuf);
3931 0 : return 1;
3932 : }
3933 :
3934 0 : d_printf("%s\n", perms_to_string(permstring, perms));
3935 : }
3936 :
3937 0 : return 0;
3938 : }
3939 :
3940 : /****************************************************************************
3941 : Get the EA list of a file
3942 : ****************************************************************************/
3943 :
3944 0 : static int cmd_geteas(void)
3945 : {
3946 0 : TALLOC_CTX *ctx = talloc_tos();
3947 0 : char *src = NULL;
3948 0 : char *name = NULL;
3949 0 : char *targetname = NULL;
3950 : struct cli_state *targetcli;
3951 : NTSTATUS status;
3952 : size_t i, num_eas;
3953 : struct ea_struct *eas;
3954 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3955 :
3956 0 : if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
3957 0 : d_printf("geteas filename\n");
3958 0 : return 1;
3959 : }
3960 0 : src = talloc_asprintf(ctx,
3961 : "%s%s",
3962 : client_get_cur_dir(),
3963 : name);
3964 0 : if (!src) {
3965 0 : return 1;
3966 : }
3967 0 : src = client_clean_name(ctx, src);
3968 0 : if (src == NULL) {
3969 0 : return 1;
3970 : }
3971 :
3972 0 : status = cli_resolve_path(ctx, "",
3973 : creds,
3974 : cli, src, &targetcli, &targetname);
3975 0 : if (!NT_STATUS_IS_OK(status)) {
3976 0 : d_printf("stat %s: %s\n", src, nt_errstr(status));
3977 0 : return 1;
3978 : }
3979 :
3980 0 : status = cli_get_ea_list_path(targetcli, targetname, talloc_tos(),
3981 : &num_eas, &eas);
3982 0 : if (!NT_STATUS_IS_OK(status)) {
3983 0 : d_printf("cli_get_ea_list_path: %s\n", nt_errstr(status));
3984 0 : return 1;
3985 : }
3986 :
3987 0 : for (i=0; i<num_eas; i++) {
3988 0 : d_printf("%s (%d) =\n", eas[i].name, (int)eas[i].flags);
3989 0 : dump_data_file(eas[i].value.data, eas[i].value.length, false,
3990 : stdout);
3991 0 : d_printf("\n");
3992 : }
3993 :
3994 0 : TALLOC_FREE(eas);
3995 :
3996 0 : return 0;
3997 : }
3998 :
3999 : /****************************************************************************
4000 : Set an EA of a file
4001 : ****************************************************************************/
4002 :
4003 0 : static int cmd_setea(void)
4004 : {
4005 0 : TALLOC_CTX *ctx = talloc_tos();
4006 0 : char *src = NULL;
4007 0 : char *name = NULL;
4008 0 : char *eaname = NULL;
4009 0 : char *eavalue = NULL;
4010 0 : char *targetname = NULL;
4011 : struct cli_state *targetcli;
4012 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
4013 : NTSTATUS status;
4014 :
4015 0 : if (!next_token_talloc(ctx, &cmd_ptr, &name, NULL)
4016 0 : || !next_token_talloc(ctx, &cmd_ptr, &eaname, NULL)) {
4017 0 : d_printf("setea filename eaname value\n");
4018 0 : return 1;
4019 : }
4020 0 : if (!next_token_talloc(ctx, &cmd_ptr, &eavalue, NULL)) {
4021 0 : eavalue = talloc_strdup(ctx, "");
4022 : }
4023 0 : src = talloc_asprintf(ctx,
4024 : "%s%s",
4025 : client_get_cur_dir(),
4026 : name);
4027 0 : if (!src) {
4028 0 : return 1;
4029 : }
4030 0 : src = client_clean_name(ctx, src);
4031 0 : if (src == NULL) {
4032 0 : return 1;
4033 : }
4034 :
4035 0 : status = cli_resolve_path(ctx, "",
4036 : creds,
4037 : cli, src, &targetcli, &targetname);
4038 0 : if (!NT_STATUS_IS_OK(status)) {
4039 0 : d_printf("stat %s: %s\n", src, nt_errstr(status));
4040 0 : return 1;
4041 : }
4042 :
4043 0 : status = cli_set_ea_path(targetcli, targetname, eaname, eavalue,
4044 : strlen(eavalue));
4045 0 : if (!NT_STATUS_IS_OK(status)) {
4046 0 : d_printf("set_ea %s: %s\n", src, nt_errstr(status));
4047 0 : return 1;
4048 : }
4049 :
4050 0 : return 0;
4051 : }
4052 :
4053 : /****************************************************************************
4054 : UNIX stat.
4055 : ****************************************************************************/
4056 :
4057 0 : static int cmd_stat(void)
4058 : {
4059 0 : TALLOC_CTX *ctx = talloc_tos();
4060 0 : char *src = NULL;
4061 0 : char *name = NULL;
4062 0 : char *targetname = NULL;
4063 : struct cli_state *targetcli;
4064 : fstring mode_str;
4065 : SMB_STRUCT_STAT sbuf;
4066 : struct tm *lt;
4067 : time_t tmp_time;
4068 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
4069 : NTSTATUS status;
4070 :
4071 0 : if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
4072 0 : d_printf("stat file\n");
4073 0 : return 1;
4074 : }
4075 0 : src = talloc_asprintf(ctx,
4076 : "%s%s",
4077 : client_get_cur_dir(),
4078 : name);
4079 0 : if (!src) {
4080 0 : return 1;
4081 : }
4082 0 : src = client_clean_name(ctx, src);
4083 0 : if (src == NULL) {
4084 0 : return 1;
4085 : }
4086 :
4087 0 : status = cli_resolve_path(ctx, "",
4088 : creds,
4089 : cli, src, &targetcli, &targetname);
4090 0 : if (!NT_STATUS_IS_OK(status)) {
4091 0 : d_printf("stat %s: %s\n", src, nt_errstr(status));
4092 0 : return 1;
4093 : }
4094 :
4095 0 : if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
4096 0 : d_printf("Server doesn't support UNIX CIFS calls.\n");
4097 0 : return 1;
4098 : }
4099 :
4100 0 : if (CLI_DIRSEP_CHAR != '/') {
4101 0 : d_printf("Command \"posix\" must be issued before "
4102 : "the \"stat\" command can be used.\n");
4103 0 : return 1;
4104 : }
4105 :
4106 0 : status = cli_posix_stat(targetcli, targetname, &sbuf);
4107 0 : if (!NT_STATUS_IS_OK(status)) {
4108 0 : d_printf("%s stat file %s\n",
4109 : nt_errstr(status), src);
4110 0 : return 1;
4111 : }
4112 :
4113 : /* Print out the stat values. */
4114 0 : d_printf("File: %s\n", src);
4115 0 : d_printf("Size: %-12.0f\tBlocks: %u\t%s\n",
4116 0 : (double)sbuf.st_ex_size,
4117 0 : (unsigned int)sbuf.st_ex_blocks,
4118 : filetype_to_str(sbuf.st_ex_mode));
4119 :
4120 : #if defined(S_ISCHR) && defined(S_ISBLK)
4121 0 : if (S_ISCHR(sbuf.st_ex_mode) || S_ISBLK(sbuf.st_ex_mode)) {
4122 0 : d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n",
4123 0 : (double)sbuf.st_ex_ino,
4124 0 : (unsigned int)sbuf.st_ex_nlink,
4125 : unix_dev_major(sbuf.st_ex_rdev),
4126 : unix_dev_minor(sbuf.st_ex_rdev));
4127 : } else
4128 : #endif
4129 0 : d_printf("Inode: %.0f\tLinks: %u\n",
4130 0 : (double)sbuf.st_ex_ino,
4131 0 : (unsigned int)sbuf.st_ex_nlink);
4132 :
4133 0 : d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n",
4134 0 : ((int)sbuf.st_ex_mode & 0777),
4135 : unix_mode_to_str(mode_str, sbuf.st_ex_mode),
4136 0 : (unsigned int)sbuf.st_ex_uid,
4137 0 : (unsigned int)sbuf.st_ex_gid);
4138 :
4139 0 : tmp_time = convert_timespec_to_time_t(sbuf.st_ex_atime);
4140 0 : lt = localtime(&tmp_time);
4141 0 : if (lt) {
4142 0 : strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
4143 : } else {
4144 0 : fstrcpy(mode_str, "unknown");
4145 : }
4146 0 : d_printf("Access: %s\n", mode_str);
4147 :
4148 0 : tmp_time = convert_timespec_to_time_t(sbuf.st_ex_mtime);
4149 0 : lt = localtime(&tmp_time);
4150 0 : if (lt) {
4151 0 : strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
4152 : } else {
4153 0 : fstrcpy(mode_str, "unknown");
4154 : }
4155 0 : d_printf("Modify: %s\n", mode_str);
4156 :
4157 0 : tmp_time = convert_timespec_to_time_t(sbuf.st_ex_ctime);
4158 0 : lt = localtime(&tmp_time);
4159 0 : if (lt) {
4160 0 : strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
4161 : } else {
4162 0 : fstrcpy(mode_str, "unknown");
4163 : }
4164 0 : d_printf("Change: %s\n", mode_str);
4165 :
4166 0 : return 0;
4167 : }
4168 :
4169 :
4170 : /****************************************************************************
4171 : UNIX chown.
4172 : ****************************************************************************/
4173 :
4174 0 : static int cmd_chown(void)
4175 : {
4176 0 : TALLOC_CTX *ctx = talloc_tos();
4177 0 : char *src = NULL;
4178 : uid_t uid;
4179 : gid_t gid;
4180 : char *buf, *buf2, *buf3;
4181 : struct cli_state *targetcli;
4182 0 : char *targetname = NULL;
4183 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
4184 : NTSTATUS status;
4185 :
4186 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
4187 0 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL) ||
4188 0 : !next_token_talloc(ctx, &cmd_ptr,&buf3,NULL)) {
4189 0 : d_printf("chown uid gid file\n");
4190 0 : return 1;
4191 : }
4192 :
4193 0 : uid = (uid_t)atoi(buf);
4194 0 : gid = (gid_t)atoi(buf2);
4195 :
4196 0 : src = talloc_asprintf(ctx,
4197 : "%s%s",
4198 : client_get_cur_dir(),
4199 : buf3);
4200 0 : if (!src) {
4201 0 : return 1;
4202 : }
4203 0 : src = client_clean_name(ctx, src);
4204 0 : if (src == NULL) {
4205 0 : return 1;
4206 : }
4207 0 : status = cli_resolve_path(ctx, "",
4208 : creds,
4209 : cli, src, &targetcli, &targetname);
4210 0 : if (!NT_STATUS_IS_OK(status)) {
4211 0 : d_printf("chown %s: %s\n", src, nt_errstr(status));
4212 0 : return 1;
4213 : }
4214 :
4215 0 : if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
4216 0 : d_printf("Server doesn't support UNIX CIFS calls.\n");
4217 0 : return 1;
4218 : }
4219 :
4220 0 : if (CLI_DIRSEP_CHAR != '/') {
4221 0 : d_printf("Command \"posix\" must be issued before "
4222 : "the \"chown\" command can be used.\n");
4223 0 : return 1;
4224 : }
4225 :
4226 0 : status = cli_posix_chown(targetcli, targetname, uid, gid);
4227 0 : if (!NT_STATUS_IS_OK(status)) {
4228 0 : d_printf("%s chown file %s uid=%d, gid=%d\n",
4229 : nt_errstr(status), src, (int)uid, (int)gid);
4230 0 : return 1;
4231 : }
4232 :
4233 0 : return 0;
4234 : }
4235 :
4236 : /****************************************************************************
4237 : Rename some file.
4238 : ****************************************************************************/
4239 :
4240 21 : static int cmd_rename(void)
4241 : {
4242 21 : TALLOC_CTX *ctx = talloc_tos();
4243 : char *src, *dest;
4244 : char *buf, *buf2;
4245 : struct cli_state *targetcli;
4246 : char *targetsrc;
4247 : char *targetdest;
4248 21 : struct cli_credentials *creds = samba_cmdline_get_creds();
4249 : NTSTATUS status;
4250 21 : bool replace = false;
4251 :
4252 32 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
4253 21 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
4254 0 : d_printf("rename <src> <dest> [-f]\n");
4255 0 : return 1;
4256 : }
4257 :
4258 21 : src = talloc_asprintf(ctx,
4259 : "%s%s",
4260 : client_get_cur_dir(),
4261 : buf);
4262 21 : if (!src) {
4263 0 : return 1;
4264 : }
4265 21 : src = client_clean_name(ctx, src);
4266 21 : if (src == NULL) {
4267 0 : return 1;
4268 : }
4269 :
4270 21 : dest = talloc_asprintf(ctx,
4271 : "%s%s",
4272 : client_get_cur_dir(),
4273 : buf2);
4274 21 : if (!dest) {
4275 0 : return 1;
4276 : }
4277 21 : dest = client_clean_name(ctx, dest);
4278 21 : if (dest == NULL) {
4279 0 : return 1;
4280 : }
4281 :
4282 25 : if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL) &&
4283 4 : strcsequal(buf, "-f")) {
4284 4 : replace = true;
4285 : }
4286 :
4287 21 : status = cli_resolve_path(ctx, "",
4288 : creds,
4289 : cli, src, &targetcli, &targetsrc);
4290 21 : if (!NT_STATUS_IS_OK(status)) {
4291 0 : d_printf("rename %s: %s\n", src, nt_errstr(status));
4292 0 : return 1;
4293 : }
4294 :
4295 21 : status = cli_resolve_path(ctx, "",
4296 : creds,
4297 : cli, dest, &targetcli, &targetdest);
4298 21 : if (!NT_STATUS_IS_OK(status)) {
4299 0 : d_printf("rename %s: %s\n", dest, nt_errstr(status));
4300 0 : return 1;
4301 : }
4302 :
4303 21 : status = cli_rename(targetcli, targetsrc, targetdest, replace);
4304 21 : if (!NT_STATUS_IS_OK(status)) {
4305 1 : d_printf("%s renaming files %s -> %s \n",
4306 : nt_errstr(status),
4307 : targetsrc,
4308 : targetdest);
4309 1 : return 1;
4310 : }
4311 :
4312 20 : return 0;
4313 : }
4314 :
4315 : struct scopy_timing {
4316 : struct timespec tp_start;
4317 : };
4318 :
4319 0 : static int scopy_status(off_t written, void *priv)
4320 : {
4321 : struct timespec tp_end;
4322 : unsigned int scopy_total_time_ms;
4323 0 : struct scopy_timing *st = priv;
4324 :
4325 0 : clock_gettime_mono(&tp_end);
4326 0 : scopy_total_time_ms = nsec_time_diff(&tp_end,&st->tp_start)/1000000;
4327 :
4328 0 : DEBUG(5,("Copied %jd bytes at an average %3.1f kb/s\n",
4329 : (intmax_t)written, written / (1.024*scopy_total_time_ms)));
4330 :
4331 0 : return true;
4332 : }
4333 :
4334 : /****************************************************************************
4335 : Server-Side copy some file.
4336 : ****************************************************************************/
4337 :
4338 4 : static int cmd_scopy(void)
4339 : {
4340 4 : TALLOC_CTX *ctx = talloc_tos();
4341 : char *src, *dest;
4342 : char *buf, *buf2;
4343 : struct cli_state *targetcli;
4344 : char *targetsrc;
4345 : char *targetdest;
4346 : uint32_t DesiredAccess, ShareAccess, CreateDisposition, CreateOptions;
4347 : struct smb_create_returns cr;
4348 4 : uint16_t destfnum = (uint16_t)-1;
4349 4 : uint16_t srcfnum = (uint16_t)-1;
4350 4 : off_t written = 0;
4351 : struct scopy_timing st;
4352 4 : int rc = 0;
4353 4 : struct cli_credentials *creds = samba_cmdline_get_creds();
4354 : NTSTATUS status;
4355 :
4356 6 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
4357 4 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
4358 0 : d_printf("scopy <src> <dest>\n");
4359 0 : return 1;
4360 : }
4361 :
4362 4 : src = talloc_asprintf(ctx,
4363 : "%s%s",
4364 : client_get_cur_dir(),
4365 : buf);
4366 4 : if (!src) {
4367 0 : return 1;
4368 : }
4369 4 : src = client_clean_name(ctx, src);
4370 4 : if (src == NULL) {
4371 0 : return 1;
4372 : }
4373 :
4374 4 : dest = talloc_asprintf(ctx,
4375 : "%s%s",
4376 : client_get_cur_dir(),
4377 : buf2);
4378 4 : if (!dest) {
4379 0 : return 1;
4380 : }
4381 4 : dest = client_clean_name(ctx, dest);
4382 4 : if (dest == NULL) {
4383 0 : return 1;
4384 : }
4385 :
4386 4 : status = cli_resolve_path(ctx, "",
4387 : creds,
4388 : cli, src, &targetcli, &targetsrc);
4389 4 : if (!NT_STATUS_IS_OK(status)) {
4390 0 : d_printf("scopy %s: %s\n", src, nt_errstr(status));
4391 0 : return 1;
4392 : }
4393 :
4394 4 : status = cli_resolve_path(ctx, "",
4395 : creds,
4396 : cli, dest, &targetcli, &targetdest);
4397 4 : if (!NT_STATUS_IS_OK(status)) {
4398 0 : d_printf("scopy %s: %s\n", dest, nt_errstr(status));
4399 0 : return 1;
4400 : }
4401 :
4402 :
4403 4 : DesiredAccess = (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES|
4404 : READ_CONTROL_ACCESS|SYNCHRONIZE_ACCESS);
4405 4 : ShareAccess = FILE_SHARE_READ|FILE_SHARE_DELETE;
4406 4 : CreateDisposition = FILE_OPEN;
4407 4 : CreateOptions = (FILE_SEQUENTIAL_ONLY|FILE_NON_DIRECTORY_FILE|
4408 : FILE_OPEN_REPARSE_POINT);
4409 4 : status = cli_ntcreate(targetcli, targetsrc, 0, DesiredAccess, 0,
4410 : ShareAccess, CreateDisposition, CreateOptions, 0x0,
4411 : &srcfnum, &cr);
4412 4 : if (!NT_STATUS_IS_OK(status)) {
4413 4 : d_printf("Failed to open file %s. %s\n",
4414 : targetsrc, nt_errstr(status));
4415 4 : return 1;
4416 : }
4417 :
4418 0 : DesiredAccess = (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_READ_EA|
4419 : FILE_WRITE_EA|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|
4420 : DELETE_ACCESS|READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|SYNCHRONIZE_ACCESS);
4421 0 : ShareAccess = FILE_SHARE_NONE;
4422 0 : CreateDisposition = FILE_CREATE;
4423 0 : CreateOptions = FILE_SEQUENTIAL_ONLY|FILE_NON_DIRECTORY_FILE;
4424 0 : status = cli_ntcreate(targetcli, targetdest, 0, DesiredAccess,
4425 : FILE_ATTRIBUTE_ARCHIVE, ShareAccess, CreateDisposition,
4426 : CreateOptions, 0x0, &destfnum, NULL);
4427 0 : if (!NT_STATUS_IS_OK(status)) {
4428 0 : d_printf("Failed to create file %s. %s\n",
4429 : targetdest, nt_errstr(status));
4430 0 : cli_close(targetcli, srcfnum);
4431 0 : return 1;
4432 : }
4433 :
4434 0 : clock_gettime_mono(&st.tp_start);
4435 0 : status = cli_splice(targetcli, targetcli, srcfnum, destfnum,
4436 0 : cr.end_of_file, 0, 0, &written, scopy_status, &st);
4437 0 : if (!NT_STATUS_IS_OK(status)) {
4438 0 : d_printf("%s copying file %s -> %s \n",
4439 : nt_errstr(status),
4440 : targetsrc,
4441 : targetdest);
4442 0 : rc = 1;
4443 : }
4444 :
4445 0 : status = cli_close(targetcli, srcfnum);
4446 0 : if (!NT_STATUS_IS_OK(status)) {
4447 0 : d_printf("Error %s closing remote source file\n", nt_errstr(status));
4448 0 : rc = 1;
4449 : }
4450 0 : status = cli_close(targetcli, destfnum);
4451 0 : if (!NT_STATUS_IS_OK(status)) {
4452 0 : d_printf("Error %s closing remote dest file\n", nt_errstr(status));
4453 0 : rc = 1;
4454 : }
4455 :
4456 0 : return rc;
4457 : }
4458 :
4459 : /****************************************************************************
4460 : Print the volume name.
4461 : ****************************************************************************/
4462 :
4463 4 : static int cmd_volume(void)
4464 : {
4465 : char *volname;
4466 : uint32_t serial_num;
4467 : time_t create_date;
4468 : NTSTATUS status;
4469 :
4470 4 : status = cli_get_fs_volume_info(cli, talloc_tos(),
4471 : &volname, &serial_num,
4472 : &create_date);
4473 4 : if (!NT_STATUS_IS_OK(status)) {
4474 0 : d_printf("Error %s getting volume info\n", nt_errstr(status));
4475 0 : return 1;
4476 : }
4477 :
4478 4 : d_printf("Volume: |%s| serial number 0x%x\n",
4479 : volname, (unsigned int)serial_num);
4480 4 : return 0;
4481 : }
4482 :
4483 : /****************************************************************************
4484 : Hard link files using the NT call.
4485 : ****************************************************************************/
4486 :
4487 4 : static int cmd_hardlink(void)
4488 : {
4489 4 : TALLOC_CTX *ctx = talloc_tos();
4490 : char *src, *dest;
4491 : char *buf, *buf2;
4492 : struct cli_state *targetcli;
4493 : char *targetname;
4494 4 : struct cli_credentials *creds = samba_cmdline_get_creds();
4495 : NTSTATUS status;
4496 :
4497 6 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
4498 4 : !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
4499 0 : d_printf("hardlink <src> <dest>\n");
4500 0 : return 1;
4501 : }
4502 :
4503 4 : src = talloc_asprintf(ctx,
4504 : "%s%s",
4505 : client_get_cur_dir(),
4506 : buf);
4507 4 : if (!src) {
4508 0 : return 1;
4509 : }
4510 4 : src = client_clean_name(ctx, src);
4511 4 : if (src == NULL) {
4512 0 : return 1;
4513 : }
4514 :
4515 4 : dest = talloc_asprintf(ctx,
4516 : "%s%s",
4517 : client_get_cur_dir(),
4518 : buf2);
4519 4 : if (!dest) {
4520 0 : return 1;
4521 : }
4522 4 : dest = client_clean_name(ctx, dest);
4523 4 : if (dest == NULL) {
4524 0 : return 1;
4525 : }
4526 :
4527 4 : status = cli_resolve_path(ctx, "",
4528 : creds,
4529 : cli, src, &targetcli, &targetname);
4530 4 : if (!NT_STATUS_IS_OK(status)) {
4531 0 : d_printf("hardlink %s: %s\n", src, nt_errstr(status));
4532 0 : return 1;
4533 : }
4534 :
4535 4 : status = cli_hardlink(targetcli, targetname, dest);
4536 4 : if (!NT_STATUS_IS_OK(status)) {
4537 0 : d_printf("%s doing an NT hard link of files\n",
4538 : nt_errstr(status));
4539 0 : return 1;
4540 : }
4541 :
4542 4 : return 0;
4543 : }
4544 :
4545 : /****************************************************************************
4546 : Toggle the prompt flag.
4547 : ****************************************************************************/
4548 :
4549 0 : static int cmd_prompt(void)
4550 : {
4551 0 : prompt = !prompt;
4552 0 : DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
4553 0 : return 1;
4554 : }
4555 :
4556 : /****************************************************************************
4557 : Set the newer than time.
4558 : ****************************************************************************/
4559 :
4560 0 : static int cmd_newer(void)
4561 : {
4562 0 : TALLOC_CTX *ctx = talloc_tos();
4563 : char *buf;
4564 : bool ok;
4565 : SMB_STRUCT_STAT sbuf;
4566 :
4567 0 : ok = next_token_talloc(ctx, &cmd_ptr,&buf,NULL);
4568 0 : if (ok && (sys_stat(buf, &sbuf, false) == 0)) {
4569 0 : newer_than = convert_timespec_to_time_t(sbuf.st_ex_mtime);
4570 0 : DEBUG(1,("Getting files newer than %s",
4571 : time_to_asc(newer_than)));
4572 : } else {
4573 0 : newer_than = 0;
4574 : }
4575 :
4576 0 : if (ok && newer_than == 0) {
4577 0 : d_printf("Error setting newer-than time\n");
4578 0 : return 1;
4579 : }
4580 :
4581 0 : return 0;
4582 : }
4583 :
4584 : /****************************************************************************
4585 : Watch directory changes
4586 : ****************************************************************************/
4587 :
4588 0 : static int cmd_notify(void)
4589 : {
4590 0 : TALLOC_CTX *frame = talloc_stackframe();
4591 : char *name, *buf;
4592 : NTSTATUS status;
4593 : uint16_t fnum;
4594 :
4595 0 : name = talloc_strdup(talloc_tos(), client_get_cur_dir());
4596 0 : if (name == NULL) {
4597 0 : goto fail;
4598 : }
4599 0 : if (!next_token_talloc(talloc_tos(), &cmd_ptr, &buf, NULL)) {
4600 0 : goto usage;
4601 : }
4602 0 : name = talloc_asprintf_append(name, "%s", buf);
4603 0 : if (name == NULL) {
4604 0 : goto fail;
4605 : }
4606 0 : name = client_clean_name(talloc_tos(), name);
4607 0 : if (name == NULL) {
4608 0 : return 1;
4609 : }
4610 0 : status = cli_ntcreate(
4611 : cli, name, 0, FILE_READ_DATA, 0,
4612 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4613 : FILE_OPEN, 0, 0, &fnum, NULL);
4614 0 : if (!NT_STATUS_IS_OK(status)) {
4615 0 : d_printf("Could not open file: %s\n", nt_errstr(status));
4616 0 : goto fail;
4617 : }
4618 :
4619 0 : while (1) {
4620 : uint32_t i;
4621 0 : uint32_t num_changes = 0;
4622 0 : struct notify_change *changes = NULL;
4623 :
4624 0 : status = cli_notify(cli, fnum, 1000, FILE_NOTIFY_CHANGE_ALL,
4625 : true,
4626 : talloc_tos(), &num_changes, &changes);
4627 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOTIFY_ENUM_DIR)) {
4628 0 : printf("NOTIFY_ENUM_DIR\n");
4629 0 : status = NT_STATUS_OK;
4630 : }
4631 0 : if (!NT_STATUS_IS_OK(status)) {
4632 0 : d_printf("notify returned %s\n",
4633 : nt_errstr(status));
4634 0 : goto fail;
4635 : }
4636 0 : for (i=0; i<num_changes; i++) {
4637 0 : printf("%4.4x %s\n", changes[i].action,
4638 0 : changes[i].name);
4639 : }
4640 0 : TALLOC_FREE(changes);
4641 : }
4642 0 : usage:
4643 0 : d_printf("notify <dir name>\n");
4644 0 : fail:
4645 0 : TALLOC_FREE(frame);
4646 0 : return 1;
4647 : }
4648 :
4649 : /****************************************************************************
4650 : Set the archive level.
4651 : ****************************************************************************/
4652 :
4653 0 : static int cmd_archive(void)
4654 : {
4655 0 : TALLOC_CTX *ctx = talloc_tos();
4656 : char *buf;
4657 :
4658 0 : if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
4659 0 : archive_level = atoi(buf);
4660 : } else {
4661 0 : d_printf("Archive level is %d\n",archive_level);
4662 : }
4663 :
4664 0 : return 0;
4665 : }
4666 :
4667 : /****************************************************************************
4668 : Toggle the backup_intent state.
4669 : ****************************************************************************/
4670 :
4671 4 : static int cmd_backup(void)
4672 : {
4673 4 : backup_intent = !backup_intent;
4674 4 : cli_set_backup_intent(cli, backup_intent);
4675 4 : DEBUG(2,("backup intent is now %s\n",backup_intent?"on":"off"));
4676 4 : return 1;
4677 : }
4678 :
4679 : /****************************************************************************
4680 : Toggle the lowercaseflag.
4681 : ****************************************************************************/
4682 :
4683 0 : static int cmd_lowercase(void)
4684 : {
4685 0 : lowercase = !lowercase;
4686 0 : DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
4687 0 : return 0;
4688 : }
4689 :
4690 : /****************************************************************************
4691 : Toggle the case sensitive flag.
4692 : ****************************************************************************/
4693 :
4694 0 : static int cmd_setcase(void)
4695 : {
4696 0 : bool orig_case_sensitive = cli_set_case_sensitive(cli, false);
4697 :
4698 0 : cli_set_case_sensitive(cli, !orig_case_sensitive);
4699 0 : DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
4700 : "on":"off"));
4701 0 : return 0;
4702 : }
4703 :
4704 : /****************************************************************************
4705 : Toggle the showacls flag.
4706 : ****************************************************************************/
4707 :
4708 0 : static int cmd_showacls(void)
4709 : {
4710 0 : showacls = !showacls;
4711 0 : DEBUG(2,("showacls is now %s\n",showacls?"on":"off"));
4712 0 : return 0;
4713 : }
4714 :
4715 :
4716 : /****************************************************************************
4717 : Toggle the recurse flag.
4718 : ****************************************************************************/
4719 :
4720 4 : static int cmd_recurse(void)
4721 : {
4722 4 : recurse = !recurse;
4723 4 : DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
4724 4 : return 0;
4725 : }
4726 :
4727 : /****************************************************************************
4728 : Toggle the translate flag.
4729 : ****************************************************************************/
4730 :
4731 0 : static int cmd_translate(void)
4732 : {
4733 0 : translation = !translation;
4734 0 : DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
4735 : translation?"on":"off"));
4736 0 : return 0;
4737 : }
4738 :
4739 : /****************************************************************************
4740 : Do the lcd command.
4741 : ****************************************************************************/
4742 :
4743 36 : static int cmd_lcd(void)
4744 : {
4745 36 : TALLOC_CTX *ctx = talloc_tos();
4746 : char *buf;
4747 : char *d;
4748 :
4749 36 : if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
4750 36 : if (chdir(buf) == -1) {
4751 0 : d_printf("chdir to %s failed (%s)\n",
4752 0 : buf, strerror(errno));
4753 : }
4754 : }
4755 36 : d = sys_getwd();
4756 36 : if (!d) {
4757 0 : return 1;
4758 : }
4759 36 : DEBUG(2,("the local directory is now %s\n",d));
4760 36 : SAFE_FREE(d);
4761 36 : return 0;
4762 : }
4763 :
4764 : /****************************************************************************
4765 : Get a file restarting at end of local file.
4766 : ****************************************************************************/
4767 :
4768 0 : static int cmd_reget(void)
4769 : {
4770 0 : TALLOC_CTX *ctx = talloc_tos();
4771 0 : char *local_name = NULL;
4772 0 : char *remote_name = NULL;
4773 0 : char *fname = NULL;
4774 0 : char *p = NULL;
4775 :
4776 0 : remote_name = talloc_strdup(ctx, client_get_cur_dir());
4777 0 : if (!remote_name) {
4778 0 : return 1;
4779 : }
4780 :
4781 0 : if (!next_token_talloc(ctx, &cmd_ptr, &fname, NULL)) {
4782 0 : d_printf("reget <filename>\n");
4783 0 : return 1;
4784 : }
4785 0 : remote_name = talloc_asprintf_append(remote_name, "%s", fname);
4786 0 : if (!remote_name) {
4787 0 : return 1;
4788 : }
4789 0 : remote_name = client_clean_name(ctx,remote_name);
4790 0 : if (!remote_name) {
4791 0 : return 1;
4792 : }
4793 :
4794 0 : local_name = fname;
4795 0 : next_token_talloc(ctx, &cmd_ptr, &p, NULL);
4796 0 : if (p) {
4797 0 : local_name = p;
4798 : }
4799 :
4800 0 : return do_get(remote_name, local_name, true);
4801 : }
4802 :
4803 : /****************************************************************************
4804 : Put a file restarting at end of local file.
4805 : ****************************************************************************/
4806 :
4807 0 : static int cmd_reput(void)
4808 : {
4809 0 : TALLOC_CTX *ctx = talloc_tos();
4810 0 : char *local_name = NULL;
4811 0 : char *remote_name = NULL;
4812 : char *buf;
4813 : SMB_STRUCT_STAT st;
4814 :
4815 0 : remote_name = talloc_strdup(ctx, client_get_cur_dir());
4816 0 : if (!remote_name) {
4817 0 : return 1;
4818 : }
4819 :
4820 0 : if (!next_token_talloc(ctx, &cmd_ptr, &local_name, NULL)) {
4821 0 : d_printf("reput <filename>\n");
4822 0 : return 1;
4823 : }
4824 :
4825 0 : if (!file_exist_stat(local_name, &st, false)) {
4826 0 : d_printf("%s does not exist\n", local_name);
4827 0 : return 1;
4828 : }
4829 :
4830 0 : if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
4831 0 : remote_name = talloc_asprintf_append(remote_name,
4832 : "%s", buf);
4833 : } else {
4834 0 : remote_name = talloc_asprintf_append(remote_name,
4835 : "%s", local_name);
4836 : }
4837 0 : if (!remote_name) {
4838 0 : return 1;
4839 : }
4840 :
4841 0 : remote_name = client_clean_name(ctx, remote_name);
4842 0 : if (!remote_name) {
4843 0 : return 1;
4844 : }
4845 :
4846 0 : return do_put(remote_name, local_name, true);
4847 : }
4848 :
4849 : /****************************************************************************
4850 : List a share name.
4851 : ****************************************************************************/
4852 :
4853 3227 : static void browse_fn(const char *name, uint32_t m,
4854 : const char *comment, void *state)
4855 : {
4856 3227 : const char *typestr = "";
4857 :
4858 3227 : switch (m & 7) {
4859 3041 : case STYPE_DISKTREE:
4860 3041 : typestr = "Disk";
4861 3041 : break;
4862 155 : case STYPE_PRINTQ:
4863 155 : typestr = "Printer";
4864 155 : break;
4865 0 : case STYPE_DEVICE:
4866 0 : typestr = "Device";
4867 0 : break;
4868 31 : case STYPE_IPC:
4869 31 : typestr = "IPC";
4870 31 : break;
4871 : }
4872 : /* FIXME: If the remote machine returns non-ascii characters
4873 : in any of these fields, they can corrupt the output. We
4874 : should remove them. */
4875 3227 : if (!grepable) {
4876 3227 : d_printf("\t%-15s %-10.10s%s\n",
4877 : name,typestr,comment);
4878 : } else {
4879 0 : d_printf ("%s|%s|%s\n",typestr,name,comment);
4880 : }
4881 3227 : }
4882 :
4883 31 : static bool browse_host_rpc(bool sort)
4884 : {
4885 : NTSTATUS status;
4886 31 : struct rpc_pipe_client *pipe_hnd = NULL;
4887 31 : TALLOC_CTX *frame = talloc_stackframe();
4888 : WERROR werr;
4889 : struct srvsvc_NetShareInfoCtr info_ctr;
4890 : struct srvsvc_NetShareCtr1 ctr1;
4891 31 : uint32_t resume_handle = 0;
4892 31 : uint32_t total_entries = 0;
4893 : uint32_t i;
4894 : struct dcerpc_binding_handle *b;
4895 :
4896 31 : status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc,
4897 : &pipe_hnd);
4898 :
4899 31 : if (!NT_STATUS_IS_OK(status)) {
4900 0 : DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
4901 : nt_errstr(status)));
4902 0 : TALLOC_FREE(frame);
4903 0 : return false;
4904 : }
4905 :
4906 31 : b = pipe_hnd->binding_handle;
4907 :
4908 31 : ZERO_STRUCT(info_ctr);
4909 31 : ZERO_STRUCT(ctr1);
4910 :
4911 31 : info_ctr.level = 1;
4912 31 : info_ctr.ctr.ctr1 = &ctr1;
4913 :
4914 31 : status = dcerpc_srvsvc_NetShareEnumAll(b, frame,
4915 31 : pipe_hnd->desthost,
4916 : &info_ctr,
4917 : 0xffffffff,
4918 : &total_entries,
4919 : &resume_handle,
4920 : &werr);
4921 :
4922 31 : if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
4923 0 : TALLOC_FREE(pipe_hnd);
4924 0 : TALLOC_FREE(frame);
4925 0 : return false;
4926 : }
4927 :
4928 3258 : for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
4929 3227 : struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
4930 3227 : browse_fn(info.name, info.type, info.comment, NULL);
4931 : }
4932 :
4933 31 : TALLOC_FREE(pipe_hnd);
4934 31 : TALLOC_FREE(frame);
4935 31 : return true;
4936 : }
4937 :
4938 : /****************************************************************************
4939 : Try and browse available connections on a host.
4940 : ****************************************************************************/
4941 :
4942 31 : static bool browse_host(bool sort)
4943 : {
4944 : int ret;
4945 :
4946 31 : if (!grepable) {
4947 31 : d_printf("\n\tSharename Type Comment\n");
4948 31 : d_printf("\t--------- ---- -------\n");
4949 : }
4950 :
4951 31 : if (browse_host_rpc(sort)) {
4952 31 : return true;
4953 : }
4954 :
4955 0 : if (smbXcli_conn_protocol(cli->conn) > PROTOCOL_NT1) {
4956 0 : return false;
4957 : }
4958 :
4959 0 : ret = cli_RNetShareEnum(cli, browse_fn, NULL);
4960 0 : if (ret == -1) {
4961 0 : NTSTATUS status = cli_nt_error(cli);
4962 0 : d_printf("Error returning browse list: %s\n",
4963 : nt_errstr(status));
4964 : }
4965 :
4966 0 : return (ret != -1);
4967 : }
4968 :
4969 : /****************************************************************************
4970 : List a server name.
4971 : ****************************************************************************/
4972 :
4973 4 : static void server_fn(const char *name, uint32_t m,
4974 : const char *comment, void *state)
4975 : {
4976 :
4977 4 : if (!grepable){
4978 4 : d_printf("\t%-16s %s\n", name, comment);
4979 : } else {
4980 0 : d_printf("%s|%s|%s\n",(char *)state, name, comment);
4981 : }
4982 4 : }
4983 :
4984 : /****************************************************************************
4985 : Try and browse available connections on a host.
4986 : ****************************************************************************/
4987 :
4988 2 : static bool list_servers(const char *wk_grp)
4989 : {
4990 : fstring state;
4991 :
4992 2 : if (!cli->server_domain)
4993 0 : return false;
4994 :
4995 2 : if (!grepable) {
4996 2 : d_printf("\n\tServer Comment\n");
4997 2 : d_printf("\t--------- -------\n");
4998 : };
4999 2 : fstrcpy( state, "Server" );
5000 2 : cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn,
5001 : state);
5002 :
5003 2 : if (!grepable) {
5004 2 : d_printf("\n\tWorkgroup Master\n");
5005 2 : d_printf("\t--------- -------\n");
5006 : };
5007 :
5008 2 : fstrcpy( state, "Workgroup" );
5009 2 : cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
5010 : server_fn, state);
5011 2 : return true;
5012 : }
5013 :
5014 : /****************************************************************************
5015 : Print or set current VUID
5016 : ****************************************************************************/
5017 :
5018 0 : static int cmd_vuid(void)
5019 : {
5020 0 : TALLOC_CTX *ctx = talloc_tos();
5021 : char *buf;
5022 :
5023 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
5024 0 : d_printf("Current VUID is %d\n",
5025 0 : cli_state_get_uid(cli));
5026 0 : return 0;
5027 : }
5028 :
5029 0 : cli_state_set_uid(cli, atoi(buf));
5030 0 : return 0;
5031 : }
5032 :
5033 : /****************************************************************************
5034 : Setup a new VUID, by issuing a session setup
5035 : ****************************************************************************/
5036 :
5037 0 : static int cmd_logon(void)
5038 : {
5039 0 : TALLOC_CTX *ctx = talloc_tos();
5040 : char *l_username, *l_password;
5041 0 : struct cli_credentials *creds = NULL;
5042 : NTSTATUS nt_status;
5043 :
5044 0 : if (!next_token_talloc(ctx, &cmd_ptr,&l_username,NULL)) {
5045 0 : d_printf("logon <username> [<password>]\n");
5046 0 : return 0;
5047 : }
5048 :
5049 0 : if (!next_token_talloc(ctx, &cmd_ptr,&l_password,NULL)) {
5050 0 : char pwd[256] = {0};
5051 : int rc;
5052 :
5053 0 : rc = samba_getpass("Password: ", pwd, sizeof(pwd), false, false);
5054 0 : if (rc == 0) {
5055 0 : l_password = talloc_strdup(ctx, pwd);
5056 : }
5057 : }
5058 0 : if (!l_password) {
5059 0 : return 1;
5060 : }
5061 :
5062 0 : creds = cli_session_creds_init(ctx,
5063 : l_username,
5064 : lp_workgroup(),
5065 : NULL, /* realm */
5066 : l_password,
5067 : false, /* use_kerberos */
5068 : false, /* fallback_after_kerberos */
5069 : false, /* use_ccache */
5070 : false); /* password_is_nt_hash */
5071 0 : if (creds == NULL) {
5072 0 : d_printf("cli_session_creds_init() failed.\n");
5073 0 : return -1;
5074 : }
5075 0 : nt_status = cli_session_setup_creds(cli, creds);
5076 0 : TALLOC_FREE(creds);
5077 0 : if (!NT_STATUS_IS_OK(nt_status)) {
5078 0 : d_printf("session setup failed: %s\n", nt_errstr(nt_status));
5079 0 : return -1;
5080 : }
5081 :
5082 0 : d_printf("Current VUID is %d\n", cli_state_get_uid(cli));
5083 0 : return 0;
5084 : }
5085 :
5086 : /**
5087 : * close the session
5088 : */
5089 :
5090 0 : static int cmd_logoff(void)
5091 : {
5092 : NTSTATUS status;
5093 :
5094 0 : status = cli_ulogoff(cli);
5095 0 : if (!NT_STATUS_IS_OK(status)) {
5096 0 : d_printf("logoff failed: %s\n", nt_errstr(status));
5097 0 : return -1;
5098 : }
5099 :
5100 0 : d_printf("logoff successful\n");
5101 0 : return 0;
5102 : }
5103 :
5104 :
5105 : /**
5106 : * tree connect (connect to a share)
5107 : */
5108 :
5109 0 : static int cmd_tcon(void)
5110 : {
5111 0 : TALLOC_CTX *ctx = talloc_tos();
5112 : char *sharename;
5113 : NTSTATUS status;
5114 :
5115 0 : if (!next_token_talloc(ctx, &cmd_ptr, &sharename, NULL)) {
5116 0 : d_printf("tcon <sharename>\n");
5117 0 : return 0;
5118 : }
5119 :
5120 0 : if (!sharename) {
5121 0 : return 1;
5122 : }
5123 :
5124 0 : status = cli_tree_connect(cli, sharename, "?????", NULL);
5125 0 : if (!NT_STATUS_IS_OK(status)) {
5126 0 : d_printf("tcon failed: %s\n", nt_errstr(status));
5127 0 : return -1;
5128 : }
5129 :
5130 0 : d_printf("tcon to %s successful, tid: %u\n", sharename,
5131 : cli_state_get_tid(cli));
5132 :
5133 0 : talloc_free(sharename);
5134 :
5135 0 : return 0;
5136 : }
5137 :
5138 : /**
5139 : * tree disconnect (disconnect from a share)
5140 : */
5141 :
5142 0 : static int cmd_tdis(void)
5143 : {
5144 : NTSTATUS status;
5145 :
5146 0 : status = cli_tdis(cli);
5147 0 : if (!NT_STATUS_IS_OK(status)) {
5148 0 : d_printf("tdis failed: %s\n", nt_errstr(status));
5149 0 : return -1;
5150 : }
5151 :
5152 0 : d_printf("tdis successful\n");
5153 0 : return 0;
5154 : }
5155 :
5156 :
5157 : /**
5158 : * get or set tid
5159 : */
5160 :
5161 0 : static int cmd_tid(void)
5162 : {
5163 0 : TALLOC_CTX *ctx = talloc_tos();
5164 : char *tid_str;
5165 :
5166 0 : if (!next_token_talloc(ctx, &cmd_ptr, &tid_str, NULL)) {
5167 0 : if (cli_state_has_tcon(cli)) {
5168 0 : d_printf("current tid is %d\n", cli_state_get_tid(cli));
5169 : } else {
5170 0 : d_printf("no tcon currently\n");
5171 : }
5172 : } else {
5173 0 : uint32_t tid = atoi(tid_str);
5174 0 : if (!cli_state_has_tcon(cli)) {
5175 0 : d_printf("no tcon currently\n");
5176 : }
5177 0 : cli_state_set_tid(cli, tid);
5178 : }
5179 :
5180 0 : return 0;
5181 : }
5182 :
5183 :
5184 : /****************************************************************************
5185 : list active connections
5186 : ****************************************************************************/
5187 :
5188 0 : static int cmd_list_connect(void)
5189 : {
5190 0 : cli_cm_display(cli);
5191 0 : return 0;
5192 : }
5193 :
5194 : /****************************************************************************
5195 : display the current active client connection
5196 : ****************************************************************************/
5197 :
5198 0 : static int cmd_show_connect( void )
5199 : {
5200 0 : TALLOC_CTX *ctx = talloc_tos();
5201 : struct cli_state *targetcli;
5202 : char *targetpath;
5203 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
5204 : NTSTATUS status;
5205 :
5206 0 : status = cli_resolve_path(ctx, "",
5207 : creds,
5208 : cli,
5209 : client_get_cur_dir(), &targetcli,
5210 : &targetpath);
5211 0 : if (!NT_STATUS_IS_OK(status)) {
5212 0 : d_printf("showconnect %s: %s\n", cur_dir, nt_errstr(status));
5213 0 : return 1;
5214 : }
5215 :
5216 0 : d_printf("//%s/%s\n", smbXcli_conn_remote_name(targetcli->conn), targetcli->share);
5217 0 : return 0;
5218 : }
5219 :
5220 : /**
5221 : * cmd_utimes - interactive command to set the four times
5222 : *
5223 : * Read a filename and four times from the client command line and update
5224 : * the file times. A value of -1 for a time means don't change.
5225 : */
5226 4 : static int cmd_utimes(void)
5227 : {
5228 : char *buf;
5229 4 : char *fname = NULL;
5230 4 : struct timespec times[4] = {{0}};
5231 : struct timeval_buf tbuf[4];
5232 4 : int time_count = 0;
5233 4 : int err = 0;
5234 : bool ok;
5235 4 : TALLOC_CTX *ctx = talloc_new(NULL);
5236 : NTSTATUS status;
5237 :
5238 4 : if (ctx == NULL) {
5239 0 : return 1;
5240 : }
5241 :
5242 4 : ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
5243 4 : if (!ok) {
5244 0 : d_printf("utimes <filename> <create-time> <access-time> "
5245 : "<write-time> <change-time>\n");
5246 0 : d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
5247 : "or -1 for no change\n");
5248 0 : err = 1;
5249 0 : goto out;
5250 : }
5251 :
5252 4 : fname = talloc_asprintf(ctx,
5253 : "%s%s",
5254 : client_get_cur_dir(),
5255 : buf);
5256 4 : if (fname == NULL) {
5257 0 : err = 1;
5258 0 : goto out;
5259 : }
5260 4 : fname = client_clean_name(ctx, fname);
5261 4 : if (fname == NULL) {
5262 0 : err = 1;
5263 0 : goto out;
5264 : }
5265 :
5266 22 : while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL) &&
5267 : time_count < 4) {
5268 16 : const char *s = buf;
5269 16 : struct tm tm = {0,};
5270 : time_t t;
5271 : char *ret;
5272 :
5273 16 : if (strlen(s) == 2 && strcmp(s, "-1") == 0) {
5274 8 : times[time_count] = make_omit_timespec();
5275 8 : time_count++;
5276 8 : continue;
5277 : }
5278 :
5279 8 : ret = strptime(s, "%y:%m:%d-%H:%M:%S", &tm);
5280 :
5281 8 : if (ret == NULL) {
5282 4 : ret = strptime(s, "%Y:%m:%d-%H:%M:%S", &tm);
5283 : }
5284 :
5285 : /* We could not match all the chars, so print error */
5286 8 : if (ret == NULL || *ret != 0) {
5287 0 : d_printf("Invalid date format: %s\n", s);
5288 0 : d_printf("utimes <filename> <create-time> "
5289 : "<access-time> <write-time> <change-time>\n");
5290 0 : d_printf("Dates should be in [YY]YY:MM:DD-HH:MM:SS "
5291 : "format or -1 for no change\n");
5292 0 : err = 1;
5293 0 : goto out;
5294 : }
5295 :
5296 : /* Convert tm to a time_t */
5297 8 : t = mktime(&tm);
5298 8 : times[time_count] = (struct timespec){.tv_sec = t};
5299 8 : time_count++;
5300 : }
5301 :
5302 4 : if (time_count < 4) {
5303 0 : d_printf("Insufficient dates: %d\n", time_count);
5304 0 : d_printf("utimes <filename> <create-time> <access-time> "
5305 : "<write-time> <change-time>\n");
5306 0 : d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
5307 : "or -1 for no change\n");
5308 0 : err = 1;
5309 0 : goto out;
5310 : }
5311 :
5312 4 : DEBUG(10, ("times\nCreate: %sAccess: %s Write: %sChange: %s\n",
5313 : timespec_string_buf(×[0], false, &tbuf[0]),
5314 : timespec_string_buf(×[1], false, &tbuf[1]),
5315 : timespec_string_buf(×[2], false, &tbuf[2]),
5316 : timespec_string_buf(×[3], false, &tbuf[3])));
5317 :
5318 4 : status = cli_setpathinfo_ext(
5319 : cli, fname, times[0], times[1], times[2], times[3],
5320 : (uint32_t)-1);
5321 4 : if (!NT_STATUS_IS_OK(status)) {
5322 0 : d_printf("cli_setpathinfo_ext failed: %s\n",
5323 : nt_errstr(status));
5324 0 : err = 1;
5325 0 : goto out;
5326 : }
5327 6 : out:
5328 4 : talloc_free(ctx);
5329 4 : return err;
5330 : }
5331 :
5332 : /**
5333 : * set_remote_attr - set DOS attributes of a remote file
5334 : * @filename: path to the file name
5335 : * @new_attr: attribute bit mask to use
5336 : * @mode: one of ATTR_SET or ATTR_UNSET
5337 : *
5338 : * Update the file attributes with the one provided.
5339 : */
5340 56 : int set_remote_attr(const char *filename, uint32_t new_attr, int mode)
5341 : {
5342 : extern struct cli_state *cli;
5343 : uint32_t old_attr;
5344 : NTSTATUS status;
5345 :
5346 56 : status = cli_getatr(cli, filename, &old_attr, NULL, NULL);
5347 56 : if (!NT_STATUS_IS_OK(status)) {
5348 0 : d_printf("cli_getatr failed: %s\n", nt_errstr(status));
5349 0 : return 1;
5350 : }
5351 :
5352 56 : if (mode == ATTR_SET) {
5353 28 : new_attr |= old_attr;
5354 : } else {
5355 28 : new_attr = old_attr & ~new_attr;
5356 : }
5357 :
5358 56 : status = cli_setatr(cli, filename, new_attr, 0);
5359 56 : if (!NT_STATUS_IS_OK(status)) {
5360 0 : d_printf("cli_setatr failed: %s\n", nt_errstr(status));
5361 0 : return 1;
5362 : }
5363 :
5364 56 : return 0;
5365 : }
5366 :
5367 : /**
5368 : * cmd_setmode - interactive command to set DOS attributes
5369 : *
5370 : * Read a filename and mode from the client command line and update
5371 : * the file DOS attributes.
5372 : */
5373 28 : int cmd_setmode(void)
5374 : {
5375 : char *buf;
5376 28 : char *fname = NULL;
5377 28 : uint32_t attr[2] = {0};
5378 28 : int mode = ATTR_SET;
5379 28 : int err = 0;
5380 : bool ok;
5381 28 : TALLOC_CTX *ctx = talloc_new(NULL);
5382 28 : if (ctx == NULL) {
5383 0 : return 1;
5384 : }
5385 :
5386 28 : ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
5387 28 : if (!ok) {
5388 0 : d_printf("setmode <filename> <[+|-]rsha>\n");
5389 0 : err = 1;
5390 0 : goto out;
5391 : }
5392 :
5393 28 : fname = talloc_asprintf(ctx,
5394 : "%s%s",
5395 : client_get_cur_dir(),
5396 : buf);
5397 28 : if (fname == NULL) {
5398 0 : err = 1;
5399 0 : goto out;
5400 : }
5401 28 : fname = client_clean_name(ctx, fname);
5402 28 : if (fname == NULL) {
5403 0 : err = 1;
5404 0 : goto out;
5405 : }
5406 :
5407 82 : while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
5408 40 : const char *s = buf;
5409 :
5410 152 : while (*s) {
5411 92 : switch (*s++) {
5412 16 : case '+':
5413 16 : mode = ATTR_SET;
5414 16 : break;
5415 24 : case '-':
5416 24 : mode = ATTR_UNSET;
5417 24 : break;
5418 8 : case 'r':
5419 8 : attr[mode] |= FILE_ATTRIBUTE_READONLY;
5420 8 : break;
5421 8 : case 'h':
5422 8 : attr[mode] |= FILE_ATTRIBUTE_HIDDEN;
5423 8 : break;
5424 8 : case 's':
5425 8 : attr[mode] |= FILE_ATTRIBUTE_SYSTEM;
5426 8 : break;
5427 28 : case 'a':
5428 28 : attr[mode] |= FILE_ATTRIBUTE_ARCHIVE;
5429 28 : break;
5430 0 : default:
5431 0 : d_printf("setmode <filename> <perm=[+|-]rsha>\n");
5432 0 : err = 1;
5433 0 : goto out;
5434 : }
5435 : }
5436 : }
5437 :
5438 28 : if (attr[ATTR_SET] == 0 && attr[ATTR_UNSET] == 0) {
5439 0 : d_printf("setmode <filename> <[+|-]rsha>\n");
5440 0 : err = 1;
5441 0 : goto out;
5442 : }
5443 :
5444 28 : DEBUG(2, ("perm set %d %d\n", attr[ATTR_SET], attr[ATTR_UNSET]));
5445 :
5446 : /* ignore return value: server might not store DOS attributes */
5447 28 : set_remote_attr(fname, attr[ATTR_SET], ATTR_SET);
5448 28 : set_remote_attr(fname, attr[ATTR_UNSET], ATTR_UNSET);
5449 28 : out:
5450 28 : talloc_free(ctx);
5451 28 : return err;
5452 : }
5453 :
5454 : /****************************************************************************
5455 : iosize command
5456 : ***************************************************************************/
5457 :
5458 0 : int cmd_iosize(void)
5459 : {
5460 0 : TALLOC_CTX *ctx = talloc_tos();
5461 : char *buf;
5462 : int iosize;
5463 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
5464 0 : bool smb_encrypt =
5465 0 : (cli_credentials_get_smb_encryption(creds) ==
5466 : SMB_ENCRYPTION_REQUIRED);
5467 :
5468 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
5469 0 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
5470 0 : if (!smb_encrypt) {
5471 0 : d_printf("iosize <n> or iosize 0x<n>. "
5472 : "Minimum is 0 (default), "
5473 : "max is 16776960 (0xFFFF00)\n");
5474 : } else {
5475 0 : d_printf("iosize <n> or iosize 0x<n>. "
5476 : "(Encrypted connection) ,"
5477 : "Minimum is 0 (default), "
5478 : "max is 130048 (0x1FC00)\n");
5479 : }
5480 : } else {
5481 0 : d_printf("iosize <n> or iosize 0x<n>.\n");
5482 : }
5483 0 : return 1;
5484 : }
5485 :
5486 0 : iosize = strtol(buf,NULL,0);
5487 0 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
5488 0 : if (smb_encrypt && (iosize < 0 || iosize > 0xFC00)) {
5489 0 : d_printf("iosize out of range for encrypted "
5490 : "connection (min = 0 (default), "
5491 : "max = 130048 (0x1FC00)\n");
5492 0 : return 1;
5493 0 : } else if (!smb_encrypt && (iosize < 0 || iosize > 0xFFFF00)) {
5494 0 : d_printf("iosize out of range (min = 0 (default), "
5495 : "max = 16776960 (0xFFFF00)\n");
5496 0 : return 1;
5497 : }
5498 : }
5499 :
5500 0 : io_bufsize = iosize;
5501 0 : d_printf("iosize is now %d\n", io_bufsize);
5502 0 : return 0;
5503 : }
5504 :
5505 : /****************************************************************************
5506 : timeout command
5507 : ***************************************************************************/
5508 :
5509 0 : static int cmd_timeout(void)
5510 : {
5511 0 : TALLOC_CTX *ctx = talloc_tos();
5512 : char *buf;
5513 :
5514 0 : if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
5515 0 : unsigned int old_timeout = cli_set_timeout(cli, 0);
5516 0 : cli_set_timeout(cli, old_timeout);
5517 0 : d_printf("timeout <n> (per-operation timeout "
5518 : "in seconds - currently %u).\n",
5519 : old_timeout/1000);
5520 0 : return 1;
5521 : }
5522 :
5523 0 : io_timeout = strtol(buf,NULL,0);
5524 0 : cli_set_timeout(cli, io_timeout*1000);
5525 0 : d_printf("io_timeout per operation is now %d\n", io_timeout);
5526 0 : return 0;
5527 : }
5528 :
5529 :
5530 : /****************************************************************************
5531 : history
5532 : ****************************************************************************/
5533 0 : static int cmd_history(void)
5534 : {
5535 : #if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
5536 : HIST_ENTRY **hlist;
5537 : int i;
5538 :
5539 0 : hlist = history_list();
5540 :
5541 0 : for (i = 0; hlist && hlist[i]; i++) {
5542 0 : DEBUG(0, ("%d: %s\n", i, hlist[i]->line));
5543 : }
5544 : #else
5545 : DEBUG(0,("no history without readline support\n"));
5546 : #endif
5547 :
5548 0 : return 0;
5549 : }
5550 :
5551 : /* Some constants for completing filename arguments */
5552 :
5553 : #define COMPL_NONE 0 /* No completions */
5554 : #define COMPL_REMOTE 1 /* Complete remote filename */
5555 : #define COMPL_LOCAL 2 /* Complete local filename */
5556 :
5557 : /* This defines the commands supported by this client.
5558 : * NOTE: The "!" must be the last one in the list because it's fn pointer
5559 : * field is NULL, and NULL in that field is used in process_tok()
5560 : * (below) to indicate the end of the list. crh
5561 : */
5562 : static struct {
5563 : const char *name;
5564 : int (*fn)(void);
5565 : const char *description;
5566 : char compl_args[2]; /* Completion argument info */
5567 : } commands[] = {
5568 : {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
5569 : {"allinfo",cmd_allinfo,"<file> show all available info",
5570 : {COMPL_REMOTE,COMPL_NONE}},
5571 : {"altname",cmd_altname,"<file> show alt name",{COMPL_REMOTE,COMPL_NONE}},
5572 : {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
5573 : {"backup",cmd_backup,"toggle backup intent state",{COMPL_NONE,COMPL_NONE}},
5574 : {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
5575 : {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
5576 : {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
5577 : {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
5578 : {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_NONE}},
5579 : {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_NONE}},
5580 : {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_NONE}},
5581 : {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
5582 : {"deltree",cmd_deltree,"<mask> recursively delete all matching files and directories",{COMPL_REMOTE,COMPL_NONE}},
5583 : {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
5584 : {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
5585 : {"echo",cmd_echo,"ping the server",{COMPL_NONE,COMPL_NONE}},
5586 : {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
5587 : {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
5588 : {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_NONE}},
5589 : {"geteas", cmd_geteas, "<file name> get the EA list of a file",
5590 : {COMPL_REMOTE, COMPL_NONE}},
5591 : {"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
5592 : {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
5593 : {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
5594 : {"iosize",cmd_iosize,"iosize <number> (default 64512)",{COMPL_NONE,COMPL_NONE}},
5595 : {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
5596 : {"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
5597 : {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
5598 : {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
5599 : {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
5600 : {"l",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
5601 : {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
5602 : {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
5603 : {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
5604 : {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
5605 : {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
5606 : {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
5607 : {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
5608 : {"notify",cmd_notify,"<file>Get notified of dir changes",{COMPL_REMOTE,COMPL_NONE}},
5609 : {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
5610 : {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
5611 : {"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
5612 : {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
5613 : {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
5614 : {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
5615 : {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
5616 : {"posix_whoami",cmd_posix_whoami,"return logged on user information "
5617 : "using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
5618 : {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
5619 : {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
5620 : {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
5621 : {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
5622 : {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
5623 : {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
5624 : {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
5625 : {"readlink",cmd_readlink,"filename Do a UNIX extensions readlink call on a symlink",{COMPL_REMOTE,COMPL_REMOTE}},
5626 : {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
5627 : {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
5628 : {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
5629 : {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
5630 : {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
5631 : {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
5632 : {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_REMOTE,COMPL_NONE}},
5633 : {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}},
5634 : {"setea", cmd_setea, "<file name> <eaname> <eaval> Set an EA of a file",
5635 : {COMPL_REMOTE, COMPL_LOCAL}},
5636 : {"setmode",cmd_setmode,"<file name> <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
5637 : {"scopy",cmd_scopy,"<src> <dest> server-side copy file",{COMPL_REMOTE,COMPL_REMOTE}},
5638 : {"stat",cmd_stat,"<file name> Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_NONE}},
5639 : {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
5640 : {"tar",cmd_tar,"tar <c|x>[IXFvbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
5641 : {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
5642 : {"timeout",cmd_timeout,"timeout <number> - set the per-operation timeout in seconds (default 20)",{COMPL_NONE,COMPL_NONE}},
5643 : {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
5644 : {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
5645 : {"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
5646 : {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
5647 : {"wdel",cmd_wdel,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
5648 : {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
5649 : {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
5650 : {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
5651 : {"tcon",cmd_tcon,"connect to a share" ,{COMPL_NONE,COMPL_NONE}},
5652 : {"tdis",cmd_tdis,"disconnect from a share",{COMPL_NONE,COMPL_NONE}},
5653 : {"tid",cmd_tid,"show or set the current tid (tree-id)",{COMPL_NONE,COMPL_NONE}},
5654 : {"utimes", cmd_utimes,"<file name> <create_time> <access_time> <mod_time> "
5655 : "<ctime> set times", {COMPL_REMOTE,COMPL_NONE}},
5656 : {"logoff",cmd_logoff,"log off (close the session)",{COMPL_NONE,COMPL_NONE}},
5657 : {"..",cmd_cd_oneup,"change the remote directory (up one level)",{COMPL_REMOTE,COMPL_NONE}},
5658 :
5659 : /* Yes, this must be here, see crh's comment above. */
5660 : {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
5661 : {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
5662 : };
5663 :
5664 : /*******************************************************************
5665 : Lookup a command string in the list of commands, including
5666 : abbreviations.
5667 : ******************************************************************/
5668 :
5669 1502 : static int process_tok(char *tok)
5670 : {
5671 1502 : size_t i = 0, matches = 0;
5672 1502 : size_t cmd=0;
5673 1502 : size_t tok_len = strlen(tok);
5674 :
5675 57089 : while (commands[i].fn != NULL) {
5676 56282 : if (strequal(commands[i].name,tok)) {
5677 1486 : matches = 1;
5678 1486 : cmd = i;
5679 1486 : break;
5680 54796 : } else if (strnequal(commands[i].name, tok, tok_len)) {
5681 16 : matches++;
5682 16 : cmd = i;
5683 : }
5684 54796 : i++;
5685 : }
5686 :
5687 1502 : if (matches == 0)
5688 0 : return(-1);
5689 1502 : else if (matches == 1)
5690 1502 : return(cmd);
5691 : else
5692 0 : return(-2);
5693 : }
5694 :
5695 : /****************************************************************************
5696 : Help.
5697 : ****************************************************************************/
5698 :
5699 0 : static int cmd_help(void)
5700 : {
5701 0 : TALLOC_CTX *ctx = talloc_tos();
5702 0 : int i=0,j;
5703 : char *buf;
5704 :
5705 0 : if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
5706 0 : if ((i = process_tok(buf)) >= 0)
5707 0 : d_printf("HELP %s:\n\t%s\n\n",
5708 : commands[i].name,commands[i].description);
5709 : } else {
5710 0 : while (commands[i].description) {
5711 0 : for (j=0; commands[i].description && (j<5); j++) {
5712 0 : d_printf("%-15s",commands[i].name);
5713 0 : i++;
5714 : }
5715 0 : d_printf("\n");
5716 : }
5717 : }
5718 0 : return 0;
5719 : }
5720 :
5721 : /****************************************************************************
5722 : Process a -c command string.
5723 : ****************************************************************************/
5724 :
5725 585 : static int process_command_string(const char *cmd_in)
5726 : {
5727 585 : TALLOC_CTX *ctx = talloc_tos();
5728 585 : char *cmd = talloc_strdup(ctx, cmd_in);
5729 585 : int rc = 0;
5730 585 : struct cli_credentials *creds = samba_cmdline_get_creds();
5731 :
5732 585 : if (!cmd) {
5733 0 : return 1;
5734 : }
5735 : /* establish the connection if not already */
5736 :
5737 585 : if (!cli) {
5738 : NTSTATUS status;
5739 :
5740 0 : status = cli_cm_open(talloc_tos(), NULL,
5741 : desthost,
5742 : service,
5743 : creds,
5744 0 : have_ip ? &dest_ss : NULL, port,
5745 : name_type,
5746 : &cli);
5747 0 : if (!NT_STATUS_IS_OK(status)) {
5748 0 : return 1;
5749 : }
5750 0 : cli_set_timeout(cli, io_timeout*1000);
5751 : }
5752 :
5753 1227 : while (cmd[0] != '\0') {
5754 : char *line;
5755 : char *p;
5756 : char *tok;
5757 : int i;
5758 :
5759 593 : if ((p = strchr_m(cmd, ';')) == 0) {
5760 585 : line = cmd;
5761 585 : cmd += strlen(cmd);
5762 : } else {
5763 8 : *p = '\0';
5764 8 : line = cmd;
5765 8 : cmd = p + 1;
5766 : }
5767 :
5768 : /* and get the first part of the command */
5769 593 : cmd_ptr = line;
5770 593 : if (!next_token_talloc(ctx, &cmd_ptr,&tok,NULL)) {
5771 0 : continue;
5772 : }
5773 :
5774 593 : if ((i = process_tok(tok)) >= 0) {
5775 593 : rc = commands[i].fn();
5776 0 : } else if (i == -2) {
5777 0 : d_printf("%s: command abbreviation ambiguous\n",tok);
5778 : } else {
5779 0 : d_printf("%s: command not found\n",tok);
5780 : }
5781 : }
5782 :
5783 304 : return rc;
5784 : }
5785 :
5786 : #define MAX_COMPLETIONS 100
5787 :
5788 : struct completion_remote {
5789 : char *dirmask;
5790 : char **matches;
5791 : int count, samelen;
5792 : const char *text;
5793 : int len;
5794 : };
5795 :
5796 0 : static NTSTATUS completion_remote_filter(struct file_info *f,
5797 : const char *mask,
5798 : void *state)
5799 : {
5800 0 : struct completion_remote *info = (struct completion_remote *)state;
5801 :
5802 0 : if (info->count >= MAX_COMPLETIONS - 1) {
5803 0 : return NT_STATUS_OK;
5804 : }
5805 0 : if (strncmp(info->text, f->name, info->len) != 0) {
5806 0 : return NT_STATUS_OK;
5807 : }
5808 0 : if (ISDOT(f->name) || ISDOTDOT(f->name)) {
5809 0 : return NT_STATUS_OK;
5810 : }
5811 :
5812 0 : if ((info->dirmask[0] == 0) && !(f->attr & FILE_ATTRIBUTE_DIRECTORY))
5813 0 : info->matches[info->count] = SMB_STRDUP(f->name);
5814 : else {
5815 0 : TALLOC_CTX *ctx = talloc_stackframe();
5816 : char *tmp;
5817 :
5818 0 : tmp = talloc_strdup(ctx,info->dirmask);
5819 0 : if (!tmp) {
5820 0 : TALLOC_FREE(ctx);
5821 0 : return NT_STATUS_NO_MEMORY;
5822 : }
5823 0 : tmp = talloc_asprintf_append(tmp, "%s", f->name);
5824 0 : if (!tmp) {
5825 0 : TALLOC_FREE(ctx);
5826 0 : return NT_STATUS_NO_MEMORY;
5827 : }
5828 0 : if (f->attr & FILE_ATTRIBUTE_DIRECTORY) {
5829 0 : tmp = talloc_asprintf_append(tmp, "%s",
5830 : CLI_DIRSEP_STR);
5831 : }
5832 0 : if (!tmp) {
5833 0 : TALLOC_FREE(ctx);
5834 0 : return NT_STATUS_NO_MEMORY;
5835 : }
5836 0 : info->matches[info->count] = SMB_STRDUP(tmp);
5837 0 : TALLOC_FREE(ctx);
5838 : }
5839 0 : if (info->matches[info->count] == NULL) {
5840 0 : return NT_STATUS_OK;
5841 : }
5842 0 : if (f->attr & FILE_ATTRIBUTE_DIRECTORY) {
5843 0 : smb_readline_ca_char(0);
5844 : }
5845 0 : if (info->count == 1) {
5846 0 : info->samelen = strlen(info->matches[info->count]);
5847 : } else {
5848 0 : while (strncmp(info->matches[info->count],
5849 0 : info->matches[info->count-1],
5850 0 : info->samelen) != 0) {
5851 0 : info->samelen--;
5852 : }
5853 : }
5854 0 : info->count++;
5855 0 : return NT_STATUS_OK;
5856 : }
5857 :
5858 0 : static char **remote_completion(const char *text, int len)
5859 : {
5860 0 : TALLOC_CTX *ctx = talloc_stackframe();
5861 0 : char *dirmask = NULL;
5862 0 : char *targetpath = NULL;
5863 0 : struct cli_state *targetcli = NULL;
5864 : int i;
5865 0 : struct completion_remote info = { NULL, NULL, 1, 0, NULL, 0 };
5866 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
5867 : NTSTATUS status;
5868 :
5869 : /* can't have non-static initialisation on Sun CC, so do it
5870 : at run time here */
5871 0 : info.samelen = len;
5872 0 : info.text = text;
5873 0 : info.len = len;
5874 :
5875 0 : info.matches = SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS);
5876 0 : if (!info.matches) {
5877 0 : TALLOC_FREE(ctx);
5878 0 : return NULL;
5879 : }
5880 :
5881 : /*
5882 : * We're leaving matches[0] free to fill it later with the text to
5883 : * display: Either the one single match or the longest common subset
5884 : * of the matches.
5885 : */
5886 0 : info.matches[0] = NULL;
5887 0 : info.count = 1;
5888 :
5889 0 : for (i = len-1; i >= 0; i--) {
5890 0 : if ((text[i] == '/') || (text[i] == CLI_DIRSEP_CHAR)) {
5891 : break;
5892 : }
5893 : }
5894 :
5895 0 : info.text = text+i+1;
5896 0 : info.samelen = info.len = len-i-1;
5897 :
5898 0 : if (i > 0) {
5899 0 : info.dirmask = SMB_MALLOC_ARRAY(char, i+2);
5900 0 : if (!info.dirmask) {
5901 0 : goto cleanup;
5902 : }
5903 0 : strncpy(info.dirmask, text, i+1);
5904 0 : info.dirmask[i+1] = 0;
5905 0 : dirmask = talloc_asprintf(ctx,
5906 : "%s%*s*",
5907 : client_get_cur_dir(),
5908 : i-1,
5909 : text);
5910 : } else {
5911 0 : info.dirmask = SMB_STRDUP("");
5912 0 : if (!info.dirmask) {
5913 0 : goto cleanup;
5914 : }
5915 0 : dirmask = talloc_asprintf(ctx,
5916 : "%s*",
5917 : client_get_cur_dir());
5918 : }
5919 0 : if (!dirmask) {
5920 0 : goto cleanup;
5921 : }
5922 0 : dirmask = client_clean_name(ctx, dirmask);
5923 0 : if (dirmask == NULL) {
5924 0 : goto cleanup;
5925 : }
5926 :
5927 0 : status = cli_resolve_path(ctx, "",
5928 : creds,
5929 : cli, dirmask, &targetcli, &targetpath);
5930 0 : if (!NT_STATUS_IS_OK(status)) {
5931 0 : goto cleanup;
5932 : }
5933 0 : status = cli_list(targetcli, targetpath, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
5934 : completion_remote_filter, (void *)&info);
5935 0 : if (!NT_STATUS_IS_OK(status)) {
5936 0 : goto cleanup;
5937 : }
5938 :
5939 0 : if (info.count == 1) {
5940 : /*
5941 : * No matches at all, NULL indicates there is nothing
5942 : */
5943 0 : SAFE_FREE(info.matches[0]);
5944 0 : SAFE_FREE(info.matches);
5945 0 : TALLOC_FREE(ctx);
5946 0 : return NULL;
5947 : }
5948 :
5949 0 : if (info.count == 2) {
5950 : /*
5951 : * Exactly one match in matches[1], indicate this is the one
5952 : * in matches[0].
5953 : */
5954 0 : info.matches[0] = info.matches[1];
5955 0 : info.matches[1] = NULL;
5956 0 : info.count -= 1;
5957 0 : TALLOC_FREE(ctx);
5958 0 : return info.matches;
5959 : }
5960 :
5961 : /*
5962 : * We got more than one possible match, set the result to the maximum
5963 : * common subset
5964 : */
5965 :
5966 0 : info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
5967 0 : info.matches[info.count] = NULL;
5968 0 : TALLOC_FREE(ctx);
5969 0 : return info.matches;
5970 :
5971 0 : cleanup:
5972 0 : for (i = 0; i < info.count; i++) {
5973 0 : SAFE_FREE(info.matches[i]);
5974 : }
5975 0 : SAFE_FREE(info.matches);
5976 0 : SAFE_FREE(info.dirmask);
5977 0 : TALLOC_FREE(ctx);
5978 0 : return NULL;
5979 : }
5980 :
5981 0 : static char **completion_fn(const char *text, int start, int end)
5982 : {
5983 0 : smb_readline_ca_char(' ');
5984 :
5985 0 : if (start) {
5986 : const char *buf, *sp;
5987 : int i;
5988 : char compl_type;
5989 :
5990 0 : buf = smb_readline_get_line_buffer();
5991 0 : if (buf == NULL)
5992 0 : return NULL;
5993 :
5994 0 : sp = strchr(buf, ' ');
5995 0 : if (sp == NULL)
5996 0 : return NULL;
5997 :
5998 0 : for (i = 0; commands[i].name; i++) {
5999 0 : if ((strncmp(commands[i].name, buf, sp - buf) == 0) &&
6000 0 : (commands[i].name[sp - buf] == 0)) {
6001 0 : break;
6002 : }
6003 : }
6004 0 : if (commands[i].name == NULL)
6005 0 : return NULL;
6006 :
6007 0 : while (*sp == ' ')
6008 0 : sp++;
6009 :
6010 0 : if (sp == (buf + start))
6011 0 : compl_type = commands[i].compl_args[0];
6012 : else
6013 0 : compl_type = commands[i].compl_args[1];
6014 :
6015 0 : if (compl_type == COMPL_REMOTE)
6016 0 : return remote_completion(text, end - start);
6017 : else /* fall back to local filename completion */
6018 0 : return NULL;
6019 : } else {
6020 : char **matches;
6021 0 : size_t i, len, samelen = 0, count=1;
6022 :
6023 0 : matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
6024 0 : if (!matches) {
6025 0 : return NULL;
6026 : }
6027 0 : matches[0] = NULL;
6028 :
6029 0 : len = strlen(text);
6030 0 : for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
6031 0 : if (strncmp(text, commands[i].name, len) == 0) {
6032 0 : matches[count] = SMB_STRDUP(commands[i].name);
6033 0 : if (!matches[count])
6034 0 : goto cleanup;
6035 0 : if (count == 1)
6036 0 : samelen = strlen(matches[count]);
6037 : else
6038 0 : while (strncmp(matches[count], matches[count-1], samelen) != 0)
6039 0 : samelen--;
6040 0 : count++;
6041 : }
6042 : }
6043 :
6044 0 : switch (count) {
6045 0 : case 0: /* should never happen */
6046 : case 1:
6047 0 : goto cleanup;
6048 0 : case 2:
6049 0 : matches[0] = SMB_STRDUP(matches[1]);
6050 0 : break;
6051 0 : default:
6052 0 : matches[0] = (char *)SMB_MALLOC(samelen+1);
6053 0 : if (!matches[0])
6054 0 : goto cleanup;
6055 0 : strncpy(matches[0], matches[1], samelen);
6056 0 : matches[0][samelen] = 0;
6057 : }
6058 0 : matches[count] = NULL;
6059 0 : return matches;
6060 :
6061 0 : cleanup:
6062 0 : for (i = 0; i < count; i++)
6063 0 : free(matches[i]);
6064 :
6065 0 : free(matches);
6066 0 : return NULL;
6067 : }
6068 : }
6069 :
6070 : static bool finished;
6071 :
6072 : /****************************************************************************
6073 : Make sure we swallow keepalives during idle time.
6074 : ****************************************************************************/
6075 :
6076 0 : static void readline_callback(void)
6077 : {
6078 : static time_t last_t;
6079 : struct timespec now;
6080 : time_t t;
6081 : NTSTATUS status;
6082 : unsigned char garbage[16];
6083 :
6084 0 : clock_gettime_mono(&now);
6085 0 : t = now.tv_sec;
6086 :
6087 0 : if (t - last_t < 5)
6088 0 : return;
6089 :
6090 0 : last_t = t;
6091 :
6092 : /* Ping the server to keep the connection alive using SMBecho. */
6093 0 : memset(garbage, 0xf0, sizeof(garbage));
6094 0 : status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
6095 0 : if (NT_STATUS_IS_OK(status) ||
6096 0 : NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
6097 : /*
6098 : * Even if server returns NT_STATUS_INVALID_PARAMETER
6099 : * it still responded.
6100 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13007
6101 : */
6102 0 : return;
6103 : }
6104 :
6105 0 : if (!cli_state_is_connected(cli)) {
6106 0 : DEBUG(0,("SMBecho failed (%s). The connection is "
6107 : "disconnected now\n", nt_errstr(status)));
6108 0 : finished = true;
6109 0 : smb_readline_done();
6110 : }
6111 : }
6112 :
6113 : /****************************************************************************
6114 : Process commands on stdin.
6115 : ****************************************************************************/
6116 :
6117 233 : static int process_stdin(void)
6118 : {
6119 233 : int rc = 0;
6120 :
6121 233 : if (!quiet) {
6122 229 : d_printf("Try \"help\" to get a list of possible commands.\n");
6123 : }
6124 :
6125 1042 : while (!finished) {
6126 925 : TALLOC_CTX *frame = talloc_stackframe();
6127 925 : char *tok = NULL;
6128 925 : char *the_prompt = NULL;
6129 925 : char *line = NULL;
6130 : int i;
6131 :
6132 : /* display a prompt */
6133 925 : if (asprintf(&the_prompt, "smb: %s> ", client_get_cur_dir()) < 0) {
6134 0 : TALLOC_FREE(frame);
6135 16 : break;
6136 : }
6137 925 : line = smb_readline(the_prompt, readline_callback, completion_fn);
6138 925 : SAFE_FREE(the_prompt);
6139 925 : if (!line) {
6140 16 : TALLOC_FREE(frame);
6141 16 : break;
6142 : }
6143 :
6144 : /* special case - first char is ! */
6145 909 : if (*line == '!') {
6146 0 : if (system(line + 1) == -1) {
6147 0 : d_printf("system() command %s failed.\n",
6148 : line+1);
6149 : }
6150 0 : SAFE_FREE(line);
6151 0 : TALLOC_FREE(frame);
6152 0 : continue;
6153 : }
6154 :
6155 : /* and get the first part of the command */
6156 909 : cmd_ptr = line;
6157 909 : if (!next_token_talloc(frame, &cmd_ptr,&tok,NULL)) {
6158 0 : TALLOC_FREE(frame);
6159 0 : SAFE_FREE(line);
6160 0 : continue;
6161 : }
6162 :
6163 909 : if ((i = process_tok(tok)) >= 0) {
6164 909 : rc = commands[i].fn();
6165 0 : } else if (i == -2) {
6166 0 : d_printf("%s: command abbreviation ambiguous\n",tok);
6167 : } else {
6168 0 : d_printf("%s: command not found\n",tok);
6169 : }
6170 692 : SAFE_FREE(line);
6171 692 : TALLOC_FREE(frame);
6172 : }
6173 16 : return rc;
6174 : }
6175 :
6176 : /****************************************************************************
6177 : Process commands from the client.
6178 : ****************************************************************************/
6179 :
6180 1108 : static int process(const char *base_directory)
6181 : {
6182 1108 : int rc = 0;
6183 : NTSTATUS status;
6184 1108 : struct cli_credentials *creds = samba_cmdline_get_creds();
6185 :
6186 1704 : status = cli_cm_open(talloc_tos(), NULL,
6187 : desthost,
6188 : service,
6189 : creds,
6190 1108 : have_ip ? &dest_ss : NULL, port,
6191 : name_type, &cli);
6192 1108 : if (!NT_STATUS_IS_OK(status)) {
6193 290 : return 1;
6194 : }
6195 :
6196 818 : cli_set_timeout(cli, io_timeout*1000);
6197 :
6198 818 : if (base_directory && *base_directory) {
6199 0 : rc = do_cd(base_directory);
6200 0 : if (rc) {
6201 0 : cli_shutdown(cli);
6202 0 : return rc;
6203 : }
6204 : }
6205 :
6206 818 : if (cmdstr) {
6207 585 : rc = process_command_string(cmdstr);
6208 : } else {
6209 233 : process_stdin();
6210 : }
6211 :
6212 320 : cli_shutdown(cli);
6213 320 : return rc;
6214 : }
6215 :
6216 : /****************************************************************************
6217 : Handle a -L query.
6218 : ****************************************************************************/
6219 :
6220 39 : static int do_host_query(const char *query_host)
6221 : {
6222 : NTSTATUS status;
6223 39 : struct cli_credentials *creds = samba_cmdline_get_creds();
6224 :
6225 62 : status = cli_cm_open(talloc_tos(), NULL,
6226 : query_host,
6227 : "IPC$",
6228 : creds,
6229 39 : have_ip ? &dest_ss : NULL, port,
6230 : name_type, &cli);
6231 39 : if (!NT_STATUS_IS_OK(status)) {
6232 8 : return 1;
6233 : }
6234 :
6235 31 : cli_set_timeout(cli, io_timeout*1000);
6236 31 : browse_host(true);
6237 :
6238 : /* Ensure that the host can do IPv4 */
6239 :
6240 31 : if (!interpret_addr(query_host)) {
6241 : struct sockaddr_storage ss;
6242 23 : if (interpret_string_addr(&ss, query_host, 0) &&
6243 0 : (ss.ss_family != AF_INET)) {
6244 0 : d_printf("%s is an IPv6 address -- no workgroup available\n",
6245 : query_host);
6246 0 : return 1;
6247 : }
6248 : }
6249 :
6250 31 : if (lp_client_min_protocol() > PROTOCOL_NT1) {
6251 21 : d_printf("SMB1 disabled -- no workgroup available\n");
6252 21 : goto out;
6253 : }
6254 :
6255 10 : if (lp_disable_netbios()) {
6256 0 : d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
6257 0 : goto out;
6258 : }
6259 :
6260 20 : if (port != NBT_SMB_PORT ||
6261 10 : smbXcli_conn_protocol(cli->conn) > PROTOCOL_NT1)
6262 : {
6263 : /*
6264 : * Workgroups simply don't make sense over anything
6265 : * else but port 139 and SMB1.
6266 : */
6267 :
6268 10 : cli_shutdown(cli);
6269 10 : d_printf("Reconnecting with SMB1 for workgroup listing.\n");
6270 10 : lp_set_cmdline("client max protocol", "NT1");
6271 15 : status = cli_cm_open(talloc_tos(), NULL,
6272 : query_host,
6273 : "IPC$",
6274 : creds,
6275 10 : have_ip ? &dest_ss : NULL, NBT_SMB_PORT,
6276 : name_type, &cli);
6277 10 : if (!NT_STATUS_IS_OK(status)) {
6278 8 : d_printf("Unable to connect with SMB1 "
6279 : "-- no workgroup available\n");
6280 8 : return 0;
6281 : }
6282 : }
6283 :
6284 2 : cli_set_timeout(cli, io_timeout*1000);
6285 2 : list_servers(lp_workgroup());
6286 23 : out:
6287 23 : cli_shutdown(cli);
6288 :
6289 23 : return(0);
6290 : }
6291 :
6292 : /****************************************************************************
6293 : Handle a tar operation.
6294 : ****************************************************************************/
6295 :
6296 0 : static int do_tar_op(const char *base_directory)
6297 : {
6298 0 : struct tar *tar_ctx = tar_get_ctx();
6299 0 : int ret = 0;
6300 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
6301 :
6302 : /* do we already have a connection? */
6303 0 : if (!cli) {
6304 : NTSTATUS status;
6305 :
6306 0 : status = cli_cm_open(talloc_tos(), NULL,
6307 : desthost,
6308 : service,
6309 : creds,
6310 0 : have_ip ? &dest_ss : NULL, port,
6311 : name_type, &cli);
6312 0 : if (!NT_STATUS_IS_OK(status)) {
6313 0 : ret = 1;
6314 0 : goto out;
6315 : }
6316 0 : cli_set_timeout(cli, io_timeout*1000);
6317 : }
6318 :
6319 0 : recurse = true;
6320 :
6321 0 : if (base_directory && *base_directory) {
6322 0 : ret = do_cd(base_directory);
6323 0 : if (ret) {
6324 0 : goto out_cli;
6325 : }
6326 : }
6327 :
6328 0 : ret = tar_process(tar_ctx);
6329 :
6330 0 : out_cli:
6331 0 : cli_shutdown(cli);
6332 0 : out:
6333 0 : return ret;
6334 : }
6335 :
6336 : /****************************************************************************
6337 : Handle a message operation.
6338 : ****************************************************************************/
6339 :
6340 8 : static int do_message_op(struct cli_credentials *creds)
6341 : {
6342 : NTSTATUS status;
6343 :
6344 8 : if (lp_disable_netbios()) {
6345 0 : d_printf("NetBIOS over TCP disabled.\n");
6346 0 : return 1;
6347 : }
6348 :
6349 16 : status = cli_connect_nb(desthost, have_ip ? &dest_ss : NULL,
6350 8 : port ? port : NBT_SMB_PORT, name_type,
6351 : lp_netbios_name(),
6352 : SMB_SIGNING_OFF,
6353 : 0,
6354 : &cli);
6355 8 : if (!NT_STATUS_IS_OK(status)) {
6356 0 : d_printf("Connection to %s failed. Error %s\n", desthost, nt_errstr(status));
6357 0 : return 1;
6358 : }
6359 :
6360 8 : cli_set_timeout(cli, io_timeout*1000);
6361 8 : send_message(cli_credentials_get_username(creds));
6362 8 : cli_shutdown(cli);
6363 :
6364 8 : return 0;
6365 : }
6366 :
6367 : /****************************************************************************
6368 : main program
6369 : ****************************************************************************/
6370 :
6371 1155 : int main(int argc,char *argv[])
6372 : {
6373 1155 : const char **const_argv = discard_const_p(const char *, argv);
6374 1155 : char *base_directory = NULL;
6375 : int opt;
6376 1155 : char *query_host = NULL;
6377 1155 : bool message = false;
6378 : static const char *new_name_resolve_order = NULL;
6379 : poptContext pc;
6380 : char *p;
6381 1155 : int rc = 0;
6382 1155 : bool tar_opt = false;
6383 1155 : bool service_opt = false;
6384 1155 : struct tar *tar_ctx = tar_get_ctx();
6385 : bool ok;
6386 :
6387 6930 : struct poptOption long_options[] = {
6388 : POPT_AUTOHELP
6389 :
6390 : {
6391 : .longName = "message",
6392 : .shortName = 'M',
6393 : .argInfo = POPT_ARG_STRING,
6394 : .arg = NULL,
6395 : .val = 'M',
6396 : .descrip = "Send message",
6397 : .argDescrip = "HOST",
6398 : },
6399 : {
6400 : .longName = "ip-address",
6401 : .shortName = 'I',
6402 : .argInfo = POPT_ARG_STRING,
6403 : .arg = NULL,
6404 : .val = 'I',
6405 : .descrip = "Use this IP to connect to",
6406 : .argDescrip = "IP",
6407 : },
6408 : {
6409 : .longName = "stderr",
6410 : .shortName = 'E',
6411 : .argInfo = POPT_ARG_NONE,
6412 : .arg = NULL,
6413 : .val = 'E',
6414 : .descrip = "Write messages to stderr instead of stdout",
6415 : },
6416 : {
6417 : .longName = "list",
6418 : .shortName = 'L',
6419 : .argInfo = POPT_ARG_STRING,
6420 : .arg = NULL,
6421 : .val = 'L',
6422 : .descrip = "Get a list of shares available on a host",
6423 : .argDescrip = "HOST",
6424 : },
6425 : {
6426 : .longName = "tar",
6427 : .shortName = 'T',
6428 : .argInfo = POPT_ARG_STRING,
6429 : .arg = NULL,
6430 : .val = 'T',
6431 : .descrip = "Command line tar",
6432 : .argDescrip = "<c|x>IXFvgbNan",
6433 : },
6434 : {
6435 : .longName = "directory",
6436 : .shortName = 'D',
6437 : .argInfo = POPT_ARG_STRING,
6438 : .arg = NULL,
6439 : .val = 'D',
6440 : .descrip = "Start from directory",
6441 : .argDescrip = "DIR",
6442 : },
6443 : {
6444 : .longName = "command",
6445 : .shortName = 'c',
6446 : .argInfo = POPT_ARG_STRING,
6447 : .arg = &cmdstr,
6448 : .val = 'c',
6449 : .descrip = "Execute semicolon separated commands",
6450 : },
6451 : {
6452 : .longName = "send-buffer",
6453 : .shortName = 'b',
6454 : .argInfo = POPT_ARG_INT,
6455 : .arg = &io_bufsize,
6456 : .val = 'b',
6457 : .descrip = "Changes the transmit/send buffer",
6458 : .argDescrip = "BYTES",
6459 : },
6460 : {
6461 : .longName = "timeout",
6462 : .shortName = 't',
6463 : .argInfo = POPT_ARG_INT,
6464 : .arg = &io_timeout,
6465 : .val = 'b',
6466 : .descrip = "Changes the per-operation timeout",
6467 : .argDescrip = "SECONDS",
6468 : },
6469 : {
6470 : .longName = "port",
6471 : .shortName = 'p',
6472 : .argInfo = POPT_ARG_INT,
6473 : .arg = &port,
6474 : .val = 'p',
6475 : .descrip = "Port to connect to",
6476 : .argDescrip = "PORT",
6477 : },
6478 : {
6479 : .longName = "grepable",
6480 : .shortName = 'g',
6481 : .argInfo = POPT_ARG_NONE,
6482 : .arg = NULL,
6483 : .val = 'g',
6484 : .descrip = "Produce grepable output",
6485 : },
6486 : {
6487 : .longName = "quiet",
6488 : .shortName = 'q',
6489 : .argInfo = POPT_ARG_NONE,
6490 : .arg = NULL,
6491 : .val = 'q',
6492 : .descrip = "Suppress help message",
6493 : },
6494 : {
6495 : .longName = "browse",
6496 : .shortName = 'B',
6497 : .argInfo = POPT_ARG_NONE,
6498 : .arg = NULL,
6499 : .val = 'B',
6500 : .descrip = "Browse SMB servers using DNS",
6501 : },
6502 1155 : POPT_COMMON_SAMBA
6503 1155 : POPT_COMMON_CONNECTION
6504 1155 : POPT_COMMON_CREDENTIALS
6505 1155 : POPT_LEGACY_S3
6506 1155 : POPT_COMMON_VERSION
6507 : POPT_TABLEEND
6508 : };
6509 1155 : TALLOC_CTX *frame = talloc_stackframe();
6510 1155 : struct cli_credentials *creds = NULL;
6511 :
6512 1155 : if (!client_set_cur_dir("\\")) {
6513 0 : exit(ENOMEM);
6514 : }
6515 :
6516 1155 : smb_init_locale();
6517 :
6518 1155 : ok = samba_cmdline_init(frame,
6519 : SAMBA_CMDLINE_CONFIG_CLIENT,
6520 : false /* require_smbconf */);
6521 1155 : if (!ok) {
6522 0 : DBG_ERR("Failed to init cmdline parser!\n");
6523 0 : exit(ENOMEM);
6524 : }
6525 1155 : lp_set_cmdline("log level", "1");
6526 :
6527 : /* skip argv(0) */
6528 1155 : pc = samba_popt_get_context(getprogname(),
6529 : argc,
6530 : const_argv,
6531 : long_options,
6532 : 0);
6533 1155 : if (pc == NULL) {
6534 0 : DBG_ERR("Failed to setup popt context!\n");
6535 0 : exit(1);
6536 : }
6537 :
6538 1155 : poptSetOtherOptionHelp(pc, "[OPTIONS] service <password>");
6539 :
6540 1155 : creds = samba_cmdline_get_creds();
6541 1986 : while ((opt = poptGetNextOpt(pc)) != -1) {
6542 :
6543 : /*
6544 : * if the tar option has been called previously, now
6545 : * we need to eat out the leftovers
6546 : */
6547 : /* I see no other way to keep things sane --SSS */
6548 1813 : if (tar_opt == true) {
6549 0 : while (poptPeekArg(pc)) {
6550 0 : poptGetArg(pc);
6551 : }
6552 0 : tar_opt = false;
6553 : }
6554 :
6555 : /* if the service has not yet been specified lets see if it is available in the popt stack */
6556 1813 : if (!service_opt && poptPeekArg(pc)) {
6557 1047 : service = talloc_strdup(frame, poptGetArg(pc));
6558 1047 : if (!service) {
6559 0 : exit(ENOMEM);
6560 : }
6561 1047 : service_opt = true;
6562 : }
6563 :
6564 : /* if the service has already been retrieved then check if we have also a password */
6565 3473 : if (service_opt &&
6566 2331 : cli_credentials_get_password(creds) == NULL &&
6567 671 : poptPeekArg(pc)) {
6568 0 : cli_credentials_set_password(creds,
6569 : poptGetArg(pc),
6570 : CRED_SPECIFIED);
6571 : }
6572 :
6573 :
6574 1813 : switch (opt) {
6575 8 : case 'M':
6576 : /* Messages are sent to NetBIOS name type 0x3
6577 : * (Messenger Service). Make sure we default
6578 : * to port 139 instead of port 445. srl,crh
6579 : */
6580 8 : name_type = 0x03;
6581 8 : desthost = talloc_strdup(frame,poptGetOptArg(pc));
6582 8 : if (!desthost) {
6583 0 : exit(ENOMEM);
6584 : }
6585 8 : if( !port )
6586 8 : port = NBT_SMB_PORT;
6587 8 : message = true;
6588 8 : break;
6589 629 : case 'I':
6590 : {
6591 629 : if (!interpret_string_addr(&dest_ss, poptGetOptArg(pc), 0)) {
6592 0 : exit(1);
6593 : }
6594 629 : have_ip = true;
6595 629 : print_sockaddr(dest_ss_str, sizeof(dest_ss_str), &dest_ss);
6596 : }
6597 629 : break;
6598 8 : case 'E':
6599 8 : setup_logging("smbclient", DEBUG_STDERR );
6600 8 : display_set_stderr();
6601 8 : break;
6602 :
6603 39 : case 'L':
6604 39 : query_host = talloc_strdup(frame, poptGetOptArg(pc));
6605 39 : if (!query_host) {
6606 0 : exit(ENOMEM);
6607 : }
6608 39 : break;
6609 0 : case 'T':
6610 : /* We must use old option processing for this. Find the
6611 : * position of the -T option in the raw argv[]. */
6612 0 : {
6613 : int i;
6614 :
6615 0 : for (i = 1; i < argc; i++) {
6616 0 : if (strncmp("-T", argv[i],2)==0)
6617 0 : break;
6618 : }
6619 0 : i++;
6620 0 : if (tar_parse_args(tar_ctx, poptGetOptArg(pc),
6621 0 : const_argv + i, argc - i)) {
6622 0 : poptPrintUsage(pc, stderr, 0);
6623 0 : exit(1);
6624 : }
6625 : }
6626 : /* this must be the last option, mark we have parsed it so that we know we have */
6627 0 : tar_opt = true;
6628 0 : break;
6629 0 : case 'D':
6630 0 : base_directory = talloc_strdup(frame, poptGetOptArg(pc));
6631 0 : if (!base_directory) {
6632 0 : exit(ENOMEM);
6633 : }
6634 0 : break;
6635 0 : case 'g':
6636 0 : grepable=true;
6637 0 : break;
6638 8 : case 'q':
6639 8 : quiet=true;
6640 8 : break;
6641 0 : case 'B':
6642 0 : return(do_smb_browse());
6643 0 : case POPT_ERROR_BADOPT:
6644 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
6645 : poptBadOption(pc, 0), poptStrerror(opt));
6646 0 : poptPrintUsage(pc, stderr, 0);
6647 0 : exit(1);
6648 : }
6649 : }
6650 :
6651 : /* We may still have some leftovers after the last popt option has been called */
6652 1155 : if (tar_opt == true) {
6653 0 : while (poptPeekArg(pc)) {
6654 0 : poptGetArg(pc);
6655 : }
6656 0 : tar_opt = false;
6657 : }
6658 :
6659 : /* if the service has not yet been specified lets see if it is available in the popt stack */
6660 1155 : if (!service_opt && poptPeekArg(pc)) {
6661 61 : service = talloc_strdup(frame,poptGetArg(pc));
6662 61 : if (!service) {
6663 0 : exit(ENOMEM);
6664 : }
6665 61 : service_opt = true;
6666 : }
6667 :
6668 : /* if the service has already been retrieved then check if we have also a password */
6669 2263 : if (service_opt &&
6670 1362 : cli_credentials_get_password(creds) == NULL &&
6671 254 : poptPeekArg(pc)) {
6672 0 : cli_credentials_set_password(creds,
6673 : poptGetArg(pc),
6674 : CRED_SPECIFIED);
6675 : }
6676 :
6677 1155 : if (service_opt && service) {
6678 : size_t len;
6679 :
6680 : /* Convert any '/' characters in the service name to '\' characters */
6681 1108 : string_replace(service, '/','\\');
6682 1108 : if (count_chars(service,'\\') < 3) {
6683 0 : d_printf("\n%s: Not enough '\\' characters in service\n",service);
6684 0 : poptPrintUsage(pc, stderr, 0);
6685 0 : exit(1);
6686 : }
6687 : /* Remove trailing slashes */
6688 1108 : len = strlen(service);
6689 1704 : while(len > 0 && service[len - 1] == '\\') {
6690 0 : --len;
6691 0 : service[len] = '\0';
6692 : }
6693 : }
6694 :
6695 1155 : if(new_name_resolve_order)
6696 0 : lp_set_cmdline("name resolve order", new_name_resolve_order);
6697 :
6698 1155 : if (!tar_to_process(tar_ctx) && !query_host && !service && !message) {
6699 0 : poptPrintUsage(pc, stderr, 0);
6700 0 : exit(1);
6701 : }
6702 :
6703 1155 : poptFreeContext(pc);
6704 1155 : samba_cmdline_burn(argc, argv);
6705 :
6706 1155 : DEBUG(3,("Client started (version %s).\n", samba_version_string()));
6707 :
6708 1155 : if (tar_to_process(tar_ctx)) {
6709 0 : if (cmdstr)
6710 0 : process_command_string(cmdstr);
6711 0 : rc = do_tar_op(base_directory);
6712 1194 : } else if (query_host && *query_host) {
6713 39 : char *qhost = query_host;
6714 : char *slash;
6715 :
6716 62 : while (*qhost == '\\' || *qhost == '/')
6717 0 : qhost++;
6718 :
6719 39 : if ((slash = strchr_m(qhost, '/'))
6720 39 : || (slash = strchr_m(qhost, '\\'))) {
6721 0 : *slash = 0;
6722 : }
6723 :
6724 39 : if ((p=strchr_m(qhost, '#'))) {
6725 0 : *p = 0;
6726 0 : p++;
6727 0 : sscanf(p, "%x", &name_type);
6728 : }
6729 :
6730 39 : rc = do_host_query(qhost);
6731 1116 : } else if (message) {
6732 8 : rc = do_message_op(creds);
6733 1108 : } else if (process(base_directory)) {
6734 303 : rc = 1;
6735 : }
6736 :
6737 657 : TALLOC_FREE(frame);
6738 657 : return rc;
6739 : }
|