~ubuntu-branches/ubuntu/oneiric/samba/oneiric-security

« back to all changes in this revision

Viewing changes to .pc/security-CVE-2011-0719.patch/source3/client/client.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2011-03-10 10:03:01 UTC
  • mfrom: (0.39.11 sid)
  • Revision ID: james.westby@ubuntu.com-20110310100301-jfjg41wv0iq05zj4
Tags: 2:3.5.8~dfsg-1ubuntu1
* Merge from debian unstable.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access. 
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/mksmbpasswd.awk:
    - Do not add user with UID less than 1000 to smbpasswd
  + debian/control:
    - Make libwbclient0 replace/conflict with hardy's likewise-open.
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
    - Add cuups breaks to push the package to aslo upgrade cups (LP: #639768)
  + debian/rules:
    - enable "native" PIE hardening.
    - Add BIND_NOW to maximize benefit of RELRO hardening.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
    - Don't ship the /etc/network/if-up.d file.
  + debian/samba.postinst: 
    - Fixed bashism.
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/samba.logrotate: Make it upstart compatible
  + debian/samba-common.dhcp: Fix typo to get a proper parsing in
    /etc/samba/dhcp.
  + Dropped:
    - debian/patches/fix-windows7-print-connection.patch: Merged upstream.
    - debian/patches/security-CVE-2011-0719.patch: Merged upstream. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 "client/client_proto.h"
26
 
#include "../librpc/gen_ndr/cli_srvsvc.h"
27
 
 
28
 
#ifndef REGISTER
29
 
#define REGISTER 0
30
 
#endif
31
 
 
32
 
extern int do_smb_browse(void); /* mDNS browsing */
33
 
 
34
 
extern bool AllowDebugChange;
35
 
extern bool override_logfile;
36
 
extern char tar_type;
37
 
 
38
 
static int port = 0;
39
 
static char *service;
40
 
static char *desthost;
41
 
static char *calling_name;
42
 
static bool grepable = false;
43
 
static char *cmdstr = NULL;
44
 
const char *cmd_ptr = NULL;
45
 
 
46
 
static int io_bufsize = 524288;
47
 
 
48
 
static int name_type = 0x20;
49
 
static int max_protocol = PROTOCOL_NT1;
50
 
 
51
 
static int process_tok(char *tok);
52
 
static int cmd_help(void);
53
 
 
54
 
#define CREATE_ACCESS_READ READ_CONTROL_ACCESS
55
 
 
56
 
/* 30 second timeout on most commands */
57
 
#define CLIENT_TIMEOUT (30*1000)
58
 
#define SHORT_TIMEOUT (5*1000)
59
 
 
60
 
/* value for unused fid field in trans2 secondary request */
61
 
#define FID_UNUSED (0xFFFF)
62
 
 
63
 
time_t newer_than = 0;
64
 
static int archive_level = 0;
65
 
 
66
 
static bool translation = false;
67
 
static bool have_ip;
68
 
 
69
 
/* clitar bits insert */
70
 
extern int blocksize;
71
 
extern bool tar_inc;
72
 
extern bool tar_reset;
73
 
/* clitar bits end */
74
 
 
75
 
static bool prompt = true;
76
 
 
77
 
static bool recurse = false;
78
 
static bool showacls = false;
79
 
bool lowercase = false;
80
 
 
81
 
static struct sockaddr_storage dest_ss;
82
 
static char dest_ss_str[INET6_ADDRSTRLEN];
83
 
 
84
 
#define SEPARATORS " \t\n\r"
85
 
 
86
 
static bool abort_mget = true;
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
 
/* encrypted state. */
98
 
static bool smb_encrypt;
99
 
 
100
 
/* root cli_state connection */
101
 
 
102
 
struct cli_state *cli;
103
 
 
104
 
static char CLI_DIRSEP_CHAR = '\\';
105
 
static char CLI_DIRSEP_STR[] = { '\\', '\0' };
106
 
 
107
 
/* Authentication for client connections. */
108
 
struct user_auth_info *auth_info;
109
 
 
110
 
/* Accessor functions for directory paths. */
111
 
static char *fileselection;
112
 
static const char *client_get_fileselection(void)
113
 
{
114
 
        if (fileselection) {
115
 
                return fileselection;
116
 
        }
117
 
        return "";
118
 
}
119
 
 
120
 
static const char *client_set_fileselection(const char *new_fs)
121
 
{
122
 
        SAFE_FREE(fileselection);
123
 
        if (new_fs) {
124
 
                fileselection = SMB_STRDUP(new_fs);
125
 
        }
126
 
        return client_get_fileselection();
127
 
}
128
 
 
129
 
static char *cwd;
130
 
static const char *client_get_cwd(void)
131
 
{
132
 
        if (cwd) {
133
 
                return cwd;
134
 
        }
135
 
        return CLI_DIRSEP_STR;
136
 
}
137
 
 
138
 
static const char *client_set_cwd(const char *new_cwd)
139
 
{
140
 
        SAFE_FREE(cwd);
141
 
        if (new_cwd) {
142
 
                cwd = SMB_STRDUP(new_cwd);
143
 
        }
144
 
        return client_get_cwd();
145
 
}
146
 
 
147
 
static char *cur_dir;
148
 
const char *client_get_cur_dir(void)
149
 
{
150
 
        if (cur_dir) {
151
 
                return cur_dir;
152
 
        }
153
 
        return CLI_DIRSEP_STR;
154
 
}
155
 
 
156
 
const char *client_set_cur_dir(const char *newdir)
157
 
{
158
 
        SAFE_FREE(cur_dir);
159
 
        if (newdir) {
160
 
                cur_dir = SMB_STRDUP(newdir);
161
 
        }
162
 
        return client_get_cur_dir();
163
 
}
164
 
 
165
 
/****************************************************************************
166
 
 Write to a local file with CR/LF->LF translation if appropriate. Return the
167
 
 number taken from the buffer. This may not equal the number written.
168
 
****************************************************************************/
169
 
 
170
 
static int writefile(int f, char *b, int n)
171
 
{
172
 
        int i;
173
 
 
174
 
        if (!translation) {
175
 
                return write(f,b,n);
176
 
        }
177
 
 
178
 
        i = 0;
179
 
        while (i < n) {
180
 
                if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
181
 
                        b++;i++;
182
 
                }
183
 
                if (write(f, b, 1) != 1) {
184
 
                        break;
185
 
                }
186
 
                b++;
187
 
                i++;
188
 
        }
189
 
 
190
 
        return(i);
191
 
}
192
 
 
193
 
/****************************************************************************
194
 
 Read from a file with LF->CR/LF translation if appropriate. Return the
195
 
 number read. read approx n bytes.
196
 
****************************************************************************/
197
 
 
198
 
static int readfile(uint8_t *b, int n, XFILE *f)
199
 
{
200
 
        int i;
201
 
        int c;
202
 
 
203
 
        if (!translation)
204
 
                return x_fread(b,1,n,f);
205
 
 
206
 
        i = 0;
207
 
        while (i < (n - 1) && (i < BUFFER_SIZE)) {
208
 
                if ((c = x_getc(f)) == EOF) {
209
 
                        break;
210
 
                }
211
 
 
212
 
                if (c == '\n') { /* change all LFs to CR/LF */
213
 
                        b[i++] = '\r';
214
 
                }
215
 
 
216
 
                b[i++] = c;
217
 
        }
218
 
 
219
 
        return(i);
220
 
}
221
 
 
222
 
struct push_state {
223
 
        XFILE *f;
224
 
        SMB_OFF_T nread;
225
 
};
226
 
 
227
 
static size_t push_source(uint8_t *buf, size_t n, void *priv)
228
 
{
229
 
        struct push_state *state = (struct push_state *)priv;
230
 
        int result;
231
 
 
232
 
        if (x_feof(state->f)) {
233
 
                return 0;
234
 
        }
235
 
 
236
 
        result = readfile(buf, n, state->f);
237
 
        state->nread += result;
238
 
        return result;
239
 
}
240
 
 
241
 
/****************************************************************************
242
 
 Send a message.
243
 
****************************************************************************/
244
 
 
245
 
static void send_message(const char *username)
246
 
{
247
 
        char buf[1600];
248
 
        NTSTATUS status;
249
 
        int i;
250
 
 
251
 
        d_printf("Type your message, ending it with a Control-D\n");
252
 
 
253
 
        i = 0;
254
 
        while (i<sizeof(buf)-2) {
255
 
                int c = fgetc(stdin);
256
 
                if (c == EOF) {
257
 
                        break;
258
 
                }
259
 
                if (c == '\n') {
260
 
                        buf[i++] = '\r';
261
 
                }
262
 
                buf[i++] = c;
263
 
        }
264
 
        buf[i] = '\0';
265
 
 
266
 
        status = cli_message(cli, desthost, username, buf);
267
 
        if (!NT_STATUS_IS_OK(status)) {
268
 
                d_fprintf(stderr, "cli_message returned %s\n",
269
 
                          nt_errstr(status));
270
 
        }
271
 
}
272
 
 
273
 
/****************************************************************************
274
 
 Check the space on a device.
275
 
****************************************************************************/
276
 
 
277
 
static int do_dskattr(void)
278
 
{
279
 
        int total, bsize, avail;
280
 
        struct cli_state *targetcli = NULL;
281
 
        char *targetpath = NULL;
282
 
        TALLOC_CTX *ctx = talloc_tos();
283
 
 
284
 
        if ( !cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(), &targetcli, &targetpath)) {
285
 
                d_printf("Error in dskattr: %s\n", cli_errstr(cli));
286
 
                return 1;
287
 
        }
288
 
 
289
 
        if (!NT_STATUS_IS_OK(cli_dskattr(targetcli, &bsize, &total, &avail))) {
290
 
                d_printf("Error in dskattr: %s\n",cli_errstr(targetcli));
291
 
                return 1;
292
 
        }
293
 
 
294
 
        d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
295
 
                 total, bsize, avail);
296
 
 
297
 
        return 0;
298
 
}
299
 
 
300
 
/****************************************************************************
301
 
 Show cd/pwd.
302
 
****************************************************************************/
303
 
 
304
 
static int cmd_pwd(void)
305
 
{
306
 
        d_printf("Current directory is %s",service);
307
 
        d_printf("%s\n",client_get_cur_dir());
308
 
        return 0;
309
 
}
310
 
 
311
 
/****************************************************************************
312
 
 Ensure name has correct directory separators.
313
 
****************************************************************************/
314
 
 
315
 
static void normalize_name(char *newdir)
316
 
{
317
 
        if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
318
 
                string_replace(newdir,'/','\\');
319
 
        }
320
 
}
321
 
 
322
 
/****************************************************************************
323
 
 Change directory - inner section.
324
 
****************************************************************************/
325
 
 
326
 
static int do_cd(const char *new_dir)
327
 
{
328
 
        char *newdir = NULL;
329
 
        char *saved_dir = NULL;
330
 
        char *new_cd = NULL;
331
 
        char *targetpath = NULL;
332
 
        struct cli_state *targetcli = NULL;
333
 
        SMB_STRUCT_STAT sbuf;
334
 
        uint32 attributes;
335
 
        int ret = 1;
336
 
        TALLOC_CTX *ctx = talloc_stackframe();
337
 
 
338
 
        newdir = talloc_strdup(ctx, new_dir);
339
 
        if (!newdir) {
340
 
                TALLOC_FREE(ctx);
341
 
                return 1;
342
 
        }
343
 
 
344
 
        normalize_name(newdir);
345
 
 
346
 
        /* Save the current directory in case the new directory is invalid */
347
 
 
348
 
        saved_dir = talloc_strdup(ctx, client_get_cur_dir());
349
 
        if (!saved_dir) {
350
 
                TALLOC_FREE(ctx);
351
 
                return 1;
352
 
        }
353
 
 
354
 
        if (*newdir == CLI_DIRSEP_CHAR) {
355
 
                client_set_cur_dir(newdir);
356
 
                new_cd = newdir;
357
 
        } else {
358
 
                new_cd = talloc_asprintf(ctx, "%s%s",
359
 
                                client_get_cur_dir(),
360
 
                                newdir);
361
 
                if (!new_cd) {
362
 
                        goto out;
363
 
                }
364
 
        }
365
 
 
366
 
        /* Ensure cur_dir ends in a DIRSEP */
367
 
        if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
368
 
                new_cd = talloc_asprintf_append(new_cd, "%s", CLI_DIRSEP_STR);
369
 
                if (!new_cd) {
370
 
                        goto out;
371
 
                }
372
 
        }
373
 
        client_set_cur_dir(new_cd);
374
 
 
375
 
        new_cd = clean_name(ctx, new_cd);
376
 
        client_set_cur_dir(new_cd);
377
 
 
378
 
        if ( !cli_resolve_path(ctx, "", auth_info, cli, new_cd, &targetcli, &targetpath)) {
379
 
                d_printf("cd %s: %s\n", new_cd, cli_errstr(cli));
380
 
                client_set_cur_dir(saved_dir);
381
 
                goto out;
382
 
        }
383
 
 
384
 
        if (strequal(targetpath,CLI_DIRSEP_STR )) {
385
 
                TALLOC_FREE(ctx);
386
 
                return 0;
387
 
        }
388
 
 
389
 
        /* Use a trans2_qpathinfo to test directories for modern servers.
390
 
           Except Win9x doesn't support the qpathinfo_basic() call..... */
391
 
 
392
 
        if (targetcli->protocol > PROTOCOL_LANMAN2 && !targetcli->win95) {
393
 
                if (!cli_qpathinfo_basic( targetcli, targetpath, &sbuf, &attributes ) ) {
394
 
                        d_printf("cd %s: %s\n", new_cd, cli_errstr(targetcli));
395
 
                        client_set_cur_dir(saved_dir);
396
 
                        goto out;
397
 
                }
398
 
 
399
 
                if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
400
 
                        d_printf("cd %s: not a directory\n", new_cd);
401
 
                        client_set_cur_dir(saved_dir);
402
 
                        goto out;
403
 
                }
404
 
        } else {
405
 
                targetpath = talloc_asprintf(ctx,
406
 
                                "%s%s",
407
 
                                targetpath,
408
 
                                CLI_DIRSEP_STR );
409
 
                if (!targetpath) {
410
 
                        client_set_cur_dir(saved_dir);
411
 
                        goto out;
412
 
                }
413
 
                targetpath = clean_name(ctx, targetpath);
414
 
                if (!targetpath) {
415
 
                        client_set_cur_dir(saved_dir);
416
 
                        goto out;
417
 
                }
418
 
 
419
 
                if (!NT_STATUS_IS_OK(cli_chkpath(targetcli, targetpath))) {
420
 
                        d_printf("cd %s: %s\n", new_cd, cli_errstr(targetcli));
421
 
                        client_set_cur_dir(saved_dir);
422
 
                        goto out;
423
 
                }
424
 
        }
425
 
 
426
 
        ret = 0;
427
 
 
428
 
out:
429
 
 
430
 
        TALLOC_FREE(ctx);
431
 
        return ret;
432
 
}
433
 
 
434
 
/****************************************************************************
435
 
 Change directory.
436
 
****************************************************************************/
437
 
 
438
 
static int cmd_cd(void)
439
 
{
440
 
        char *buf = NULL;
441
 
        int rc = 0;
442
 
 
443
 
        if (next_token_talloc(talloc_tos(), &cmd_ptr, &buf,NULL)) {
444
 
                rc = do_cd(buf);
445
 
        } else {
446
 
                d_printf("Current directory is %s\n",client_get_cur_dir());
447
 
        }
448
 
 
449
 
        return rc;
450
 
}
451
 
 
452
 
/****************************************************************************
453
 
 Change directory.
454
 
****************************************************************************/
455
 
 
456
 
static int cmd_cd_oneup(void)
457
 
{
458
 
        return do_cd("..");
459
 
}
460
 
 
461
 
/*******************************************************************
462
 
 Decide if a file should be operated on.
463
 
********************************************************************/
464
 
 
465
 
static bool do_this_one(file_info *finfo)
466
 
{
467
 
        if (!finfo->name) {
468
 
                return false;
469
 
        }
470
 
 
471
 
        if (finfo->mode & aDIR) {
472
 
                return true;
473
 
        }
474
 
 
475
 
        if (*client_get_fileselection() &&
476
 
            !mask_match(finfo->name,client_get_fileselection(),false)) {
477
 
                DEBUG(3,("mask_match %s failed\n", finfo->name));
478
 
                return false;
479
 
        }
480
 
 
481
 
        if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
482
 
                DEBUG(3,("newer_than %s failed\n", finfo->name));
483
 
                return false;
484
 
        }
485
 
 
486
 
        if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) {
487
 
                DEBUG(3,("archive %s failed\n", finfo->name));
488
 
                return false;
489
 
        }
490
 
 
491
 
        return true;
492
 
}
493
 
 
494
 
/****************************************************************************
495
 
 Display info about a file.
496
 
****************************************************************************/
497
 
 
498
 
static void display_finfo(file_info *finfo, const char *dir)
499
 
{
500
 
        time_t t;
501
 
        TALLOC_CTX *ctx = talloc_tos();
502
 
 
503
 
        if (!do_this_one(finfo)) {
504
 
                return;
505
 
        }
506
 
 
507
 
        t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
508
 
        if (!showacls) {
509
 
                d_printf("  %-30s%7.7s %8.0f  %s",
510
 
                         finfo->name,
511
 
                         attrib_string(finfo->mode),
512
 
                        (double)finfo->size,
513
 
                        time_to_asc(t));
514
 
                dir_total += finfo->size;
515
 
        } else {
516
 
                char *afname = NULL;
517
 
                uint16_t fnum;
518
 
 
519
 
                /* skip if this is . or .. */
520
 
                if ( strequal(finfo->name,"..") || strequal(finfo->name,".") )
521
 
                        return;
522
 
                /* create absolute filename for cli_ntcreate() FIXME */
523
 
                afname = talloc_asprintf(ctx,
524
 
                                        "%s%s%s",
525
 
                                        dir,
526
 
                                        CLI_DIRSEP_STR,
527
 
                                        finfo->name);
528
 
                if (!afname) {
529
 
                        return;
530
 
                }
531
 
                /* print file meta date header */
532
 
                d_printf( "FILENAME:%s\n", finfo->name);
533
 
                d_printf( "MODE:%s\n", attrib_string(finfo->mode));
534
 
                d_printf( "SIZE:%.0f\n", (double)finfo->size);
535
 
                d_printf( "MTIME:%s", time_to_asc(t));
536
 
                if (!NT_STATUS_IS_OK(cli_ntcreate(finfo->cli, afname, 0,
537
 
                                CREATE_ACCESS_READ, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
538
 
                                FILE_OPEN, 0x0, 0x0, &fnum))) {
539
 
                        DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
540
 
                                afname,
541
 
                                cli_errstr( finfo->cli)));
542
 
                } else {
543
 
                        SEC_DESC *sd = NULL;
544
 
                        sd = cli_query_secdesc(finfo->cli, fnum, ctx);
545
 
                        if (!sd) {
546
 
                                DEBUG( 0, ("display_finfo() failed to "
547
 
                                        "get security descriptor: %s",
548
 
                                        cli_errstr( finfo->cli)));
549
 
                        } else {
550
 
                                display_sec_desc(sd);
551
 
                        }
552
 
                        TALLOC_FREE(sd);
553
 
                }
554
 
                TALLOC_FREE(afname);
555
 
        }
556
 
}
557
 
 
558
 
/****************************************************************************
559
 
 Accumulate size of a file.
560
 
****************************************************************************/
561
 
 
562
 
static void do_du(file_info *finfo, const char *dir)
563
 
{
564
 
        if (do_this_one(finfo)) {
565
 
                dir_total += finfo->size;
566
 
        }
567
 
}
568
 
 
569
 
static bool do_list_recurse;
570
 
static bool do_list_dirs;
571
 
static char *do_list_queue = 0;
572
 
static long do_list_queue_size = 0;
573
 
static long do_list_queue_start = 0;
574
 
static long do_list_queue_end = 0;
575
 
static void (*do_list_fn)(file_info *, const char *dir);
576
 
 
577
 
/****************************************************************************
578
 
 Functions for do_list_queue.
579
 
****************************************************************************/
580
 
 
581
 
/*
582
 
 * The do_list_queue is a NUL-separated list of strings stored in a
583
 
 * char*.  Since this is a FIFO, we keep track of the beginning and
584
 
 * ending locations of the data in the queue.  When we overflow, we
585
 
 * double the size of the char*.  When the start of the data passes
586
 
 * the midpoint, we move everything back.  This is logically more
587
 
 * complex than a linked list, but easier from a memory management
588
 
 * angle.  In any memory error condition, do_list_queue is reset.
589
 
 * Functions check to ensure that do_list_queue is non-NULL before
590
 
 * accessing it.
591
 
 */
592
 
 
593
 
static void reset_do_list_queue(void)
594
 
{
595
 
        SAFE_FREE(do_list_queue);
596
 
        do_list_queue_size = 0;
597
 
        do_list_queue_start = 0;
598
 
        do_list_queue_end = 0;
599
 
}
600
 
 
601
 
static void init_do_list_queue(void)
602
 
{
603
 
        reset_do_list_queue();
604
 
        do_list_queue_size = 1024;
605
 
        do_list_queue = (char *)SMB_MALLOC(do_list_queue_size);
606
 
        if (do_list_queue == 0) {
607
 
                d_printf("malloc fail for size %d\n",
608
 
                         (int)do_list_queue_size);
609
 
                reset_do_list_queue();
610
 
        } else {
611
 
                memset(do_list_queue, 0, do_list_queue_size);
612
 
        }
613
 
}
614
 
 
615
 
static void adjust_do_list_queue(void)
616
 
{
617
 
        /*
618
 
         * If the starting point of the queue is more than half way through,
619
 
         * move everything toward the beginning.
620
 
         */
621
 
 
622
 
        if (do_list_queue == NULL) {
623
 
                DEBUG(4,("do_list_queue is empty\n"));
624
 
                do_list_queue_start = do_list_queue_end = 0;
625
 
                return;
626
 
        }
627
 
 
628
 
        if (do_list_queue_start == do_list_queue_end) {
629
 
                DEBUG(4,("do_list_queue is empty\n"));
630
 
                do_list_queue_start = do_list_queue_end = 0;
631
 
                *do_list_queue = '\0';
632
 
        } else if (do_list_queue_start > (do_list_queue_size / 2)) {
633
 
                DEBUG(4,("sliding do_list_queue backward\n"));
634
 
                memmove(do_list_queue,
635
 
                        do_list_queue + do_list_queue_start,
636
 
                        do_list_queue_end - do_list_queue_start);
637
 
                do_list_queue_end -= do_list_queue_start;
638
 
                do_list_queue_start = 0;
639
 
        }
640
 
}
641
 
 
642
 
static void add_to_do_list_queue(const char *entry)
643
 
{
644
 
        long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
645
 
        while (new_end > do_list_queue_size) {
646
 
                do_list_queue_size *= 2;
647
 
                DEBUG(4,("enlarging do_list_queue to %d\n",
648
 
                         (int)do_list_queue_size));
649
 
                do_list_queue = (char *)SMB_REALLOC(do_list_queue, do_list_queue_size);
650
 
                if (! do_list_queue) {
651
 
                        d_printf("failure enlarging do_list_queue to %d bytes\n",
652
 
                                 (int)do_list_queue_size);
653
 
                        reset_do_list_queue();
654
 
                } else {
655
 
                        memset(do_list_queue + do_list_queue_size / 2,
656
 
                               0, do_list_queue_size / 2);
657
 
                }
658
 
        }
659
 
        if (do_list_queue) {
660
 
                safe_strcpy_base(do_list_queue + do_list_queue_end,
661
 
                                 entry, do_list_queue, do_list_queue_size);
662
 
                do_list_queue_end = new_end;
663
 
                DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
664
 
                         entry, (int)do_list_queue_start, (int)do_list_queue_end));
665
 
        }
666
 
}
667
 
 
668
 
static char *do_list_queue_head(void)
669
 
{
670
 
        return do_list_queue + do_list_queue_start;
671
 
}
672
 
 
673
 
static void remove_do_list_queue_head(void)
674
 
{
675
 
        if (do_list_queue_end > do_list_queue_start) {
676
 
                do_list_queue_start += strlen(do_list_queue_head()) + 1;
677
 
                adjust_do_list_queue();
678
 
                DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
679
 
                         (int)do_list_queue_start, (int)do_list_queue_end));
680
 
        }
681
 
}
682
 
 
683
 
static int do_list_queue_empty(void)
684
 
{
685
 
        return (! (do_list_queue && *do_list_queue));
686
 
}
687
 
 
688
 
/****************************************************************************
689
 
 A helper for do_list.
690
 
****************************************************************************/
691
 
 
692
 
static void do_list_helper(const char *mntpoint, file_info *f, const char *mask, void *state)
693
 
{
694
 
        TALLOC_CTX *ctx = talloc_tos();
695
 
        char *dir = NULL;
696
 
        char *dir_end = NULL;
697
 
 
698
 
        /* Work out the directory. */
699
 
        dir = talloc_strdup(ctx, mask);
700
 
        if (!dir) {
701
 
                return;
702
 
        }
703
 
        if ((dir_end = strrchr(dir, CLI_DIRSEP_CHAR)) != NULL) {
704
 
                *dir_end = '\0';
705
 
        }
706
 
 
707
 
        if (f->mode & aDIR) {
708
 
                if (do_list_dirs && do_this_one(f)) {
709
 
                        do_list_fn(f, dir);
710
 
                }
711
 
                if (do_list_recurse &&
712
 
                    f->name &&
713
 
                    !strequal(f->name,".") &&
714
 
                    !strequal(f->name,"..")) {
715
 
                        char *mask2 = NULL;
716
 
                        char *p = NULL;
717
 
 
718
 
                        if (!f->name[0]) {
719
 
                                d_printf("Empty dir name returned. Possible server misconfiguration.\n");
720
 
                                TALLOC_FREE(dir);
721
 
                                return;
722
 
                        }
723
 
 
724
 
                        mask2 = talloc_asprintf(ctx,
725
 
                                        "%s%s",
726
 
                                        mntpoint,
727
 
                                        mask);
728
 
                        if (!mask2) {
729
 
                                TALLOC_FREE(dir);
730
 
                                return;
731
 
                        }
732
 
                        p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
733
 
                        if (p) {
734
 
                                p[1] = 0;
735
 
                        } else {
736
 
                                mask2[0] = '\0';
737
 
                        }
738
 
                        mask2 = talloc_asprintf_append(mask2,
739
 
                                        "%s%s*",
740
 
                                        f->name,
741
 
                                        CLI_DIRSEP_STR);
742
 
                        if (!mask2) {
743
 
                                TALLOC_FREE(dir);
744
 
                                return;
745
 
                        }
746
 
                        add_to_do_list_queue(mask2);
747
 
                        TALLOC_FREE(mask2);
748
 
                }
749
 
                TALLOC_FREE(dir);
750
 
                return;
751
 
        }
752
 
 
753
 
        if (do_this_one(f)) {
754
 
                do_list_fn(f,dir);
755
 
        }
756
 
        TALLOC_FREE(dir);
757
 
}
758
 
 
759
 
/****************************************************************************
760
 
 A wrapper around cli_list that adds recursion.
761
 
****************************************************************************/
762
 
 
763
 
void do_list(const char *mask,
764
 
                        uint16 attribute,
765
 
                        void (*fn)(file_info *, const char *dir),
766
 
                        bool rec,
767
 
                        bool dirs)
768
 
{
769
 
        static int in_do_list = 0;
770
 
        TALLOC_CTX *ctx = talloc_tos();
771
 
        struct cli_state *targetcli = NULL;
772
 
        char *targetpath = NULL;
773
 
 
774
 
        if (in_do_list && rec) {
775
 
                fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
776
 
                exit(1);
777
 
        }
778
 
 
779
 
        in_do_list = 1;
780
 
 
781
 
        do_list_recurse = rec;
782
 
        do_list_dirs = dirs;
783
 
        do_list_fn = fn;
784
 
 
785
 
        if (rec) {
786
 
                init_do_list_queue();
787
 
                add_to_do_list_queue(mask);
788
 
 
789
 
                while (!do_list_queue_empty()) {
790
 
                        /*
791
 
                         * Need to copy head so that it doesn't become
792
 
                         * invalid inside the call to cli_list.  This
793
 
                         * would happen if the list were expanded
794
 
                         * during the call.
795
 
                         * Fix from E. Jay Berkenbilt (ejb@ql.org)
796
 
                         */
797
 
                        char *head = talloc_strdup(ctx, do_list_queue_head());
798
 
 
799
 
                        if (!head) {
800
 
                                return;
801
 
                        }
802
 
 
803
 
                        /* check for dfs */
804
 
 
805
 
                        if ( !cli_resolve_path(ctx, "", auth_info, cli, head, &targetcli, &targetpath ) ) {
806
 
                                d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
807
 
                                remove_do_list_queue_head();
808
 
                                continue;
809
 
                        }
810
 
 
811
 
                        cli_list(targetcli, targetpath, attribute, do_list_helper, NULL);
812
 
                        remove_do_list_queue_head();
813
 
                        if ((! do_list_queue_empty()) && (fn == display_finfo)) {
814
 
                                char *next_file = do_list_queue_head();
815
 
                                char *save_ch = 0;
816
 
                                if ((strlen(next_file) >= 2) &&
817
 
                                    (next_file[strlen(next_file) - 1] == '*') &&
818
 
                                    (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
819
 
                                        save_ch = next_file +
820
 
                                                strlen(next_file) - 2;
821
 
                                        *save_ch = '\0';
822
 
                                        if (showacls) {
823
 
                                                /* cwd is only used if showacls is on */
824
 
                                                client_set_cwd(next_file);
825
 
                                        }
826
 
                                }
827
 
                                if (!showacls) /* don't disturbe the showacls output */
828
 
                                        d_printf("\n%s\n",next_file);
829
 
                                if (save_ch) {
830
 
                                        *save_ch = CLI_DIRSEP_CHAR;
831
 
                                }
832
 
                        }
833
 
                        TALLOC_FREE(head);
834
 
                        TALLOC_FREE(targetpath);
835
 
                }
836
 
        } else {
837
 
                /* check for dfs */
838
 
                if (cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetpath)) {
839
 
                        if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1) {
840
 
                                d_printf("%s listing %s\n",
841
 
                                        cli_errstr(targetcli), targetpath);
842
 
                        }
843
 
                        TALLOC_FREE(targetpath);
844
 
                } else {
845
 
                        d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli));
846
 
                }
847
 
        }
848
 
 
849
 
        in_do_list = 0;
850
 
        reset_do_list_queue();
851
 
}
852
 
 
853
 
/****************************************************************************
854
 
 Get a directory listing.
855
 
****************************************************************************/
856
 
 
857
 
static int cmd_dir(void)
858
 
{
859
 
        TALLOC_CTX *ctx = talloc_tos();
860
 
        uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
861
 
        char *mask = NULL;
862
 
        char *buf = NULL;
863
 
        int rc = 1;
864
 
 
865
 
        dir_total = 0;
866
 
        mask = talloc_strdup(ctx, client_get_cur_dir());
867
 
        if (!mask) {
868
 
                return 1;
869
 
        }
870
 
 
871
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
872
 
                normalize_name(buf);
873
 
                if (*buf == CLI_DIRSEP_CHAR) {
874
 
                        mask = talloc_strdup(ctx, buf);
875
 
                } else {
876
 
                        mask = talloc_asprintf_append(mask, "%s", buf);
877
 
                }
878
 
        } else {
879
 
                mask = talloc_asprintf_append(mask, "*");
880
 
        }
881
 
        if (!mask) {
882
 
                return 1;
883
 
        }
884
 
 
885
 
        if (showacls) {
886
 
                /* cwd is only used if showacls is on */
887
 
                client_set_cwd(client_get_cur_dir());
888
 
        }
889
 
 
890
 
        do_list(mask, attribute, display_finfo, recurse, true);
891
 
 
892
 
        rc = do_dskattr();
893
 
 
894
 
        DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
895
 
 
896
 
        return rc;
897
 
}
898
 
 
899
 
/****************************************************************************
900
 
 Get a directory listing.
901
 
****************************************************************************/
902
 
 
903
 
static int cmd_du(void)
904
 
{
905
 
        TALLOC_CTX *ctx = talloc_tos();
906
 
        uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
907
 
        char *mask = NULL;
908
 
        char *buf = NULL;
909
 
        int rc = 1;
910
 
 
911
 
        dir_total = 0;
912
 
        mask = talloc_strdup(ctx, client_get_cur_dir());
913
 
        if (!mask) {
914
 
                return 1;
915
 
        }
916
 
        if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
917
 
                mask = talloc_asprintf_append(mask, "%s", CLI_DIRSEP_STR);
918
 
                if (!mask) {
919
 
                        return 1;
920
 
                }
921
 
        }
922
 
 
923
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
924
 
                normalize_name(buf);
925
 
                if (*buf == CLI_DIRSEP_CHAR) {
926
 
                        mask = talloc_strdup(ctx, buf);
927
 
                } else {
928
 
                        mask = talloc_asprintf_append(mask, "%s", buf);
929
 
                }
930
 
        } else {
931
 
                mask = talloc_strdup(ctx, "*");
932
 
        }
933
 
 
934
 
        do_list(mask, attribute, do_du, recurse, true);
935
 
 
936
 
        rc = do_dskattr();
937
 
 
938
 
        d_printf("Total number of bytes: %.0f\n", dir_total);
939
 
 
940
 
        return rc;
941
 
}
942
 
 
943
 
static int cmd_echo(void)
944
 
{
945
 
        TALLOC_CTX *ctx = talloc_tos();
946
 
        char *num;
947
 
        char *data;
948
 
        NTSTATUS status;
949
 
 
950
 
        if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
951
 
            || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
952
 
                d_printf("echo <num> <data>\n");
953
 
                return 1;
954
 
        }
955
 
 
956
 
        status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
957
 
 
958
 
        if (!NT_STATUS_IS_OK(status)) {
959
 
                d_printf("echo failed: %s\n", nt_errstr(status));
960
 
                return 1;
961
 
        }
962
 
 
963
 
        return 0;
964
 
}
965
 
 
966
 
/****************************************************************************
967
 
 Get a file from rname to lname
968
 
****************************************************************************/
969
 
 
970
 
static NTSTATUS writefile_sink(char *buf, size_t n, void *priv)
971
 
{
972
 
        int *pfd = (int *)priv;
973
 
        if (writefile(*pfd, buf, n) == -1) {
974
 
                return map_nt_error_from_unix(errno);
975
 
        }
976
 
        return NT_STATUS_OK;
977
 
}
978
 
 
979
 
static int do_get(const char *rname, const char *lname_in, bool reget)
980
 
{
981
 
        TALLOC_CTX *ctx = talloc_tos();
982
 
        int handle = 0;
983
 
        uint16_t fnum;
984
 
        bool newhandle = false;
985
 
        struct timeval tp_start;
986
 
        uint16 attr;
987
 
        SMB_OFF_T size;
988
 
        off_t start = 0;
989
 
        SMB_OFF_T nread = 0;
990
 
        int rc = 0;
991
 
        struct cli_state *targetcli = NULL;
992
 
        char *targetname = NULL;
993
 
        char *lname = NULL;
994
 
        NTSTATUS status;
995
 
 
996
 
        lname = talloc_strdup(ctx, lname_in);
997
 
        if (!lname) {
998
 
                return 1;
999
 
        }
1000
 
 
1001
 
        if (lowercase) {
1002
 
                strlower_m(lname);
1003
 
        }
1004
 
 
1005
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname ) ) {
1006
 
                d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
1007
 
                return 1;
1008
 
        }
1009
 
 
1010
 
        GetTimeOfDay(&tp_start);
1011
 
 
1012
 
        if (!NT_STATUS_IS_OK(cli_open(targetcli, targetname, O_RDONLY, DENY_NONE, &fnum))) {
1013
 
                d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
1014
 
                return 1;
1015
 
        }
1016
 
 
1017
 
        if(!strcmp(lname,"-")) {
1018
 
                handle = fileno(stdout);
1019
 
        } else {
1020
 
                if (reget) {
1021
 
                        handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
1022
 
                        if (handle >= 0) {
1023
 
                                start = sys_lseek(handle, 0, SEEK_END);
1024
 
                                if (start == -1) {
1025
 
                                        d_printf("Error seeking local file\n");
1026
 
                                        return 1;
1027
 
                                }
1028
 
                        }
1029
 
                } else {
1030
 
                        handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
1031
 
                }
1032
 
                newhandle = true;
1033
 
        }
1034
 
        if (handle < 0) {
1035
 
                d_printf("Error opening local file %s\n",lname);
1036
 
                return 1;
1037
 
        }
1038
 
 
1039
 
 
1040
 
        if (!cli_qfileinfo(targetcli, fnum,
1041
 
                           &attr, &size, NULL, NULL, NULL, NULL, NULL) &&
1042
 
            !NT_STATUS_IS_OK(cli_getattrE(targetcli, fnum,
1043
 
                          &attr, &size, NULL, NULL, NULL))) {
1044
 
                d_printf("getattrib: %s\n",cli_errstr(targetcli));
1045
 
                return 1;
1046
 
        }
1047
 
 
1048
 
        DEBUG(1,("getting file %s of size %.0f as %s ",
1049
 
                 rname, (double)size, lname));
1050
 
 
1051
 
        status = cli_pull(targetcli, fnum, start, size, io_bufsize,
1052
 
                          writefile_sink, (void *)&handle, &nread);
1053
 
        if (!NT_STATUS_IS_OK(status)) {
1054
 
                d_fprintf(stderr, "parallel_read returned %s\n",
1055
 
                          nt_errstr(status));
1056
 
                cli_close(targetcli, fnum);
1057
 
                return 1;
1058
 
        }
1059
 
 
1060
 
        if (!NT_STATUS_IS_OK(cli_close(targetcli, fnum))) {
1061
 
                d_printf("Error %s closing remote file\n",cli_errstr(cli));
1062
 
                rc = 1;
1063
 
        }
1064
 
 
1065
 
        if (newhandle) {
1066
 
                close(handle);
1067
 
        }
1068
 
 
1069
 
        if (archive_level >= 2 && (attr & aARCH)) {
1070
 
                cli_setatr(cli, rname, attr & ~(uint16)aARCH, 0);
1071
 
        }
1072
 
 
1073
 
        {
1074
 
                struct timeval tp_end;
1075
 
                int this_time;
1076
 
 
1077
 
                GetTimeOfDay(&tp_end);
1078
 
                this_time =
1079
 
                        (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1080
 
                        (tp_end.tv_usec - tp_start.tv_usec)/1000;
1081
 
                get_total_time_ms += this_time;
1082
 
                get_total_size += nread;
1083
 
 
1084
 
                DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
1085
 
                         nread / (1.024*this_time + 1.0e-4),
1086
 
                         get_total_size / (1.024*get_total_time_ms)));
1087
 
        }
1088
 
 
1089
 
        TALLOC_FREE(targetname);
1090
 
        return rc;
1091
 
}
1092
 
 
1093
 
/****************************************************************************
1094
 
 Get a file.
1095
 
****************************************************************************/
1096
 
 
1097
 
static int cmd_get(void)
1098
 
{
1099
 
        TALLOC_CTX *ctx = talloc_tos();
1100
 
        char *lname = NULL;
1101
 
        char *rname = NULL;
1102
 
        char *fname = NULL;
1103
 
 
1104
 
        rname = talloc_strdup(ctx, client_get_cur_dir());
1105
 
        if (!rname) {
1106
 
                return 1;
1107
 
        }
1108
 
 
1109
 
        if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
1110
 
                d_printf("get <filename> [localname]\n");
1111
 
                return 1;
1112
 
        }
1113
 
        rname = talloc_asprintf_append(rname, "%s", fname);
1114
 
        if (!rname) {
1115
 
                return 1;
1116
 
        }
1117
 
        rname = clean_name(ctx, rname);
1118
 
        if (!rname) {
1119
 
                return 1;
1120
 
        }
1121
 
 
1122
 
        next_token_talloc(ctx, &cmd_ptr,&lname,NULL);
1123
 
        if (!lname) {
1124
 
                lname = fname;
1125
 
        }
1126
 
 
1127
 
        return do_get(rname, lname, false);
1128
 
}
1129
 
 
1130
 
/****************************************************************************
1131
 
 Do an mget operation on one file.
1132
 
****************************************************************************/
1133
 
 
1134
 
static void do_mget(file_info *finfo, const char *dir)
1135
 
{
1136
 
        TALLOC_CTX *ctx = talloc_tos();
1137
 
        char *rname = NULL;
1138
 
        char *quest = NULL;
1139
 
        char *saved_curdir = NULL;
1140
 
        char *mget_mask = NULL;
1141
 
        char *new_cd = NULL;
1142
 
 
1143
 
        if (!finfo->name) {
1144
 
                return;
1145
 
        }
1146
 
 
1147
 
        if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1148
 
                return;
1149
 
 
1150
 
        if (abort_mget) {
1151
 
                d_printf("mget aborted\n");
1152
 
                return;
1153
 
        }
1154
 
 
1155
 
        if (finfo->mode & aDIR) {
1156
 
                if (asprintf(&quest,
1157
 
                         "Get directory %s? ",finfo->name) < 0) {
1158
 
                        return;
1159
 
                }
1160
 
        } else {
1161
 
                if (asprintf(&quest,
1162
 
                         "Get file %s? ",finfo->name) < 0) {
1163
 
                        return;
1164
 
                }
1165
 
        }
1166
 
 
1167
 
        if (prompt && !yesno(quest)) {
1168
 
                SAFE_FREE(quest);
1169
 
                return;
1170
 
        }
1171
 
        SAFE_FREE(quest);
1172
 
 
1173
 
        if (!(finfo->mode & aDIR)) {
1174
 
                rname = talloc_asprintf(ctx,
1175
 
                                "%s%s",
1176
 
                                client_get_cur_dir(),
1177
 
                                finfo->name);
1178
 
                if (!rname) {
1179
 
                        return;
1180
 
                }
1181
 
                do_get(rname, finfo->name, false);
1182
 
                TALLOC_FREE(rname);
1183
 
                return;
1184
 
        }
1185
 
 
1186
 
        /* handle directories */
1187
 
        saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
1188
 
        if (!saved_curdir) {
1189
 
                return;
1190
 
        }
1191
 
 
1192
 
        new_cd = talloc_asprintf(ctx,
1193
 
                                "%s%s%s",
1194
 
                                client_get_cur_dir(),
1195
 
                                finfo->name,
1196
 
                                CLI_DIRSEP_STR);
1197
 
        if (!new_cd) {
1198
 
                return;
1199
 
        }
1200
 
        client_set_cur_dir(new_cd);
1201
 
 
1202
 
        string_replace(finfo->name,'\\','/');
1203
 
        if (lowercase) {
1204
 
                strlower_m(finfo->name);
1205
 
        }
1206
 
 
1207
 
        if (!directory_exist(finfo->name) &&
1208
 
            mkdir(finfo->name,0777) != 0) {
1209
 
                d_printf("failed to create directory %s\n",finfo->name);
1210
 
                client_set_cur_dir(saved_curdir);
1211
 
                return;
1212
 
        }
1213
 
 
1214
 
        if (chdir(finfo->name) != 0) {
1215
 
                d_printf("failed to chdir to directory %s\n",finfo->name);
1216
 
                client_set_cur_dir(saved_curdir);
1217
 
                return;
1218
 
        }
1219
 
 
1220
 
        mget_mask = talloc_asprintf(ctx,
1221
 
                        "%s*",
1222
 
                        client_get_cur_dir());
1223
 
 
1224
 
        if (!mget_mask) {
1225
 
                return;
1226
 
        }
1227
 
 
1228
 
        do_list(mget_mask, aSYSTEM | aHIDDEN | aDIR,do_mget,false, true);
1229
 
        if (chdir("..") == -1) {
1230
 
                d_printf("do_mget: failed to chdir to .. (error %s)\n",
1231
 
                        strerror(errno) );
1232
 
        }
1233
 
        client_set_cur_dir(saved_curdir);
1234
 
        TALLOC_FREE(mget_mask);
1235
 
        TALLOC_FREE(saved_curdir);
1236
 
        TALLOC_FREE(new_cd);
1237
 
}
1238
 
 
1239
 
/****************************************************************************
1240
 
 View the file using the pager.
1241
 
****************************************************************************/
1242
 
 
1243
 
static int cmd_more(void)
1244
 
{
1245
 
        TALLOC_CTX *ctx = talloc_tos();
1246
 
        char *rname = NULL;
1247
 
        char *fname = NULL;
1248
 
        char *lname = NULL;
1249
 
        char *pager_cmd = NULL;
1250
 
        const char *pager;
1251
 
        int fd;
1252
 
        int rc = 0;
1253
 
 
1254
 
        rname = talloc_strdup(ctx, client_get_cur_dir());
1255
 
        if (!rname) {
1256
 
                return 1;
1257
 
        }
1258
 
 
1259
 
        lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
1260
 
        if (!lname) {
1261
 
                return 1;
1262
 
        }
1263
 
        fd = mkstemp(lname);
1264
 
        if (fd == -1) {
1265
 
                d_printf("failed to create temporary file for more\n");
1266
 
                return 1;
1267
 
        }
1268
 
        close(fd);
1269
 
 
1270
 
        if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
1271
 
                d_printf("more <filename>\n");
1272
 
                unlink(lname);
1273
 
                return 1;
1274
 
        }
1275
 
        rname = talloc_asprintf_append(rname, "%s", fname);
1276
 
        if (!rname) {
1277
 
                return 1;
1278
 
        }
1279
 
        rname = clean_name(ctx,rname);
1280
 
        if (!rname) {
1281
 
                return 1;
1282
 
        }
1283
 
 
1284
 
        rc = do_get(rname, lname, false);
1285
 
 
1286
 
        pager=getenv("PAGER");
1287
 
 
1288
 
        pager_cmd = talloc_asprintf(ctx,
1289
 
                                "%s %s",
1290
 
                                (pager? pager:PAGER),
1291
 
                                lname);
1292
 
        if (!pager_cmd) {
1293
 
                return 1;
1294
 
        }
1295
 
        if (system(pager_cmd) == -1) {
1296
 
                d_printf("system command '%s' returned -1\n",
1297
 
                        pager_cmd);
1298
 
        }
1299
 
        unlink(lname);
1300
 
 
1301
 
        return rc;
1302
 
}
1303
 
 
1304
 
/****************************************************************************
1305
 
 Do a mget command.
1306
 
****************************************************************************/
1307
 
 
1308
 
static int cmd_mget(void)
1309
 
{
1310
 
        TALLOC_CTX *ctx = talloc_tos();
1311
 
        uint16 attribute = aSYSTEM | aHIDDEN;
1312
 
        char *mget_mask = NULL;
1313
 
        char *buf = NULL;
1314
 
 
1315
 
        if (recurse) {
1316
 
                attribute |= aDIR;
1317
 
        }
1318
 
 
1319
 
        abort_mget = false;
1320
 
 
1321
 
        while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1322
 
                mget_mask = talloc_strdup(ctx, client_get_cur_dir());
1323
 
                if (!mget_mask) {
1324
 
                        return 1;
1325
 
                }
1326
 
                if (*buf == CLI_DIRSEP_CHAR) {
1327
 
                        mget_mask = talloc_strdup(ctx, buf);
1328
 
                } else {
1329
 
                        mget_mask = talloc_asprintf_append(mget_mask,
1330
 
                                                        "%s", buf);
1331
 
                }
1332
 
                if (!mget_mask) {
1333
 
                        return 1;
1334
 
                }
1335
 
                do_list(mget_mask, attribute, do_mget, false, true);
1336
 
        }
1337
 
 
1338
 
        if (mget_mask == NULL) {
1339
 
                d_printf("nothing to mget\n");
1340
 
                return 0;
1341
 
        }
1342
 
 
1343
 
        if (!*mget_mask) {
1344
 
                mget_mask = talloc_asprintf(ctx,
1345
 
                                        "%s*",
1346
 
                                        client_get_cur_dir());
1347
 
                if (!mget_mask) {
1348
 
                        return 1;
1349
 
                }
1350
 
                do_list(mget_mask, attribute, do_mget, false, true);
1351
 
        }
1352
 
 
1353
 
        return 0;
1354
 
}
1355
 
 
1356
 
/****************************************************************************
1357
 
 Make a directory of name "name".
1358
 
****************************************************************************/
1359
 
 
1360
 
static bool do_mkdir(const char *name)
1361
 
{
1362
 
        TALLOC_CTX *ctx = talloc_tos();
1363
 
        struct cli_state *targetcli;
1364
 
        char *targetname = NULL;
1365
 
 
1366
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
1367
 
                d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
1368
 
                return false;
1369
 
        }
1370
 
 
1371
 
        if (!NT_STATUS_IS_OK(cli_mkdir(targetcli, targetname))) {
1372
 
                d_printf("%s making remote directory %s\n",
1373
 
                         cli_errstr(targetcli),name);
1374
 
                return false;
1375
 
        }
1376
 
 
1377
 
        return true;
1378
 
}
1379
 
 
1380
 
/****************************************************************************
1381
 
 Show 8.3 name of a file.
1382
 
****************************************************************************/
1383
 
 
1384
 
static bool do_altname(const char *name)
1385
 
{
1386
 
        fstring altname;
1387
 
 
1388
 
        if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
1389
 
                d_printf("%s getting alt name for %s\n",
1390
 
                         cli_errstr(cli),name);
1391
 
                return false;
1392
 
        }
1393
 
        d_printf("%s\n", altname);
1394
 
 
1395
 
        return true;
1396
 
}
1397
 
 
1398
 
/****************************************************************************
1399
 
 Exit client.
1400
 
****************************************************************************/
1401
 
 
1402
 
static int cmd_quit(void)
1403
 
{
1404
 
        cli_shutdown(cli);
1405
 
        exit(0);
1406
 
        /* NOTREACHED */
1407
 
        return 0;
1408
 
}
1409
 
 
1410
 
/****************************************************************************
1411
 
 Make a directory.
1412
 
****************************************************************************/
1413
 
 
1414
 
static int cmd_mkdir(void)
1415
 
{
1416
 
        TALLOC_CTX *ctx = talloc_tos();
1417
 
        char *mask = NULL;
1418
 
        char *buf = NULL;
1419
 
 
1420
 
        mask = talloc_strdup(ctx, client_get_cur_dir());
1421
 
        if (!mask) {
1422
 
                return 1;
1423
 
        }
1424
 
 
1425
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1426
 
                if (!recurse) {
1427
 
                        d_printf("mkdir <dirname>\n");
1428
 
                }
1429
 
                return 1;
1430
 
        }
1431
 
        mask = talloc_asprintf_append(mask, "%s", buf);
1432
 
        if (!mask) {
1433
 
                return 1;
1434
 
        }
1435
 
 
1436
 
        if (recurse) {
1437
 
                char *ddir = NULL;
1438
 
                char *ddir2 = NULL;
1439
 
                struct cli_state *targetcli;
1440
 
                char *targetname = NULL;
1441
 
                char *p = NULL;
1442
 
                char *saveptr;
1443
 
 
1444
 
                ddir2 = talloc_strdup(ctx, "");
1445
 
                if (!ddir2) {
1446
 
                        return 1;
1447
 
                }
1448
 
 
1449
 
                if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
1450
 
                        return 1;
1451
 
                }
1452
 
 
1453
 
                ddir = talloc_strdup(ctx, targetname);
1454
 
                if (!ddir) {
1455
 
                        return 1;
1456
 
                }
1457
 
                trim_char(ddir,'.','\0');
1458
 
                p = strtok_r(ddir, "/\\", &saveptr);
1459
 
                while (p) {
1460
 
                        ddir2 = talloc_asprintf_append(ddir2, "%s", p);
1461
 
                        if (!ddir2) {
1462
 
                                return 1;
1463
 
                        }
1464
 
                        if (!NT_STATUS_IS_OK(cli_chkpath(targetcli, ddir2))) {
1465
 
                                do_mkdir(ddir2);
1466
 
                        }
1467
 
                        ddir2 = talloc_asprintf_append(ddir2, "%s", CLI_DIRSEP_STR);
1468
 
                        if (!ddir2) {
1469
 
                                return 1;
1470
 
                        }
1471
 
                        p = strtok_r(NULL, "/\\", &saveptr);
1472
 
                }
1473
 
        } else {
1474
 
                do_mkdir(mask);
1475
 
        }
1476
 
 
1477
 
        return 0;
1478
 
}
1479
 
 
1480
 
/****************************************************************************
1481
 
 Show alt name.
1482
 
****************************************************************************/
1483
 
 
1484
 
static int cmd_altname(void)
1485
 
{
1486
 
        TALLOC_CTX *ctx = talloc_tos();
1487
 
        char *name;
1488
 
        char *buf;
1489
 
 
1490
 
        name = talloc_strdup(ctx, client_get_cur_dir());
1491
 
        if (!name) {
1492
 
                return 1;
1493
 
        }
1494
 
 
1495
 
        if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
1496
 
                d_printf("altname <file>\n");
1497
 
                return 1;
1498
 
        }
1499
 
        name = talloc_asprintf_append(name, "%s", buf);
1500
 
        if (!name) {
1501
 
                return 1;
1502
 
        }
1503
 
        do_altname(name);
1504
 
        return 0;
1505
 
}
1506
 
 
1507
 
/****************************************************************************
1508
 
 Show all info we can get
1509
 
****************************************************************************/
1510
 
 
1511
 
static int do_allinfo(const char *name)
1512
 
{
1513
 
        fstring altname;
1514
 
        struct timespec b_time, a_time, m_time, c_time;
1515
 
        SMB_OFF_T size;
1516
 
        uint16_t mode;
1517
 
        SMB_INO_T ino;
1518
 
        NTTIME tmp;
1519
 
        unsigned int num_streams;
1520
 
        struct stream_struct *streams;
1521
 
        unsigned int i;
1522
 
 
1523
 
        if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
1524
 
                d_printf("%s getting alt name for %s\n",
1525
 
                         cli_errstr(cli),name);
1526
 
                return false;
1527
 
        }
1528
 
        d_printf("altname: %s\n", altname);
1529
 
 
1530
 
        if (!cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time,
1531
 
                            &size, &mode, &ino)) {
1532
 
                d_printf("%s getting pathinfo for %s\n",
1533
 
                         cli_errstr(cli),name);
1534
 
                return false;
1535
 
        }
1536
 
 
1537
 
        unix_timespec_to_nt_time(&tmp, b_time);
1538
 
        d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1539
 
 
1540
 
        unix_timespec_to_nt_time(&tmp, a_time);
1541
 
        d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1542
 
 
1543
 
        unix_timespec_to_nt_time(&tmp, m_time);
1544
 
        d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
1545
 
 
1546
 
        unix_timespec_to_nt_time(&tmp, c_time);
1547
 
        d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
1548
 
 
1549
 
        if (!cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
1550
 
                                   &streams)) {
1551
 
                d_printf("%s getting streams for %s\n",
1552
 
                         cli_errstr(cli),name);
1553
 
                return false;
1554
 
        }
1555
 
 
1556
 
        for (i=0; i<num_streams; i++) {
1557
 
                d_printf("stream: [%s], %lld bytes\n", streams[i].name,
1558
 
                         (unsigned long long)streams[i].size);
1559
 
        }
1560
 
 
1561
 
        return 0;
1562
 
}
1563
 
 
1564
 
/****************************************************************************
1565
 
 Show all info we can get
1566
 
****************************************************************************/
1567
 
 
1568
 
static int cmd_allinfo(void)
1569
 
{
1570
 
        TALLOC_CTX *ctx = talloc_tos();
1571
 
        char *name;
1572
 
        char *buf;
1573
 
 
1574
 
        name = talloc_strdup(ctx, client_get_cur_dir());
1575
 
        if (!name) {
1576
 
                return 1;
1577
 
        }
1578
 
 
1579
 
        if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
1580
 
                d_printf("allinfo <file>\n");
1581
 
                return 1;
1582
 
        }
1583
 
        name = talloc_asprintf_append(name, "%s", buf);
1584
 
        if (!name) {
1585
 
                return 1;
1586
 
        }
1587
 
 
1588
 
        do_allinfo(name);
1589
 
 
1590
 
        return 0;
1591
 
}
1592
 
 
1593
 
/****************************************************************************
1594
 
 Put a single file.
1595
 
****************************************************************************/
1596
 
 
1597
 
static int do_put(const char *rname, const char *lname, bool reput)
1598
 
{
1599
 
        TALLOC_CTX *ctx = talloc_tos();
1600
 
        uint16_t fnum;
1601
 
        XFILE *f;
1602
 
        SMB_OFF_T start = 0;
1603
 
        int rc = 0;
1604
 
        struct timeval tp_start;
1605
 
        struct cli_state *targetcli;
1606
 
        char *targetname = NULL;
1607
 
        struct push_state state;
1608
 
        NTSTATUS status;
1609
 
 
1610
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname)) {
1611
 
                d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
1612
 
                return 1;
1613
 
        }
1614
 
 
1615
 
        GetTimeOfDay(&tp_start);
1616
 
 
1617
 
        if (reput) {
1618
 
                status = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
1619
 
                if (NT_STATUS_IS_OK(status)) {
1620
 
                        if (!cli_qfileinfo(targetcli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
1621
 
                            !NT_STATUS_IS_OK(cli_getattrE(targetcli, fnum, NULL, &start, NULL, NULL, NULL))) {
1622
 
                                d_printf("getattrib: %s\n",cli_errstr(cli));
1623
 
                                return 1;
1624
 
                        }
1625
 
                }
1626
 
        } else {
1627
 
                status = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
1628
 
        }
1629
 
 
1630
 
        if (!NT_STATUS_IS_OK(status)) {
1631
 
                d_printf("%s opening remote file %s\n",cli_errstr(targetcli),rname);
1632
 
                return 1;
1633
 
        }
1634
 
 
1635
 
        /* allow files to be piped into smbclient
1636
 
           jdblair 24.jun.98
1637
 
 
1638
 
           Note that in this case this function will exit(0) rather
1639
 
           than returning. */
1640
 
        if (!strcmp(lname, "-")) {
1641
 
                f = x_stdin;
1642
 
                /* size of file is not known */
1643
 
        } else {
1644
 
                f = x_fopen(lname,O_RDONLY, 0);
1645
 
                if (f && reput) {
1646
 
                        if (x_tseek(f, start, SEEK_SET) == -1) {
1647
 
                                d_printf("Error seeking local file\n");
1648
 
                                x_fclose(f);
1649
 
                                return 1;
1650
 
                        }
1651
 
                }
1652
 
        }
1653
 
 
1654
 
        if (!f) {
1655
 
                d_printf("Error opening local file %s\n",lname);
1656
 
                return 1;
1657
 
        }
1658
 
 
1659
 
        DEBUG(1,("putting file %s as %s ",lname,
1660
 
                 rname));
1661
 
 
1662
 
        x_setvbuf(f, NULL, X_IOFBF, io_bufsize);
1663
 
 
1664
 
        state.f = f;
1665
 
        state.nread = 0;
1666
 
 
1667
 
        status = cli_push(targetcli, fnum, 0, 0, io_bufsize, push_source,
1668
 
                          &state);
1669
 
        if (!NT_STATUS_IS_OK(status)) {
1670
 
                d_fprintf(stderr, "cli_push returned %s\n", nt_errstr(status));
1671
 
        }
1672
 
 
1673
 
        if (!NT_STATUS_IS_OK(cli_close(targetcli, fnum))) {
1674
 
                d_printf("%s closing remote file %s\n",cli_errstr(cli),rname);
1675
 
                if (f != x_stdin) {
1676
 
                        x_fclose(f);
1677
 
                }
1678
 
                return 1;
1679
 
        }
1680
 
 
1681
 
        if (f != x_stdin) {
1682
 
                x_fclose(f);
1683
 
        }
1684
 
 
1685
 
        {
1686
 
                struct timeval tp_end;
1687
 
                int this_time;
1688
 
 
1689
 
                GetTimeOfDay(&tp_end);
1690
 
                this_time =
1691
 
                        (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1692
 
                        (tp_end.tv_usec - tp_start.tv_usec)/1000;
1693
 
                put_total_time_ms += this_time;
1694
 
                put_total_size += state.nread;
1695
 
 
1696
 
                DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
1697
 
                         state.nread / (1.024*this_time + 1.0e-4),
1698
 
                         put_total_size / (1.024*put_total_time_ms)));
1699
 
        }
1700
 
 
1701
 
        if (f == x_stdin) {
1702
 
                cli_shutdown(cli);
1703
 
                exit(0);
1704
 
        }
1705
 
 
1706
 
        return rc;
1707
 
}
1708
 
 
1709
 
/****************************************************************************
1710
 
 Put a file.
1711
 
****************************************************************************/
1712
 
 
1713
 
static int cmd_put(void)
1714
 
{
1715
 
        TALLOC_CTX *ctx = talloc_tos();
1716
 
        char *lname;
1717
 
        char *rname;
1718
 
        char *buf;
1719
 
 
1720
 
        rname = talloc_strdup(ctx, client_get_cur_dir());
1721
 
        if (!rname) {
1722
 
                return 1;
1723
 
        }
1724
 
 
1725
 
        if (!next_token_talloc(ctx, &cmd_ptr,&lname,NULL)) {
1726
 
                d_printf("put <filename>\n");
1727
 
                return 1;
1728
 
        }
1729
 
 
1730
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1731
 
                rname = talloc_asprintf_append(rname, "%s", buf);
1732
 
        } else {
1733
 
                rname = talloc_asprintf_append(rname, "%s", lname);
1734
 
        }
1735
 
        if (!rname) {
1736
 
                return 1;
1737
 
        }
1738
 
 
1739
 
        rname = clean_name(ctx, rname);
1740
 
        if (!rname) {
1741
 
                return 1;
1742
 
        }
1743
 
 
1744
 
        {
1745
 
                SMB_STRUCT_STAT st;
1746
 
                /* allow '-' to represent stdin
1747
 
                   jdblair, 24.jun.98 */
1748
 
                if (!file_exist_stat(lname, &st, false) &&
1749
 
                    (strcmp(lname,"-"))) {
1750
 
                        d_printf("%s does not exist\n",lname);
1751
 
                        return 1;
1752
 
                }
1753
 
        }
1754
 
 
1755
 
        return do_put(rname, lname, false);
1756
 
}
1757
 
 
1758
 
/*************************************
1759
 
 File list structure.
1760
 
*************************************/
1761
 
 
1762
 
static struct file_list {
1763
 
        struct file_list *prev, *next;
1764
 
        char *file_path;
1765
 
        bool isdir;
1766
 
} *file_list;
1767
 
 
1768
 
/****************************************************************************
1769
 
 Free a file_list structure.
1770
 
****************************************************************************/
1771
 
 
1772
 
static void free_file_list (struct file_list *l_head)
1773
 
{
1774
 
        struct file_list *list, *next;
1775
 
 
1776
 
        for (list = l_head; list; list = next) {
1777
 
                next = list->next;
1778
 
                DLIST_REMOVE(l_head, list);
1779
 
                SAFE_FREE(list->file_path);
1780
 
                SAFE_FREE(list);
1781
 
        }
1782
 
}
1783
 
 
1784
 
/****************************************************************************
1785
 
 Seek in a directory/file list until you get something that doesn't start with
1786
 
 the specified name.
1787
 
****************************************************************************/
1788
 
 
1789
 
static bool seek_list(struct file_list *list, char *name)
1790
 
{
1791
 
        while (list) {
1792
 
                trim_string(list->file_path,"./","\n");
1793
 
                if (strncmp(list->file_path, name, strlen(name)) != 0) {
1794
 
                        return true;
1795
 
                }
1796
 
                list = list->next;
1797
 
        }
1798
 
 
1799
 
        return false;
1800
 
}
1801
 
 
1802
 
/****************************************************************************
1803
 
 Set the file selection mask.
1804
 
****************************************************************************/
1805
 
 
1806
 
static int cmd_select(void)
1807
 
{
1808
 
        TALLOC_CTX *ctx = talloc_tos();
1809
 
        char *new_fs = NULL;
1810
 
        next_token_talloc(ctx, &cmd_ptr,&new_fs,NULL)
1811
 
                ;
1812
 
        if (new_fs) {
1813
 
                client_set_fileselection(new_fs);
1814
 
        } else {
1815
 
                client_set_fileselection("");
1816
 
        }
1817
 
        return 0;
1818
 
}
1819
 
 
1820
 
/****************************************************************************
1821
 
  Recursive file matching function act as find
1822
 
  match must be always set to true when calling this function
1823
 
****************************************************************************/
1824
 
 
1825
 
static int file_find(struct file_list **list, const char *directory,
1826
 
                      const char *expression, bool match)
1827
 
{
1828
 
        SMB_STRUCT_DIR *dir;
1829
 
        struct file_list *entry;
1830
 
        struct stat statbuf;
1831
 
        int ret;
1832
 
        char *path;
1833
 
        bool isdir;
1834
 
        const char *dname;
1835
 
 
1836
 
        dir = sys_opendir(directory);
1837
 
        if (!dir)
1838
 
                return -1;
1839
 
 
1840
 
        while ((dname = readdirname(dir))) {
1841
 
                if (!strcmp("..", dname))
1842
 
                        continue;
1843
 
                if (!strcmp(".", dname))
1844
 
                        continue;
1845
 
 
1846
 
                if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
1847
 
                        continue;
1848
 
                }
1849
 
 
1850
 
                isdir = false;
1851
 
                if (!match || !gen_fnmatch(expression, dname)) {
1852
 
                        if (recurse) {
1853
 
                                ret = stat(path, &statbuf);
1854
 
                                if (ret == 0) {
1855
 
                                        if (S_ISDIR(statbuf.st_mode)) {
1856
 
                                                isdir = true;
1857
 
                                                ret = file_find(list, path, expression, false);
1858
 
                                        }
1859
 
                                } else {
1860
 
                                        d_printf("file_find: cannot stat file %s\n", path);
1861
 
                                }
1862
 
 
1863
 
                                if (ret == -1) {
1864
 
                                        SAFE_FREE(path);
1865
 
                                        sys_closedir(dir);
1866
 
                                        return -1;
1867
 
                                }
1868
 
                        }
1869
 
                        entry = SMB_MALLOC_P(struct file_list);
1870
 
                        if (!entry) {
1871
 
                                d_printf("Out of memory in file_find\n");
1872
 
                                sys_closedir(dir);
1873
 
                                return -1;
1874
 
                        }
1875
 
                        entry->file_path = path;
1876
 
                        entry->isdir = isdir;
1877
 
                        DLIST_ADD(*list, entry);
1878
 
                } else {
1879
 
                        SAFE_FREE(path);
1880
 
                }
1881
 
        }
1882
 
 
1883
 
        sys_closedir(dir);
1884
 
        return 0;
1885
 
}
1886
 
 
1887
 
/****************************************************************************
1888
 
 mput some files.
1889
 
****************************************************************************/
1890
 
 
1891
 
static int cmd_mput(void)
1892
 
{
1893
 
        TALLOC_CTX *ctx = talloc_tos();
1894
 
        char *p = NULL;
1895
 
 
1896
 
        while (next_token_talloc(ctx, &cmd_ptr,&p,NULL)) {
1897
 
                int ret;
1898
 
                struct file_list *temp_list;
1899
 
                char *quest, *lname, *rname;
1900
 
 
1901
 
                file_list = NULL;
1902
 
 
1903
 
                ret = file_find(&file_list, ".", p, true);
1904
 
                if (ret) {
1905
 
                        free_file_list(file_list);
1906
 
                        continue;
1907
 
                }
1908
 
 
1909
 
                quest = NULL;
1910
 
                lname = NULL;
1911
 
                rname = NULL;
1912
 
 
1913
 
                for (temp_list = file_list; temp_list;
1914
 
                     temp_list = temp_list->next) {
1915
 
 
1916
 
                        SAFE_FREE(lname);
1917
 
                        if (asprintf(&lname, "%s/", temp_list->file_path) <= 0) {
1918
 
                                continue;
1919
 
                        }
1920
 
                        trim_string(lname, "./", "/");
1921
 
 
1922
 
                        /* check if it's a directory */
1923
 
                        if (temp_list->isdir) {
1924
 
                                /* if (!recurse) continue; */
1925
 
 
1926
 
                                SAFE_FREE(quest);
1927
 
                                if (asprintf(&quest, "Put directory %s? ", lname) < 0) {
1928
 
                                        break;
1929
 
                                }
1930
 
                                if (prompt && !yesno(quest)) { /* No */
1931
 
                                        /* Skip the directory */
1932
 
                                        lname[strlen(lname)-1] = '/';
1933
 
                                        if (!seek_list(temp_list, lname))
1934
 
                                                break;
1935
 
                                } else { /* Yes */
1936
 
                                        SAFE_FREE(rname);
1937
 
                                        if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
1938
 
                                                break;
1939
 
                                        }
1940
 
                                        normalize_name(rname);
1941
 
                                        if (!NT_STATUS_IS_OK(cli_chkpath(cli, rname)) &&
1942
 
                                            !do_mkdir(rname)) {
1943
 
                                                DEBUG (0, ("Unable to make dir, skipping..."));
1944
 
                                                /* Skip the directory */
1945
 
                                                lname[strlen(lname)-1] = '/';
1946
 
                                                if (!seek_list(temp_list, lname)) {
1947
 
                                                        break;
1948
 
                                                }
1949
 
                                        }
1950
 
                                }
1951
 
                                continue;
1952
 
                        } else {
1953
 
                                SAFE_FREE(quest);
1954
 
                                if (asprintf(&quest,"Put file %s? ", lname) < 0) {
1955
 
                                        break;
1956
 
                                }
1957
 
                                if (prompt && !yesno(quest)) {
1958
 
                                        /* No */
1959
 
                                        continue;
1960
 
                                }
1961
 
 
1962
 
                                /* Yes */
1963
 
                                SAFE_FREE(rname);
1964
 
                                if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
1965
 
                                        break;
1966
 
                                }
1967
 
                        }
1968
 
 
1969
 
                        normalize_name(rname);
1970
 
 
1971
 
                        do_put(rname, lname, false);
1972
 
                }
1973
 
                free_file_list(file_list);
1974
 
                SAFE_FREE(quest);
1975
 
                SAFE_FREE(lname);
1976
 
                SAFE_FREE(rname);
1977
 
        }
1978
 
 
1979
 
        return 0;
1980
 
}
1981
 
 
1982
 
/****************************************************************************
1983
 
 Cancel a print job.
1984
 
****************************************************************************/
1985
 
 
1986
 
static int do_cancel(int job)
1987
 
{
1988
 
        if (cli_printjob_del(cli, job)) {
1989
 
                d_printf("Job %d cancelled\n",job);
1990
 
                return 0;
1991
 
        } else {
1992
 
                d_printf("Error cancelling job %d : %s\n",job,cli_errstr(cli));
1993
 
                return 1;
1994
 
        }
1995
 
}
1996
 
 
1997
 
/****************************************************************************
1998
 
 Cancel a print job.
1999
 
****************************************************************************/
2000
 
 
2001
 
static int cmd_cancel(void)
2002
 
{
2003
 
        TALLOC_CTX *ctx = talloc_tos();
2004
 
        char *buf = NULL;
2005
 
        int job;
2006
 
 
2007
 
        if (!next_token_talloc(ctx, &cmd_ptr, &buf,NULL)) {
2008
 
                d_printf("cancel <jobid> ...\n");
2009
 
                return 1;
2010
 
        }
2011
 
        do {
2012
 
                job = atoi(buf);
2013
 
                do_cancel(job);
2014
 
        } while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL));
2015
 
 
2016
 
        return 0;
2017
 
}
2018
 
 
2019
 
/****************************************************************************
2020
 
 Print a file.
2021
 
****************************************************************************/
2022
 
 
2023
 
static int cmd_print(void)
2024
 
{
2025
 
        TALLOC_CTX *ctx = talloc_tos();
2026
 
        char *lname = NULL;
2027
 
        char *rname = NULL;
2028
 
        char *p = NULL;
2029
 
 
2030
 
        if (!next_token_talloc(ctx, &cmd_ptr, &lname,NULL)) {
2031
 
                d_printf("print <filename>\n");
2032
 
                return 1;
2033
 
        }
2034
 
 
2035
 
        rname = talloc_strdup(ctx, lname);
2036
 
        if (!rname) {
2037
 
                return 1;
2038
 
        }
2039
 
        p = strrchr_m(rname,'/');
2040
 
        if (p) {
2041
 
                rname = talloc_asprintf(ctx,
2042
 
                                        "%s-%d",
2043
 
                                        p+1,
2044
 
                                        (int)sys_getpid());
2045
 
        }
2046
 
        if (strequal(lname,"-")) {
2047
 
                rname = talloc_asprintf(ctx,
2048
 
                                "stdin-%d",
2049
 
                                (int)sys_getpid());
2050
 
        }
2051
 
        if (!rname) {
2052
 
                return 1;
2053
 
        }
2054
 
 
2055
 
        return do_put(rname, lname, false);
2056
 
}
2057
 
 
2058
 
/****************************************************************************
2059
 
 Show a print queue entry.
2060
 
****************************************************************************/
2061
 
 
2062
 
static void queue_fn(struct print_job_info *p)
2063
 
{
2064
 
        d_printf("%-6d   %-9d    %s\n", (int)p->id, (int)p->size, p->name);
2065
 
}
2066
 
 
2067
 
/****************************************************************************
2068
 
 Show a print queue.
2069
 
****************************************************************************/
2070
 
 
2071
 
static int cmd_queue(void)
2072
 
{
2073
 
        cli_print_queue(cli, queue_fn);
2074
 
        return 0;
2075
 
}
2076
 
 
2077
 
/****************************************************************************
2078
 
 Delete some files.
2079
 
****************************************************************************/
2080
 
 
2081
 
static void do_del(file_info *finfo, const char *dir)
2082
 
{
2083
 
        TALLOC_CTX *ctx = talloc_tos();
2084
 
        char *mask = NULL;
2085
 
 
2086
 
        mask = talloc_asprintf(ctx,
2087
 
                                "%s%c%s",
2088
 
                                dir,
2089
 
                                CLI_DIRSEP_CHAR,
2090
 
                                finfo->name);
2091
 
        if (!mask) {
2092
 
                return;
2093
 
        }
2094
 
 
2095
 
        if (finfo->mode & aDIR) {
2096
 
                TALLOC_FREE(mask);
2097
 
                return;
2098
 
        }
2099
 
 
2100
 
        if (!NT_STATUS_IS_OK(cli_unlink(finfo->cli, mask, aSYSTEM | aHIDDEN))) {
2101
 
                d_printf("%s deleting remote file %s\n",
2102
 
                                cli_errstr(finfo->cli),mask);
2103
 
        }
2104
 
        TALLOC_FREE(mask);
2105
 
}
2106
 
 
2107
 
/****************************************************************************
2108
 
 Delete some files.
2109
 
****************************************************************************/
2110
 
 
2111
 
static int cmd_del(void)
2112
 
{
2113
 
        TALLOC_CTX *ctx = talloc_tos();
2114
 
        char *mask = NULL;
2115
 
        char *buf = NULL;
2116
 
        uint16 attribute = aSYSTEM | aHIDDEN;
2117
 
 
2118
 
        if (recurse) {
2119
 
                attribute |= aDIR;
2120
 
        }
2121
 
 
2122
 
        mask = talloc_strdup(ctx, client_get_cur_dir());
2123
 
        if (!mask) {
2124
 
                return 1;
2125
 
        }
2126
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2127
 
                d_printf("del <filename>\n");
2128
 
                return 1;
2129
 
        }
2130
 
        mask = talloc_asprintf_append(mask, "%s", buf);
2131
 
        if (!mask) {
2132
 
                return 1;
2133
 
        }
2134
 
 
2135
 
        do_list(mask,attribute,do_del,false,false);
2136
 
        return 0;
2137
 
}
2138
 
 
2139
 
/****************************************************************************
2140
 
 Wildcard delete some files.
2141
 
****************************************************************************/
2142
 
 
2143
 
static int cmd_wdel(void)
2144
 
{
2145
 
        TALLOC_CTX *ctx = talloc_tos();
2146
 
        char *mask = NULL;
2147
 
        char *buf = NULL;
2148
 
        uint16 attribute;
2149
 
        struct cli_state *targetcli;
2150
 
        char *targetname = NULL;
2151
 
 
2152
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2153
 
                d_printf("wdel 0x<attrib> <wcard>\n");
2154
 
                return 1;
2155
 
        }
2156
 
 
2157
 
        attribute = (uint16)strtol(buf, (char **)NULL, 16);
2158
 
 
2159
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2160
 
                d_printf("wdel 0x<attrib> <wcard>\n");
2161
 
                return 1;
2162
 
        }
2163
 
 
2164
 
        mask = talloc_asprintf(ctx, "%s%s",
2165
 
                        client_get_cur_dir(),
2166
 
                        buf);
2167
 
        if (!mask) {
2168
 
                return 1;
2169
 
        }
2170
 
 
2171
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2172
 
                d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
2173
 
                return 1;
2174
 
        }
2175
 
 
2176
 
        if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetname, attribute))) {
2177
 
                d_printf("%s deleting remote files %s\n",cli_errstr(targetcli),targetname);
2178
 
        }
2179
 
        return 0;
2180
 
}
2181
 
 
2182
 
/****************************************************************************
2183
 
****************************************************************************/
2184
 
 
2185
 
static int cmd_open(void)
2186
 
{
2187
 
        TALLOC_CTX *ctx = talloc_tos();
2188
 
        char *mask = NULL;
2189
 
        char *buf = NULL;
2190
 
        char *targetname = NULL;
2191
 
        struct cli_state *targetcli;
2192
 
        uint16_t fnum = (uint16_t)-1;
2193
 
 
2194
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2195
 
                d_printf("open <filename>\n");
2196
 
                return 1;
2197
 
        }
2198
 
        mask = talloc_asprintf(ctx,
2199
 
                        "%s%s",
2200
 
                        client_get_cur_dir(),
2201
 
                        buf);
2202
 
        if (!mask) {
2203
 
                return 1;
2204
 
        }
2205
 
 
2206
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2207
 
                d_printf("open %s: %s\n", mask, cli_errstr(cli));
2208
 
                return 1;
2209
 
        }
2210
 
 
2211
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetname, 0,
2212
 
                        FILE_READ_DATA|FILE_WRITE_DATA, 0,
2213
 
                        FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
2214
 
                if (NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetname, 0,
2215
 
                                FILE_READ_DATA, 0,
2216
 
                                FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
2217
 
                        d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
2218
 
                } else {
2219
 
                        d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
2220
 
                }
2221
 
        } else {
2222
 
                d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
2223
 
        }
2224
 
        return 0;
2225
 
}
2226
 
 
2227
 
static int cmd_posix_encrypt(void)
2228
 
{
2229
 
        TALLOC_CTX *ctx = talloc_tos();
2230
 
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2231
 
 
2232
 
        if (cli->use_kerberos) {
2233
 
                status = cli_gss_smb_encryption_start(cli);
2234
 
        } else {
2235
 
                char *domain = NULL;
2236
 
                char *user = NULL;
2237
 
                char *password = NULL;
2238
 
 
2239
 
                if (!next_token_talloc(ctx, &cmd_ptr,&domain,NULL)) {
2240
 
                        d_printf("posix_encrypt domain user password\n");
2241
 
                        return 1;
2242
 
                }
2243
 
 
2244
 
                if (!next_token_talloc(ctx, &cmd_ptr,&user,NULL)) {
2245
 
                        d_printf("posix_encrypt domain user password\n");
2246
 
                        return 1;
2247
 
                }
2248
 
 
2249
 
                if (!next_token_talloc(ctx, &cmd_ptr,&password,NULL)) {
2250
 
                        d_printf("posix_encrypt domain user password\n");
2251
 
                        return 1;
2252
 
                }
2253
 
 
2254
 
                status = cli_raw_ntlm_smb_encryption_start(cli,
2255
 
                                                        user,
2256
 
                                                        password,
2257
 
                                                        domain);
2258
 
        }
2259
 
 
2260
 
        if (!NT_STATUS_IS_OK(status)) {
2261
 
                d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
2262
 
        } else {
2263
 
                d_printf("encryption on\n");
2264
 
                smb_encrypt = true;
2265
 
        }
2266
 
 
2267
 
        return 0;
2268
 
}
2269
 
 
2270
 
/****************************************************************************
2271
 
****************************************************************************/
2272
 
 
2273
 
static int cmd_posix_open(void)
2274
 
{
2275
 
        TALLOC_CTX *ctx = talloc_tos();
2276
 
        char *mask = NULL;
2277
 
        char *buf = NULL;
2278
 
        char *targetname = NULL;
2279
 
        struct cli_state *targetcli;
2280
 
        mode_t mode;
2281
 
        uint16_t fnum;
2282
 
 
2283
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2284
 
                d_printf("posix_open <filename> 0<mode>\n");
2285
 
                return 1;
2286
 
        }
2287
 
        mask = talloc_asprintf(ctx,
2288
 
                        "%s%s",
2289
 
                        client_get_cur_dir(),
2290
 
                        buf);
2291
 
        if (!mask) {
2292
 
                return 1;
2293
 
        }
2294
 
 
2295
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2296
 
                d_printf("posix_open <filename> 0<mode>\n");
2297
 
                return 1;
2298
 
        }
2299
 
        mode = (mode_t)strtol(buf, (char **)NULL, 8);
2300
 
 
2301
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2302
 
                d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
2303
 
                return 1;
2304
 
        }
2305
 
 
2306
 
        if (!NT_STATUS_IS_OK(cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode, &fnum))) {
2307
 
                if (!NT_STATUS_IS_OK(cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode, &fnum))) {
2308
 
                        d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
2309
 
                } else {
2310
 
                        d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
2311
 
                }
2312
 
        } else {
2313
 
                d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
2314
 
        }
2315
 
 
2316
 
        return 0;
2317
 
}
2318
 
 
2319
 
static int cmd_posix_mkdir(void)
2320
 
{
2321
 
        TALLOC_CTX *ctx = talloc_tos();
2322
 
        char *mask = NULL;
2323
 
        char *buf = NULL;
2324
 
        char *targetname = NULL;
2325
 
        struct cli_state *targetcli;
2326
 
        mode_t mode;
2327
 
 
2328
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2329
 
                d_printf("posix_mkdir <filename> 0<mode>\n");
2330
 
                return 1;
2331
 
        }
2332
 
        mask = talloc_asprintf(ctx,
2333
 
                        "%s%s",
2334
 
                        client_get_cur_dir(),
2335
 
                        buf);
2336
 
        if (!mask) {
2337
 
                return 1;
2338
 
        }
2339
 
 
2340
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2341
 
                d_printf("posix_mkdir <filename> 0<mode>\n");
2342
 
                return 1;
2343
 
        }
2344
 
        mode = (mode_t)strtol(buf, (char **)NULL, 8);
2345
 
 
2346
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2347
 
                d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
2348
 
                return 1;
2349
 
        }
2350
 
 
2351
 
        if (!NT_STATUS_IS_OK(cli_posix_mkdir(targetcli, targetname, mode))) {
2352
 
                d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
2353
 
        } else {
2354
 
                d_printf("posix_mkdir created directory %s\n", targetname);
2355
 
        }
2356
 
        return 0;
2357
 
}
2358
 
 
2359
 
static int cmd_posix_unlink(void)
2360
 
{
2361
 
        TALLOC_CTX *ctx = talloc_tos();
2362
 
        char *mask = NULL;
2363
 
        char *buf = NULL;
2364
 
        char *targetname = NULL;
2365
 
        struct cli_state *targetcli;
2366
 
 
2367
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2368
 
                d_printf("posix_unlink <filename>\n");
2369
 
                return 1;
2370
 
        }
2371
 
        mask = talloc_asprintf(ctx,
2372
 
                        "%s%s",
2373
 
                        client_get_cur_dir(),
2374
 
                        buf);
2375
 
        if (!mask) {
2376
 
                return 1;
2377
 
        }
2378
 
 
2379
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2380
 
                d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
2381
 
                return 1;
2382
 
        }
2383
 
 
2384
 
        if (!NT_STATUS_IS_OK(cli_posix_unlink(targetcli, targetname))) {
2385
 
                d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
2386
 
        } else {
2387
 
                d_printf("posix_unlink deleted file %s\n", targetname);
2388
 
        }
2389
 
 
2390
 
        return 0;
2391
 
}
2392
 
 
2393
 
static int cmd_posix_rmdir(void)
2394
 
{
2395
 
        TALLOC_CTX *ctx = talloc_tos();
2396
 
        char *mask = NULL;
2397
 
        char *buf = NULL;
2398
 
        char *targetname = NULL;
2399
 
        struct cli_state *targetcli;
2400
 
 
2401
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2402
 
                d_printf("posix_rmdir <filename>\n");
2403
 
                return 1;
2404
 
        }
2405
 
        mask = talloc_asprintf(ctx,
2406
 
                        "%s%s",
2407
 
                        client_get_cur_dir(),
2408
 
                        buf);
2409
 
        if (!mask) {
2410
 
                return 1;
2411
 
        }
2412
 
 
2413
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2414
 
                d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
2415
 
                return 1;
2416
 
        }
2417
 
 
2418
 
        if (!NT_STATUS_IS_OK(cli_posix_rmdir(targetcli, targetname))) {
2419
 
                d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
2420
 
        } else {
2421
 
                d_printf("posix_rmdir deleted directory %s\n", targetname);
2422
 
        }
2423
 
 
2424
 
        return 0;
2425
 
}
2426
 
 
2427
 
static int cmd_close(void)
2428
 
{
2429
 
        TALLOC_CTX *ctx = talloc_tos();
2430
 
        char *buf = NULL;
2431
 
        int fnum;
2432
 
 
2433
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2434
 
                d_printf("close <fnum>\n");
2435
 
                return 1;
2436
 
        }
2437
 
 
2438
 
        fnum = atoi(buf);
2439
 
        /* We really should use the targetcli here.... */
2440
 
        if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
2441
 
                d_printf("close %d: %s\n", fnum, cli_errstr(cli));
2442
 
                return 1;
2443
 
        }
2444
 
        return 0;
2445
 
}
2446
 
 
2447
 
static int cmd_posix(void)
2448
 
{
2449
 
        TALLOC_CTX *ctx = talloc_tos();
2450
 
        uint16 major, minor;
2451
 
        uint32 caplow, caphigh;
2452
 
        char *caps;
2453
 
        NTSTATUS status;
2454
 
 
2455
 
        if (!SERVER_HAS_UNIX_CIFS(cli)) {
2456
 
                d_printf("Server doesn't support UNIX CIFS extensions.\n");
2457
 
                return 1;
2458
 
        }
2459
 
 
2460
 
        status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
2461
 
                                             &caphigh);
2462
 
        if (!NT_STATUS_IS_OK(status)) {
2463
 
                d_printf("Can't get UNIX CIFS extensions version from "
2464
 
                         "server: %s\n", nt_errstr(status));
2465
 
                return 1;
2466
 
        }
2467
 
 
2468
 
        d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor);
2469
 
 
2470
 
        caps = talloc_strdup(ctx, "");
2471
 
        if (!caps) {
2472
 
                return 1;
2473
 
        }
2474
 
        if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2475
 
                caps = talloc_asprintf_append(caps, "locks ");
2476
 
                if (!caps) {
2477
 
                        return 1;
2478
 
                }
2479
 
        }
2480
 
        if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) {
2481
 
                caps = talloc_asprintf_append(caps, "acls ");
2482
 
                if (!caps) {
2483
 
                        return 1;
2484
 
                }
2485
 
        }
2486
 
        if (caplow & CIFS_UNIX_XATTTR_CAP) {
2487
 
                caps = talloc_asprintf_append(caps, "eas ");
2488
 
                if (!caps) {
2489
 
                        return 1;
2490
 
                }
2491
 
        }
2492
 
        if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2493
 
                caps = talloc_asprintf_append(caps, "pathnames ");
2494
 
                if (!caps) {
2495
 
                        return 1;
2496
 
                }
2497
 
        }
2498
 
        if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
2499
 
                caps = talloc_asprintf_append(caps, "posix_path_operations ");
2500
 
                if (!caps) {
2501
 
                        return 1;
2502
 
                }
2503
 
        }
2504
 
        if (caplow & CIFS_UNIX_LARGE_READ_CAP) {
2505
 
                caps = talloc_asprintf_append(caps, "large_read ");
2506
 
                if (!caps) {
2507
 
                        return 1;
2508
 
                }
2509
 
        }
2510
 
        if (caplow & CIFS_UNIX_LARGE_WRITE_CAP) {
2511
 
                caps = talloc_asprintf_append(caps, "large_write ");
2512
 
                if (!caps) {
2513
 
                        return 1;
2514
 
                }
2515
 
        }
2516
 
        if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) {
2517
 
                caps = talloc_asprintf_append(caps, "posix_encrypt ");
2518
 
                if (!caps) {
2519
 
                        return 1;
2520
 
                }
2521
 
        }
2522
 
        if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) {
2523
 
                caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt ");
2524
 
                if (!caps) {
2525
 
                        return 1;
2526
 
                }
2527
 
        }
2528
 
 
2529
 
        if (*caps && caps[strlen(caps)-1] == ' ') {
2530
 
                caps[strlen(caps)-1] = '\0';
2531
 
        }
2532
 
 
2533
 
        d_printf("Server supports CIFS capabilities %s\n", caps);
2534
 
 
2535
 
        if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
2536
 
                d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
2537
 
                return 1;
2538
 
        }
2539
 
 
2540
 
        if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2541
 
                CLI_DIRSEP_CHAR = '/';
2542
 
                *CLI_DIRSEP_STR = '/';
2543
 
                client_set_cur_dir(CLI_DIRSEP_STR);
2544
 
        }
2545
 
 
2546
 
        return 0;
2547
 
}
2548
 
 
2549
 
static int cmd_lock(void)
2550
 
{
2551
 
        TALLOC_CTX *ctx = talloc_tos();
2552
 
        char *buf = NULL;
2553
 
        uint64_t start, len;
2554
 
        enum brl_type lock_type;
2555
 
        int fnum;
2556
 
 
2557
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2558
 
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
2559
 
                return 1;
2560
 
        }
2561
 
        fnum = atoi(buf);
2562
 
 
2563
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2564
 
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
2565
 
                return 1;
2566
 
        }
2567
 
 
2568
 
        if (*buf == 'r' || *buf == 'R') {
2569
 
                lock_type = READ_LOCK;
2570
 
        } else if (*buf == 'w' || *buf == 'W') {
2571
 
                lock_type = WRITE_LOCK;
2572
 
        } else {
2573
 
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
2574
 
                return 1;
2575
 
        }
2576
 
 
2577
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2578
 
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
2579
 
                return 1;
2580
 
        }
2581
 
 
2582
 
        start = (uint64_t)strtol(buf, (char **)NULL, 16);
2583
 
 
2584
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2585
 
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
2586
 
                return 1;
2587
 
        }
2588
 
 
2589
 
        len = (uint64_t)strtol(buf, (char **)NULL, 16);
2590
 
 
2591
 
        if (!NT_STATUS_IS_OK(cli_posix_lock(cli, fnum, start, len, true, lock_type))) {
2592
 
                d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
2593
 
        }
2594
 
 
2595
 
        return 0;
2596
 
}
2597
 
 
2598
 
static int cmd_unlock(void)
2599
 
{
2600
 
        TALLOC_CTX *ctx = talloc_tos();
2601
 
        char *buf = NULL;
2602
 
        uint64_t start, len;
2603
 
        int fnum;
2604
 
 
2605
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2606
 
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
2607
 
                return 1;
2608
 
        }
2609
 
        fnum = atoi(buf);
2610
 
 
2611
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2612
 
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
2613
 
                return 1;
2614
 
        }
2615
 
 
2616
 
        start = (uint64_t)strtol(buf, (char **)NULL, 16);
2617
 
 
2618
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2619
 
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
2620
 
                return 1;
2621
 
        }
2622
 
 
2623
 
        len = (uint64_t)strtol(buf, (char **)NULL, 16);
2624
 
 
2625
 
        if (!NT_STATUS_IS_OK(cli_posix_unlock(cli, fnum, start, len))) {
2626
 
                d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
2627
 
        }
2628
 
 
2629
 
        return 0;
2630
 
}
2631
 
 
2632
 
 
2633
 
/****************************************************************************
2634
 
 Remove a directory.
2635
 
****************************************************************************/
2636
 
 
2637
 
static int cmd_rmdir(void)
2638
 
{
2639
 
        TALLOC_CTX *ctx = talloc_tos();
2640
 
        char *mask = NULL;
2641
 
        char *buf = NULL;
2642
 
        char *targetname = NULL;
2643
 
        struct cli_state *targetcli;
2644
 
 
2645
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2646
 
                d_printf("rmdir <dirname>\n");
2647
 
                return 1;
2648
 
        }
2649
 
        mask = talloc_asprintf(ctx,
2650
 
                        "%s%s",
2651
 
                        client_get_cur_dir(),
2652
 
                        buf);
2653
 
        if (!mask) {
2654
 
                return 1;
2655
 
        }
2656
 
 
2657
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
2658
 
                d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
2659
 
                return 1;
2660
 
        }
2661
 
 
2662
 
        if (!NT_STATUS_IS_OK(cli_rmdir(targetcli, targetname))) {
2663
 
                d_printf("%s removing remote directory file %s\n",
2664
 
                         cli_errstr(targetcli),mask);
2665
 
        }
2666
 
 
2667
 
        return 0;
2668
 
}
2669
 
 
2670
 
/****************************************************************************
2671
 
 UNIX hardlink.
2672
 
****************************************************************************/
2673
 
 
2674
 
static int cmd_link(void)
2675
 
{
2676
 
        TALLOC_CTX *ctx = talloc_tos();
2677
 
        char *oldname = NULL;
2678
 
        char *newname = NULL;
2679
 
        char *buf = NULL;
2680
 
        char *buf2 = NULL;
2681
 
        char *targetname = NULL;
2682
 
        struct cli_state *targetcli;
2683
 
 
2684
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
2685
 
            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
2686
 
                d_printf("link <oldname> <newname>\n");
2687
 
                return 1;
2688
 
        }
2689
 
        oldname = talloc_asprintf(ctx,
2690
 
                        "%s%s",
2691
 
                        client_get_cur_dir(),
2692
 
                        buf);
2693
 
        if (!oldname) {
2694
 
                return 1;
2695
 
        }
2696
 
        newname = talloc_asprintf(ctx,
2697
 
                        "%s%s",
2698
 
                        client_get_cur_dir(),
2699
 
                        buf2);
2700
 
        if (!newname) {
2701
 
                return 1;
2702
 
        }
2703
 
 
2704
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
2705
 
                d_printf("link %s: %s\n", oldname, cli_errstr(cli));
2706
 
                return 1;
2707
 
        }
2708
 
 
2709
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
2710
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
2711
 
                return 1;
2712
 
        }
2713
 
 
2714
 
        if (!NT_STATUS_IS_OK(cli_posix_hardlink(targetcli, targetname, newname))) {
2715
 
                d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
2716
 
                return 1;
2717
 
        }
2718
 
        return 0;
2719
 
}
2720
 
 
2721
 
/****************************************************************************
2722
 
 UNIX readlink.
2723
 
****************************************************************************/
2724
 
 
2725
 
static int cmd_readlink(void)
2726
 
{
2727
 
        TALLOC_CTX *ctx = talloc_tos();
2728
 
        char *name= NULL;
2729
 
        char *buf = NULL;
2730
 
        char *targetname = NULL;
2731
 
        char linkname[PATH_MAX+1];
2732
 
        struct cli_state *targetcli;
2733
 
 
2734
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
2735
 
                d_printf("readlink <name>\n");
2736
 
                return 1;
2737
 
        }
2738
 
        name = talloc_asprintf(ctx,
2739
 
                        "%s%s",
2740
 
                        client_get_cur_dir(),
2741
 
                        buf);
2742
 
        if (!name) {
2743
 
                return 1;
2744
 
        }
2745
 
 
2746
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
2747
 
                d_printf("readlink %s: %s\n", name, cli_errstr(cli));
2748
 
                return 1;
2749
 
        }
2750
 
 
2751
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
2752
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
2753
 
                return 1;
2754
 
        }
2755
 
 
2756
 
        if (!NT_STATUS_IS_OK(cli_posix_readlink(targetcli, name,
2757
 
                        linkname, PATH_MAX+1))) {
2758
 
                d_printf("%s readlink on file %s\n",
2759
 
                        cli_errstr(targetcli), name);
2760
 
                return 1;
2761
 
        }
2762
 
 
2763
 
        d_printf("%s -> %s\n", name, linkname);
2764
 
 
2765
 
        return 0;
2766
 
}
2767
 
 
2768
 
 
2769
 
/****************************************************************************
2770
 
 UNIX symlink.
2771
 
****************************************************************************/
2772
 
 
2773
 
static int cmd_symlink(void)
2774
 
{
2775
 
        TALLOC_CTX *ctx = talloc_tos();
2776
 
        char *oldname = NULL;
2777
 
        char *newname = NULL;
2778
 
        char *buf = NULL;
2779
 
        char *buf2 = NULL;
2780
 
        char *targetname = NULL;
2781
 
        struct cli_state *targetcli;
2782
 
 
2783
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
2784
 
            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
2785
 
                d_printf("symlink <oldname> <newname>\n");
2786
 
                return 1;
2787
 
        }
2788
 
        oldname = talloc_asprintf(ctx,
2789
 
                        "%s%s",
2790
 
                        client_get_cur_dir(),
2791
 
                        buf);
2792
 
        if (!oldname) {
2793
 
                return 1;
2794
 
        }
2795
 
        newname = talloc_asprintf(ctx,
2796
 
                        "%s%s",
2797
 
                        client_get_cur_dir(),
2798
 
                        buf2);
2799
 
        if (!newname) {
2800
 
                return 1;
2801
 
        }
2802
 
 
2803
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
2804
 
                d_printf("link %s: %s\n", oldname, cli_errstr(cli));
2805
 
                return 1;
2806
 
        }
2807
 
 
2808
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
2809
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
2810
 
                return 1;
2811
 
        }
2812
 
 
2813
 
        if (!NT_STATUS_IS_OK(cli_posix_symlink(targetcli, targetname, newname))) {
2814
 
                d_printf("%s symlinking files (%s -> %s)\n",
2815
 
                        cli_errstr(targetcli), newname, targetname);
2816
 
                return 1;
2817
 
        }
2818
 
 
2819
 
        return 0;
2820
 
}
2821
 
 
2822
 
/****************************************************************************
2823
 
 UNIX chmod.
2824
 
****************************************************************************/
2825
 
 
2826
 
static int cmd_chmod(void)
2827
 
{
2828
 
        TALLOC_CTX *ctx = talloc_tos();
2829
 
        char *src = NULL;
2830
 
        char *buf = NULL;
2831
 
        char *buf2 = NULL;
2832
 
        char *targetname = NULL;
2833
 
        struct cli_state *targetcli;
2834
 
        mode_t mode;
2835
 
 
2836
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
2837
 
            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
2838
 
                d_printf("chmod mode file\n");
2839
 
                return 1;
2840
 
        }
2841
 
        src = talloc_asprintf(ctx,
2842
 
                        "%s%s",
2843
 
                        client_get_cur_dir(),
2844
 
                        buf2);
2845
 
        if (!src) {
2846
 
                return 1;
2847
 
        }
2848
 
 
2849
 
        mode = (mode_t)strtol(buf, NULL, 8);
2850
 
 
2851
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
2852
 
                d_printf("chmod %s: %s\n", src, cli_errstr(cli));
2853
 
                return 1;
2854
 
        }
2855
 
 
2856
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
2857
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
2858
 
                return 1;
2859
 
        }
2860
 
 
2861
 
        if (!NT_STATUS_IS_OK(cli_posix_chmod(targetcli, targetname, mode))) {
2862
 
                d_printf("%s chmod file %s 0%o\n",
2863
 
                        cli_errstr(targetcli), src, (unsigned int)mode);
2864
 
                return 1;
2865
 
        }
2866
 
 
2867
 
        return 0;
2868
 
}
2869
 
 
2870
 
static const char *filetype_to_str(mode_t mode)
2871
 
{
2872
 
        if (S_ISREG(mode)) {
2873
 
                return "regular file";
2874
 
        } else if (S_ISDIR(mode)) {
2875
 
                return "directory";
2876
 
        } else
2877
 
#ifdef S_ISCHR
2878
 
        if (S_ISCHR(mode)) {
2879
 
                return "character device";
2880
 
        } else
2881
 
#endif
2882
 
#ifdef S_ISBLK
2883
 
        if (S_ISBLK(mode)) {
2884
 
                return "block device";
2885
 
        } else
2886
 
#endif
2887
 
#ifdef S_ISFIFO
2888
 
        if (S_ISFIFO(mode)) {
2889
 
                return "fifo";
2890
 
        } else
2891
 
#endif
2892
 
#ifdef S_ISLNK
2893
 
        if (S_ISLNK(mode)) {
2894
 
                return "symbolic link";
2895
 
        } else
2896
 
#endif
2897
 
#ifdef S_ISSOCK
2898
 
        if (S_ISSOCK(mode)) {
2899
 
                return "socket";
2900
 
        } else
2901
 
#endif
2902
 
        return "";
2903
 
}
2904
 
 
2905
 
static char rwx_to_str(mode_t m, mode_t bt, char ret)
2906
 
{
2907
 
        if (m & bt) {
2908
 
                return ret;
2909
 
        } else {
2910
 
                return '-';
2911
 
        }
2912
 
}
2913
 
 
2914
 
static char *unix_mode_to_str(char *s, mode_t m)
2915
 
{
2916
 
        char *p = s;
2917
 
        const char *str = filetype_to_str(m);
2918
 
 
2919
 
        switch(str[0]) {
2920
 
                case 'd':
2921
 
                        *p++ = 'd';
2922
 
                        break;
2923
 
                case 'c':
2924
 
                        *p++ = 'c';
2925
 
                        break;
2926
 
                case 'b':
2927
 
                        *p++ = 'b';
2928
 
                        break;
2929
 
                case 'f':
2930
 
                        *p++ = 'p';
2931
 
                        break;
2932
 
                case 's':
2933
 
                        *p++ = str[1] == 'y' ? 'l' : 's';
2934
 
                        break;
2935
 
                case 'r':
2936
 
                default:
2937
 
                        *p++ = '-';
2938
 
                        break;
2939
 
        }
2940
 
        *p++ = rwx_to_str(m, S_IRUSR, 'r');
2941
 
        *p++ = rwx_to_str(m, S_IWUSR, 'w');
2942
 
        *p++ = rwx_to_str(m, S_IXUSR, 'x');
2943
 
        *p++ = rwx_to_str(m, S_IRGRP, 'r');
2944
 
        *p++ = rwx_to_str(m, S_IWGRP, 'w');
2945
 
        *p++ = rwx_to_str(m, S_IXGRP, 'x');
2946
 
        *p++ = rwx_to_str(m, S_IROTH, 'r');
2947
 
        *p++ = rwx_to_str(m, S_IWOTH, 'w');
2948
 
        *p++ = rwx_to_str(m, S_IXOTH, 'x');
2949
 
        *p++ = '\0';
2950
 
        return s;
2951
 
}
2952
 
 
2953
 
/****************************************************************************
2954
 
 Utility function for UNIX getfacl.
2955
 
****************************************************************************/
2956
 
 
2957
 
static char *perms_to_string(fstring permstr, unsigned char perms)
2958
 
{
2959
 
        fstrcpy(permstr, "---");
2960
 
        if (perms & SMB_POSIX_ACL_READ) {
2961
 
                permstr[0] = 'r';
2962
 
        }
2963
 
        if (perms & SMB_POSIX_ACL_WRITE) {
2964
 
                permstr[1] = 'w';
2965
 
        }
2966
 
        if (perms & SMB_POSIX_ACL_EXECUTE) {
2967
 
                permstr[2] = 'x';
2968
 
        }
2969
 
        return permstr;
2970
 
}
2971
 
 
2972
 
/****************************************************************************
2973
 
 UNIX getfacl.
2974
 
****************************************************************************/
2975
 
 
2976
 
static int cmd_getfacl(void)
2977
 
{
2978
 
        TALLOC_CTX *ctx = talloc_tos();
2979
 
        char *src = NULL;
2980
 
        char *name = NULL;
2981
 
        char *targetname = NULL;
2982
 
        struct cli_state *targetcli;
2983
 
        uint16 major, minor;
2984
 
        uint32 caplow, caphigh;
2985
 
        char *retbuf = NULL;
2986
 
        size_t rb_size = 0;
2987
 
        SMB_STRUCT_STAT sbuf;
2988
 
        uint16 num_file_acls = 0;
2989
 
        uint16 num_dir_acls = 0;
2990
 
        uint16 i;
2991
 
        NTSTATUS status;
2992
 
 
2993
 
        if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
2994
 
                d_printf("getfacl filename\n");
2995
 
                return 1;
2996
 
        }
2997
 
        src = talloc_asprintf(ctx,
2998
 
                        "%s%s",
2999
 
                        client_get_cur_dir(),
3000
 
                        name);
3001
 
        if (!src) {
3002
 
                return 1;
3003
 
        }
3004
 
 
3005
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
3006
 
                d_printf("stat %s: %s\n", src, cli_errstr(cli));
3007
 
                return 1;
3008
 
        }
3009
 
 
3010
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3011
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
3012
 
                return 1;
3013
 
        }
3014
 
 
3015
 
        status = cli_unix_extensions_version(targetcli, &major, &minor,
3016
 
                                             &caplow, &caphigh);
3017
 
        if (!NT_STATUS_IS_OK(status)) {
3018
 
                d_printf("Can't get UNIX CIFS version from server: %s.\n",
3019
 
                         nt_errstr(status));
3020
 
                return 1;
3021
 
        }
3022
 
 
3023
 
        if (!(caplow & CIFS_UNIX_POSIX_ACLS_CAP)) {
3024
 
                d_printf("This server supports UNIX extensions "
3025
 
                        "but doesn't support POSIX ACLs.\n");
3026
 
                return 1;
3027
 
        }
3028
 
 
3029
 
        if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) {
3030
 
                d_printf("%s getfacl doing a stat on file %s\n",
3031
 
                        cli_errstr(targetcli), src);
3032
 
                return 1;
3033
 
        }
3034
 
 
3035
 
        if (!NT_STATUS_IS_OK(cli_posix_getfacl(targetcli, targetname, ctx, &rb_size, &retbuf))) {
3036
 
                d_printf("%s getfacl file %s\n",
3037
 
                        cli_errstr(targetcli), src);
3038
 
                return 1;
3039
 
        }
3040
 
 
3041
 
        /* ToDo : Print out the ACL values. */
3042
 
        if (rb_size < 6 || SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION) {
3043
 
                d_printf("getfacl file %s, unknown POSIX acl version %u.\n",
3044
 
                        src, (unsigned int)CVAL(retbuf,0) );
3045
 
                return 1;
3046
 
        }
3047
 
 
3048
 
        num_file_acls = SVAL(retbuf,2);
3049
 
        num_dir_acls = SVAL(retbuf,4);
3050
 
        if (rb_size != SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)) {
3051
 
                d_printf("getfacl file %s, incorrect POSIX acl buffer size (should be %u, was %u).\n",
3052
 
                        src,
3053
 
                        (unsigned int)(SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)),
3054
 
                        (unsigned int)rb_size);
3055
 
                return 1;
3056
 
        }
3057
 
 
3058
 
        d_printf("# file: %s\n", src);
3059
 
        d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_ex_uid, (unsigned int)sbuf.st_ex_gid);
3060
 
 
3061
 
        if (num_file_acls == 0 && num_dir_acls == 0) {
3062
 
                d_printf("No acls found.\n");
3063
 
        }
3064
 
 
3065
 
        for (i = 0; i < num_file_acls; i++) {
3066
 
                uint32 uorg;
3067
 
                fstring permstring;
3068
 
                unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE));
3069
 
                unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+1);
3070
 
 
3071
 
                switch(tagtype) {
3072
 
                        case SMB_POSIX_ACL_USER_OBJ:
3073
 
                                d_printf("user::");
3074
 
                                break;
3075
 
                        case SMB_POSIX_ACL_USER:
3076
 
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3077
 
                                d_printf("user:%u:", uorg);
3078
 
                                break;
3079
 
                        case SMB_POSIX_ACL_GROUP_OBJ:
3080
 
                                d_printf("group::");
3081
 
                                break;
3082
 
                        case SMB_POSIX_ACL_GROUP:
3083
 
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3084
 
                                d_printf("group:%u:", uorg);
3085
 
                                break;
3086
 
                        case SMB_POSIX_ACL_MASK:
3087
 
                                d_printf("mask::");
3088
 
                                break;
3089
 
                        case SMB_POSIX_ACL_OTHER:
3090
 
                                d_printf("other::");
3091
 
                                break;
3092
 
                        default:
3093
 
                                d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
3094
 
                                        src, (unsigned int)tagtype );
3095
 
                                SAFE_FREE(retbuf);
3096
 
                                return 1;
3097
 
                }
3098
 
 
3099
 
                d_printf("%s\n", perms_to_string(permstring, perms));
3100
 
        }
3101
 
 
3102
 
        for (i = 0; i < num_dir_acls; i++) {
3103
 
                uint32 uorg;
3104
 
                fstring permstring;
3105
 
                unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE));
3106
 
                unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+1);
3107
 
 
3108
 
                switch(tagtype) {
3109
 
                        case SMB_POSIX_ACL_USER_OBJ:
3110
 
                                d_printf("default:user::");
3111
 
                                break;
3112
 
                        case SMB_POSIX_ACL_USER:
3113
 
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3114
 
                                d_printf("default:user:%u:", uorg);
3115
 
                                break;
3116
 
                        case SMB_POSIX_ACL_GROUP_OBJ:
3117
 
                                d_printf("default:group::");
3118
 
                                break;
3119
 
                        case SMB_POSIX_ACL_GROUP:
3120
 
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3121
 
                                d_printf("default:group:%u:", uorg);
3122
 
                                break;
3123
 
                        case SMB_POSIX_ACL_MASK:
3124
 
                                d_printf("default:mask::");
3125
 
                                break;
3126
 
                        case SMB_POSIX_ACL_OTHER:
3127
 
                                d_printf("default:other::");
3128
 
                                break;
3129
 
                        default:
3130
 
                                d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
3131
 
                                        src, (unsigned int)tagtype );
3132
 
                                SAFE_FREE(retbuf);
3133
 
                                return 1;
3134
 
                }
3135
 
 
3136
 
                d_printf("%s\n", perms_to_string(permstring, perms));
3137
 
        }
3138
 
 
3139
 
        return 0;
3140
 
}
3141
 
 
3142
 
/****************************************************************************
3143
 
 UNIX stat.
3144
 
****************************************************************************/
3145
 
 
3146
 
static int cmd_stat(void)
3147
 
{
3148
 
        TALLOC_CTX *ctx = talloc_tos();
3149
 
        char *src = NULL;
3150
 
        char *name = NULL;
3151
 
        char *targetname = NULL;
3152
 
        struct cli_state *targetcli;
3153
 
        fstring mode_str;
3154
 
        SMB_STRUCT_STAT sbuf;
3155
 
        struct tm *lt;
3156
 
        time_t tmp_time;
3157
 
 
3158
 
        if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
3159
 
                d_printf("stat file\n");
3160
 
                return 1;
3161
 
        }
3162
 
        src = talloc_asprintf(ctx,
3163
 
                        "%s%s",
3164
 
                        client_get_cur_dir(),
3165
 
                        name);
3166
 
        if (!src) {
3167
 
                return 1;
3168
 
        }
3169
 
 
3170
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
3171
 
                d_printf("stat %s: %s\n", src, cli_errstr(cli));
3172
 
                return 1;
3173
 
        }
3174
 
 
3175
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3176
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
3177
 
                return 1;
3178
 
        }
3179
 
 
3180
 
        if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) {
3181
 
                d_printf("%s stat file %s\n",
3182
 
                        cli_errstr(targetcli), src);
3183
 
                return 1;
3184
 
        }
3185
 
 
3186
 
        /* Print out the stat values. */
3187
 
        d_printf("File: %s\n", src);
3188
 
        d_printf("Size: %-12.0f\tBlocks: %u\t%s\n",
3189
 
                (double)sbuf.st_ex_size,
3190
 
                (unsigned int)sbuf.st_ex_blocks,
3191
 
                filetype_to_str(sbuf.st_ex_mode));
3192
 
 
3193
 
#if defined(S_ISCHR) && defined(S_ISBLK)
3194
 
        if (S_ISCHR(sbuf.st_ex_mode) || S_ISBLK(sbuf.st_ex_mode)) {
3195
 
                d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n",
3196
 
                        (double)sbuf.st_ex_ino,
3197
 
                        (unsigned int)sbuf.st_ex_nlink,
3198
 
                        unix_dev_major(sbuf.st_ex_rdev),
3199
 
                        unix_dev_minor(sbuf.st_ex_rdev));
3200
 
        } else
3201
 
#endif
3202
 
                d_printf("Inode: %.0f\tLinks: %u\n",
3203
 
                        (double)sbuf.st_ex_ino,
3204
 
                        (unsigned int)sbuf.st_ex_nlink);
3205
 
 
3206
 
        d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n",
3207
 
                ((int)sbuf.st_ex_mode & 0777),
3208
 
                unix_mode_to_str(mode_str, sbuf.st_ex_mode),
3209
 
                (unsigned int)sbuf.st_ex_uid,
3210
 
                (unsigned int)sbuf.st_ex_gid);
3211
 
 
3212
 
        tmp_time = convert_timespec_to_time_t(sbuf.st_ex_atime);
3213
 
        lt = localtime(&tmp_time);
3214
 
        if (lt) {
3215
 
                strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
3216
 
        } else {
3217
 
                fstrcpy(mode_str, "unknown");
3218
 
        }
3219
 
        d_printf("Access: %s\n", mode_str);
3220
 
 
3221
 
        tmp_time = convert_timespec_to_time_t(sbuf.st_ex_mtime);
3222
 
        lt = localtime(&tmp_time);
3223
 
        if (lt) {
3224
 
                strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
3225
 
        } else {
3226
 
                fstrcpy(mode_str, "unknown");
3227
 
        }
3228
 
        d_printf("Modify: %s\n", mode_str);
3229
 
 
3230
 
        tmp_time = convert_timespec_to_time_t(sbuf.st_ex_ctime);
3231
 
        lt = localtime(&tmp_time);
3232
 
        if (lt) {
3233
 
                strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
3234
 
        } else {
3235
 
                fstrcpy(mode_str, "unknown");
3236
 
        }
3237
 
        d_printf("Change: %s\n", mode_str);
3238
 
 
3239
 
        return 0;
3240
 
}
3241
 
 
3242
 
 
3243
 
/****************************************************************************
3244
 
 UNIX chown.
3245
 
****************************************************************************/
3246
 
 
3247
 
static int cmd_chown(void)
3248
 
{
3249
 
        TALLOC_CTX *ctx = talloc_tos();
3250
 
        char *src = NULL;
3251
 
        uid_t uid;
3252
 
        gid_t gid;
3253
 
        char *buf, *buf2, *buf3;
3254
 
        struct cli_state *targetcli;
3255
 
        char *targetname = NULL;
3256
 
 
3257
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
3258
 
            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL) ||
3259
 
            !next_token_talloc(ctx, &cmd_ptr,&buf3,NULL)) {
3260
 
                d_printf("chown uid gid file\n");
3261
 
                return 1;
3262
 
        }
3263
 
 
3264
 
        uid = (uid_t)atoi(buf);
3265
 
        gid = (gid_t)atoi(buf2);
3266
 
 
3267
 
        src = talloc_asprintf(ctx,
3268
 
                        "%s%s",
3269
 
                        client_get_cur_dir(),
3270
 
                        buf3);
3271
 
        if (!src) {
3272
 
                return 1;
3273
 
        }
3274
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname) ) {
3275
 
                d_printf("chown %s: %s\n", src, cli_errstr(cli));
3276
 
                return 1;
3277
 
        }
3278
 
 
3279
 
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
3280
 
                d_printf("Server doesn't support UNIX CIFS calls.\n");
3281
 
                return 1;
3282
 
        }
3283
 
 
3284
 
        if (!NT_STATUS_IS_OK(cli_posix_chown(targetcli, targetname, uid, gid))) {
3285
 
                d_printf("%s chown file %s uid=%d, gid=%d\n",
3286
 
                        cli_errstr(targetcli), src, (int)uid, (int)gid);
3287
 
                return 1;
3288
 
        }
3289
 
 
3290
 
        return 0;
3291
 
}
3292
 
 
3293
 
/****************************************************************************
3294
 
 Rename some file.
3295
 
****************************************************************************/
3296
 
 
3297
 
static int cmd_rename(void)
3298
 
{
3299
 
        TALLOC_CTX *ctx = talloc_tos();
3300
 
        char *src, *dest;
3301
 
        char *buf, *buf2;
3302
 
        struct cli_state *targetcli;
3303
 
        char *targetsrc;
3304
 
        char *targetdest;
3305
 
 
3306
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
3307
 
            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
3308
 
                d_printf("rename <src> <dest>\n");
3309
 
                return 1;
3310
 
        }
3311
 
 
3312
 
        src = talloc_asprintf(ctx,
3313
 
                        "%s%s",
3314
 
                        client_get_cur_dir(),
3315
 
                        buf);
3316
 
        if (!src) {
3317
 
                return 1;
3318
 
        }
3319
 
 
3320
 
        dest = talloc_asprintf(ctx,
3321
 
                        "%s%s",
3322
 
                        client_get_cur_dir(),
3323
 
                        buf2);
3324
 
        if (!dest) {
3325
 
                return 1;
3326
 
        }
3327
 
 
3328
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetsrc)) {
3329
 
                d_printf("rename %s: %s\n", src, cli_errstr(cli));
3330
 
                return 1;
3331
 
        }
3332
 
 
3333
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli, &targetdest)) {
3334
 
                d_printf("rename %s: %s\n", dest, cli_errstr(cli));
3335
 
                return 1;
3336
 
        }
3337
 
 
3338
 
        if (!NT_STATUS_IS_OK(cli_rename(targetcli, targetsrc, targetdest))) {
3339
 
                d_printf("%s renaming files %s -> %s \n",
3340
 
                        cli_errstr(targetcli),
3341
 
                        targetsrc,
3342
 
                        targetdest);
3343
 
                return 1;
3344
 
        }
3345
 
 
3346
 
        return 0;
3347
 
}
3348
 
 
3349
 
/****************************************************************************
3350
 
 Print the volume name.
3351
 
****************************************************************************/
3352
 
 
3353
 
static int cmd_volume(void)
3354
 
{
3355
 
        fstring volname;
3356
 
        uint32 serial_num;
3357
 
        time_t create_date;
3358
 
 
3359
 
        if (!cli_get_fs_volume_info(cli, volname, &serial_num, &create_date)) {
3360
 
                d_printf("Errr %s getting volume info\n",cli_errstr(cli));
3361
 
                return 1;
3362
 
        }
3363
 
 
3364
 
        d_printf("Volume: |%s| serial number 0x%x\n",
3365
 
                        volname, (unsigned int)serial_num);
3366
 
        return 0;
3367
 
}
3368
 
 
3369
 
/****************************************************************************
3370
 
 Hard link files using the NT call.
3371
 
****************************************************************************/
3372
 
 
3373
 
static int cmd_hardlink(void)
3374
 
{
3375
 
        TALLOC_CTX *ctx = talloc_tos();
3376
 
        char *src, *dest;
3377
 
        char *buf, *buf2;
3378
 
        struct cli_state *targetcli;
3379
 
        char *targetname;
3380
 
 
3381
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
3382
 
            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
3383
 
                d_printf("hardlink <src> <dest>\n");
3384
 
                return 1;
3385
 
        }
3386
 
 
3387
 
        src = talloc_asprintf(ctx,
3388
 
                        "%s%s",
3389
 
                        client_get_cur_dir(),
3390
 
                        buf);
3391
 
        if (!src) {
3392
 
                return 1;
3393
 
        }
3394
 
 
3395
 
        dest = talloc_asprintf(ctx,
3396
 
                        "%s%s",
3397
 
                        client_get_cur_dir(),
3398
 
                        buf2);
3399
 
        if (!dest) {
3400
 
                return 1;
3401
 
        }
3402
 
 
3403
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
3404
 
                d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
3405
 
                return 1;
3406
 
        }
3407
 
 
3408
 
        if (!NT_STATUS_IS_OK(cli_nt_hardlink(targetcli, targetname, dest))) {
3409
 
                d_printf("%s doing an NT hard link of files\n",cli_errstr(targetcli));
3410
 
                return 1;
3411
 
        }
3412
 
 
3413
 
        return 0;
3414
 
}
3415
 
 
3416
 
/****************************************************************************
3417
 
 Toggle the prompt flag.
3418
 
****************************************************************************/
3419
 
 
3420
 
static int cmd_prompt(void)
3421
 
{
3422
 
        prompt = !prompt;
3423
 
        DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
3424
 
        return 1;
3425
 
}
3426
 
 
3427
 
/****************************************************************************
3428
 
 Set the newer than time.
3429
 
****************************************************************************/
3430
 
 
3431
 
static int cmd_newer(void)
3432
 
{
3433
 
        TALLOC_CTX *ctx = talloc_tos();
3434
 
        char *buf;
3435
 
        bool ok;
3436
 
        SMB_STRUCT_STAT sbuf;
3437
 
 
3438
 
        ok = next_token_talloc(ctx, &cmd_ptr,&buf,NULL);
3439
 
        if (ok && (sys_stat(buf, &sbuf, false) == 0)) {
3440
 
                newer_than = convert_timespec_to_time_t(sbuf.st_ex_mtime);
3441
 
                DEBUG(1,("Getting files newer than %s",
3442
 
                         time_to_asc(newer_than)));
3443
 
        } else {
3444
 
                newer_than = 0;
3445
 
        }
3446
 
 
3447
 
        if (ok && newer_than == 0) {
3448
 
                d_printf("Error setting newer-than time\n");
3449
 
                return 1;
3450
 
        }
3451
 
 
3452
 
        return 0;
3453
 
}
3454
 
 
3455
 
/****************************************************************************
3456
 
 Set the archive level.
3457
 
****************************************************************************/
3458
 
 
3459
 
static int cmd_archive(void)
3460
 
{
3461
 
        TALLOC_CTX *ctx = talloc_tos();
3462
 
        char *buf;
3463
 
 
3464
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3465
 
                archive_level = atoi(buf);
3466
 
        } else {
3467
 
                d_printf("Archive level is %d\n",archive_level);
3468
 
        }
3469
 
 
3470
 
        return 0;
3471
 
}
3472
 
 
3473
 
/****************************************************************************
3474
 
 Toggle the lowercaseflag.
3475
 
****************************************************************************/
3476
 
 
3477
 
static int cmd_lowercase(void)
3478
 
{
3479
 
        lowercase = !lowercase;
3480
 
        DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
3481
 
        return 0;
3482
 
}
3483
 
 
3484
 
/****************************************************************************
3485
 
 Toggle the case sensitive flag.
3486
 
****************************************************************************/
3487
 
 
3488
 
static int cmd_setcase(void)
3489
 
{
3490
 
        bool orig_case_sensitive = cli_set_case_sensitive(cli, false);
3491
 
 
3492
 
        cli_set_case_sensitive(cli, !orig_case_sensitive);
3493
 
        DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
3494
 
                "on":"off"));
3495
 
        return 0;
3496
 
}
3497
 
 
3498
 
/****************************************************************************
3499
 
 Toggle the showacls flag.
3500
 
****************************************************************************/
3501
 
 
3502
 
static int cmd_showacls(void)
3503
 
{
3504
 
        showacls = !showacls;
3505
 
        DEBUG(2,("showacls is now %s\n",showacls?"on":"off"));
3506
 
        return 0;
3507
 
}
3508
 
 
3509
 
 
3510
 
/****************************************************************************
3511
 
 Toggle the recurse flag.
3512
 
****************************************************************************/
3513
 
 
3514
 
static int cmd_recurse(void)
3515
 
{
3516
 
        recurse = !recurse;
3517
 
        DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
3518
 
        return 0;
3519
 
}
3520
 
 
3521
 
/****************************************************************************
3522
 
 Toggle the translate flag.
3523
 
****************************************************************************/
3524
 
 
3525
 
static int cmd_translate(void)
3526
 
{
3527
 
        translation = !translation;
3528
 
        DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
3529
 
                 translation?"on":"off"));
3530
 
        return 0;
3531
 
}
3532
 
 
3533
 
/****************************************************************************
3534
 
 Do the lcd command.
3535
 
 ****************************************************************************/
3536
 
 
3537
 
static int cmd_lcd(void)
3538
 
{
3539
 
        TALLOC_CTX *ctx = talloc_tos();
3540
 
        char *buf;
3541
 
        char *d;
3542
 
 
3543
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3544
 
                if (chdir(buf) == -1) {
3545
 
                        d_printf("chdir to %s failed (%s)\n",
3546
 
                                buf, strerror(errno));
3547
 
                }
3548
 
        }
3549
 
        d = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
3550
 
        if (!d) {
3551
 
                return 1;
3552
 
        }
3553
 
        DEBUG(2,("the local directory is now %s\n",sys_getwd(d)));
3554
 
        return 0;
3555
 
}
3556
 
 
3557
 
/****************************************************************************
3558
 
 Get a file restarting at end of local file.
3559
 
 ****************************************************************************/
3560
 
 
3561
 
static int cmd_reget(void)
3562
 
{
3563
 
        TALLOC_CTX *ctx = talloc_tos();
3564
 
        char *local_name = NULL;
3565
 
        char *remote_name = NULL;
3566
 
        char *fname = NULL;
3567
 
        char *p = NULL;
3568
 
 
3569
 
        remote_name = talloc_strdup(ctx, client_get_cur_dir());
3570
 
        if (!remote_name) {
3571
 
                return 1;
3572
 
        }
3573
 
 
3574
 
        if (!next_token_talloc(ctx, &cmd_ptr, &fname, NULL)) {
3575
 
                d_printf("reget <filename>\n");
3576
 
                return 1;
3577
 
        }
3578
 
        remote_name = talloc_asprintf_append(remote_name, "%s", fname);
3579
 
        if (!remote_name) {
3580
 
                return 1;
3581
 
        }
3582
 
        remote_name = clean_name(ctx,remote_name);
3583
 
        if (!remote_name) {
3584
 
                return 1;
3585
 
        }
3586
 
 
3587
 
        local_name = fname;
3588
 
        next_token_talloc(ctx, &cmd_ptr, &p, NULL);
3589
 
        if (p) {
3590
 
                local_name = p;
3591
 
        }
3592
 
 
3593
 
        return do_get(remote_name, local_name, true);
3594
 
}
3595
 
 
3596
 
/****************************************************************************
3597
 
 Put a file restarting at end of local file.
3598
 
 ****************************************************************************/
3599
 
 
3600
 
static int cmd_reput(void)
3601
 
{
3602
 
        TALLOC_CTX *ctx = talloc_tos();
3603
 
        char *local_name = NULL;
3604
 
        char *remote_name = NULL;
3605
 
        char *buf;
3606
 
        SMB_STRUCT_STAT st;
3607
 
 
3608
 
        remote_name = talloc_strdup(ctx, client_get_cur_dir());
3609
 
        if (!remote_name) {
3610
 
                return 1;
3611
 
        }
3612
 
 
3613
 
        if (!next_token_talloc(ctx, &cmd_ptr, &local_name, NULL)) {
3614
 
                d_printf("reput <filename>\n");
3615
 
                return 1;
3616
 
        }
3617
 
 
3618
 
        if (!file_exist_stat(local_name, &st, false)) {
3619
 
                d_printf("%s does not exist\n", local_name);
3620
 
                return 1;
3621
 
        }
3622
 
 
3623
 
        if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
3624
 
                remote_name = talloc_asprintf_append(remote_name,
3625
 
                                                "%s", buf);
3626
 
        } else {
3627
 
                remote_name = talloc_asprintf_append(remote_name,
3628
 
                                                "%s", local_name);
3629
 
        }
3630
 
        if (!remote_name) {
3631
 
                return 1;
3632
 
        }
3633
 
 
3634
 
        remote_name = clean_name(ctx, remote_name);
3635
 
        if (!remote_name) {
3636
 
                return 1;
3637
 
        }
3638
 
 
3639
 
        return do_put(remote_name, local_name, true);
3640
 
}
3641
 
 
3642
 
/****************************************************************************
3643
 
 List a share name.
3644
 
 ****************************************************************************/
3645
 
 
3646
 
static void browse_fn(const char *name, uint32 m,
3647
 
                      const char *comment, void *state)
3648
 
{
3649
 
        const char *typestr = "";
3650
 
 
3651
 
        switch (m & 7) {
3652
 
        case STYPE_DISKTREE:
3653
 
                typestr = "Disk";
3654
 
                break;
3655
 
        case STYPE_PRINTQ:
3656
 
                typestr = "Printer";
3657
 
                break;
3658
 
        case STYPE_DEVICE:
3659
 
                typestr = "Device";
3660
 
                break;
3661
 
        case STYPE_IPC:
3662
 
                typestr = "IPC";
3663
 
                break;
3664
 
        }
3665
 
        /* FIXME: If the remote machine returns non-ascii characters
3666
 
           in any of these fields, they can corrupt the output.  We
3667
 
           should remove them. */
3668
 
        if (!grepable) {
3669
 
                d_printf("\t%-15s %-10.10s%s\n",
3670
 
                        name,typestr,comment);
3671
 
        } else {
3672
 
                d_printf ("%s|%s|%s\n",typestr,name,comment);
3673
 
        }
3674
 
}
3675
 
 
3676
 
static bool browse_host_rpc(bool sort)
3677
 
{
3678
 
        NTSTATUS status;
3679
 
        struct rpc_pipe_client *pipe_hnd = NULL;
3680
 
        TALLOC_CTX *frame = talloc_stackframe();
3681
 
        WERROR werr;
3682
 
        struct srvsvc_NetShareInfoCtr info_ctr;
3683
 
        struct srvsvc_NetShareCtr1 ctr1;
3684
 
        uint32_t resume_handle = 0;
3685
 
        uint32_t total_entries = 0;
3686
 
        int i;
3687
 
 
3688
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
3689
 
                                          &pipe_hnd);
3690
 
 
3691
 
        if (!NT_STATUS_IS_OK(status)) {
3692
 
                DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
3693
 
                           nt_errstr(status)));
3694
 
                TALLOC_FREE(frame);
3695
 
                return false;
3696
 
        }
3697
 
 
3698
 
        ZERO_STRUCT(info_ctr);
3699
 
        ZERO_STRUCT(ctr1);
3700
 
 
3701
 
        info_ctr.level = 1;
3702
 
        info_ctr.ctr.ctr1 = &ctr1;
3703
 
 
3704
 
        status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, frame,
3705
 
                                              pipe_hnd->desthost,
3706
 
                                              &info_ctr,
3707
 
                                              0xffffffff,
3708
 
                                              &total_entries,
3709
 
                                              &resume_handle,
3710
 
                                              &werr);
3711
 
 
3712
 
        if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
3713
 
                TALLOC_FREE(pipe_hnd);
3714
 
                TALLOC_FREE(frame);
3715
 
                return false;
3716
 
        }
3717
 
 
3718
 
        for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
3719
 
                struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
3720
 
                browse_fn(info.name, info.type, info.comment, NULL);
3721
 
        }
3722
 
 
3723
 
        TALLOC_FREE(pipe_hnd);
3724
 
        TALLOC_FREE(frame);
3725
 
        return true;
3726
 
}
3727
 
 
3728
 
/****************************************************************************
3729
 
 Try and browse available connections on a host.
3730
 
****************************************************************************/
3731
 
 
3732
 
static bool browse_host(bool sort)
3733
 
{
3734
 
        int ret;
3735
 
        if (!grepable) {
3736
 
                d_printf("\n\tSharename       Type      Comment\n");
3737
 
                d_printf("\t---------       ----      -------\n");
3738
 
        }
3739
 
 
3740
 
        if (browse_host_rpc(sort)) {
3741
 
                return true;
3742
 
        }
3743
 
 
3744
 
        if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1)
3745
 
                d_printf("Error returning browse list: %s\n", cli_errstr(cli));
3746
 
 
3747
 
        return (ret != -1);
3748
 
}
3749
 
 
3750
 
/****************************************************************************
3751
 
 List a server name.
3752
 
****************************************************************************/
3753
 
 
3754
 
static void server_fn(const char *name, uint32 m,
3755
 
                      const char *comment, void *state)
3756
 
{
3757
 
 
3758
 
        if (!grepable){
3759
 
                d_printf("\t%-16s     %s\n", name, comment);
3760
 
        } else {
3761
 
                d_printf("%s|%s|%s\n",(char *)state, name, comment);
3762
 
        }
3763
 
}
3764
 
 
3765
 
/****************************************************************************
3766
 
 Try and browse available connections on a host.
3767
 
****************************************************************************/
3768
 
 
3769
 
static bool list_servers(const char *wk_grp)
3770
 
{
3771
 
        fstring state;
3772
 
 
3773
 
        if (!cli->server_domain)
3774
 
                return false;
3775
 
 
3776
 
        if (!grepable) {
3777
 
                d_printf("\n\tServer               Comment\n");
3778
 
                d_printf("\t---------            -------\n");
3779
 
        };
3780
 
        fstrcpy( state, "Server" );
3781
 
        cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn,
3782
 
                          state);
3783
 
 
3784
 
        if (!grepable) {
3785
 
                d_printf("\n\tWorkgroup            Master\n");
3786
 
                d_printf("\t---------            -------\n");
3787
 
        };
3788
 
 
3789
 
        fstrcpy( state, "Workgroup" );
3790
 
        cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
3791
 
                          server_fn, state);
3792
 
        return true;
3793
 
}
3794
 
 
3795
 
/****************************************************************************
3796
 
 Print or set current VUID
3797
 
****************************************************************************/
3798
 
 
3799
 
static int cmd_vuid(void)
3800
 
{
3801
 
        TALLOC_CTX *ctx = talloc_tos();
3802
 
        char *buf;
3803
 
 
3804
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3805
 
                d_printf("Current VUID is %d\n", cli->vuid);
3806
 
                return 0;
3807
 
        }
3808
 
 
3809
 
        cli->vuid = atoi(buf);
3810
 
        return 0;
3811
 
}
3812
 
 
3813
 
/****************************************************************************
3814
 
 Setup a new VUID, by issuing a session setup
3815
 
****************************************************************************/
3816
 
 
3817
 
static int cmd_logon(void)
3818
 
{
3819
 
        TALLOC_CTX *ctx = talloc_tos();
3820
 
        char *l_username, *l_password;
3821
 
 
3822
 
        if (!next_token_talloc(ctx, &cmd_ptr,&l_username,NULL)) {
3823
 
                d_printf("logon <username> [<password>]\n");
3824
 
                return 0;
3825
 
        }
3826
 
 
3827
 
        if (!next_token_talloc(ctx, &cmd_ptr,&l_password,NULL)) {
3828
 
                char *pass = getpass("Password: ");
3829
 
                if (pass) {
3830
 
                        l_password = talloc_strdup(ctx,pass);
3831
 
                }
3832
 
        }
3833
 
        if (!l_password) {
3834
 
                return 1;
3835
 
        }
3836
 
 
3837
 
        if (!NT_STATUS_IS_OK(cli_session_setup(cli, l_username,
3838
 
                                               l_password, strlen(l_password),
3839
 
                                               l_password, strlen(l_password),
3840
 
                                               lp_workgroup()))) {
3841
 
                d_printf("session setup failed: %s\n", cli_errstr(cli));
3842
 
                return -1;
3843
 
        }
3844
 
 
3845
 
        d_printf("Current VUID is %d\n", cli->vuid);
3846
 
        return 0;
3847
 
}
3848
 
 
3849
 
 
3850
 
/****************************************************************************
3851
 
 list active connections
3852
 
****************************************************************************/
3853
 
 
3854
 
static int cmd_list_connect(void)
3855
 
{
3856
 
        cli_cm_display(cli);
3857
 
        return 0;
3858
 
}
3859
 
 
3860
 
/****************************************************************************
3861
 
 display the current active client connection
3862
 
****************************************************************************/
3863
 
 
3864
 
static int cmd_show_connect( void )
3865
 
{
3866
 
        TALLOC_CTX *ctx = talloc_tos();
3867
 
        struct cli_state *targetcli;
3868
 
        char *targetpath;
3869
 
 
3870
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(),
3871
 
                                &targetcli, &targetpath ) ) {
3872
 
                d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
3873
 
                return 1;
3874
 
        }
3875
 
 
3876
 
        d_printf("//%s/%s\n", targetcli->desthost, targetcli->share);
3877
 
        return 0;
3878
 
}
3879
 
 
3880
 
/****************************************************************************
3881
 
 iosize command
3882
 
***************************************************************************/
3883
 
 
3884
 
int cmd_iosize(void)
3885
 
{
3886
 
        TALLOC_CTX *ctx = talloc_tos();
3887
 
        char *buf;
3888
 
        int iosize;
3889
 
 
3890
 
        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
3891
 
                if (!smb_encrypt) {
3892
 
                        d_printf("iosize <n> or iosize 0x<n>. "
3893
 
                                "Minimum is 16384 (0x4000), "
3894
 
                                "max is 16776960 (0xFFFF00)\n");
3895
 
                } else {
3896
 
                        d_printf("iosize <n> or iosize 0x<n>. "
3897
 
                                "(Encrypted connection) ,"
3898
 
                                "Minimum is 16384 (0x4000), "
3899
 
                                "max is 130048 (0x1FC00)\n");
3900
 
                }
3901
 
                return 1;
3902
 
        }
3903
 
 
3904
 
        iosize = strtol(buf,NULL,0);
3905
 
        if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
3906
 
                d_printf("iosize out of range for encrypted "
3907
 
                        "connection (min = 16384 (0x4000), "
3908
 
                        "max = 130048 (0x1FC00)");
3909
 
                return 1;
3910
 
        } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
3911
 
                d_printf("iosize out of range (min = 16384 (0x4000), "
3912
 
                        "max = 16776960 (0xFFFF00)");
3913
 
                return 1;
3914
 
        }
3915
 
 
3916
 
        io_bufsize = iosize;
3917
 
        d_printf("iosize is now %d\n", io_bufsize);
3918
 
        return 0;
3919
 
}
3920
 
 
3921
 
 
3922
 
/* Some constants for completing filename arguments */
3923
 
 
3924
 
#define COMPL_NONE        0          /* No completions */
3925
 
#define COMPL_REMOTE      1          /* Complete remote filename */
3926
 
#define COMPL_LOCAL       2          /* Complete local filename */
3927
 
 
3928
 
/* This defines the commands supported by this client.
3929
 
 * NOTE: The "!" must be the last one in the list because it's fn pointer
3930
 
 *       field is NULL, and NULL in that field is used in process_tok()
3931
 
 *       (below) to indicate the end of the list.  crh
3932
 
 */
3933
 
static struct {
3934
 
        const char *name;
3935
 
        int (*fn)(void);
3936
 
        const char *description;
3937
 
        char compl_args[2];      /* Completion argument info */
3938
 
} commands[] = {
3939
 
  {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3940
 
  {"allinfo",cmd_allinfo,"<file> show all available info",
3941
 
   {COMPL_NONE,COMPL_NONE}},
3942
 
  {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
3943
 
  {"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}},
3944
 
  {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
3945
 
  {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
3946
 
  {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
3947
 
  {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
3948
 
  {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
3949
 
  {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
3950
 
  {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_REMOTE}},
3951
 
  {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3952
 
  {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3953
 
  {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3954
 
  {"echo",cmd_echo,"ping the server",{COMPL_NONE,COMPL_NONE}},
3955
 
  {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3956
 
  {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
3957
 
  {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_LOCAL}},
3958
 
  {"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
3959
 
  {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
3960
 
  {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
3961
 
  {"iosize",cmd_iosize,"iosize <number> (default 64512)",{COMPL_NONE,COMPL_NONE}},
3962
 
  {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
3963
 
  {"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
3964
 
  {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
3965
 
  {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},  
3966
 
  {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3967
 
  {"l",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
3968
 
  {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
3969
 
  {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3970
 
  {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
3971
 
  {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
3972
 
  {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},  
3973
 
  {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
3974
 
  {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
3975
 
  {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
3976
 
  {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
3977
 
  {"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
3978
 
  {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
3979
 
  {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
3980
 
  {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
3981
 
  {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
3982
 
  {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
3983
 
  {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},  
3984
 
  {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
3985
 
  {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
3986
 
  {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3987
 
  {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
3988
 
  {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
3989
 
  {"readlink",cmd_readlink,"filename Do a UNIX extensions readlink call on a symlink",{COMPL_REMOTE,COMPL_REMOTE}},
3990
 
  {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3991
 
  {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
3992
 
  {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
3993
 
  {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
3994
 
  {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
3995
 
  {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
3996
 
  {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
3997
 
  {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}},  
3998
 
  {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
3999
 
  {"stat",cmd_stat,"filename Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_REMOTE}},
4000
 
  {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
4001
 
  {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
4002
 
  {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
4003
 
  {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
4004
 
  {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
4005
 
  {"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
4006
 
  {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
4007
 
  {"wdel",cmd_wdel,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
4008
 
  {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
4009
 
  {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
4010
 
  {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
4011
 
  {"..",cmd_cd_oneup,"change the remote directory (up one level)",{COMPL_REMOTE,COMPL_NONE}},
4012
 
 
4013
 
  /* Yes, this must be here, see crh's comment above. */
4014
 
  {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
4015
 
  {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
4016
 
};
4017
 
 
4018
 
/*******************************************************************
4019
 
 Lookup a command string in the list of commands, including
4020
 
 abbreviations.
4021
 
******************************************************************/
4022
 
 
4023
 
static int process_tok(char *tok)
4024
 
{
4025
 
        int i = 0, matches = 0;
4026
 
        int cmd=0;
4027
 
        int tok_len = strlen(tok);
4028
 
 
4029
 
        while (commands[i].fn != NULL) {
4030
 
                if (strequal(commands[i].name,tok)) {
4031
 
                        matches = 1;
4032
 
                        cmd = i;
4033
 
                        break;
4034
 
                } else if (strnequal(commands[i].name, tok, tok_len)) {
4035
 
                        matches++;
4036
 
                        cmd = i;
4037
 
                }
4038
 
                i++;
4039
 
        }
4040
 
 
4041
 
        if (matches == 0)
4042
 
                return(-1);
4043
 
        else if (matches == 1)
4044
 
                return(cmd);
4045
 
        else
4046
 
                return(-2);
4047
 
}
4048
 
 
4049
 
/****************************************************************************
4050
 
 Help.
4051
 
****************************************************************************/
4052
 
 
4053
 
static int cmd_help(void)
4054
 
{
4055
 
        TALLOC_CTX *ctx = talloc_tos();
4056
 
        int i=0,j;
4057
 
        char *buf;
4058
 
 
4059
 
        if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
4060
 
                if ((i = process_tok(buf)) >= 0)
4061
 
                        d_printf("HELP %s:\n\t%s\n\n",
4062
 
                                commands[i].name,commands[i].description);
4063
 
        } else {
4064
 
                while (commands[i].description) {
4065
 
                        for (j=0; commands[i].description && (j<5); j++) {
4066
 
                                d_printf("%-15s",commands[i].name);
4067
 
                                i++;
4068
 
                        }
4069
 
                        d_printf("\n");
4070
 
                }
4071
 
        }
4072
 
        return 0;
4073
 
}
4074
 
 
4075
 
/****************************************************************************
4076
 
 Process a -c command string.
4077
 
****************************************************************************/
4078
 
 
4079
 
static int process_command_string(const char *cmd_in)
4080
 
{
4081
 
        TALLOC_CTX *ctx = talloc_tos();
4082
 
        char *cmd = talloc_strdup(ctx, cmd_in);
4083
 
        int rc = 0;
4084
 
 
4085
 
        if (!cmd) {
4086
 
                return 1;
4087
 
        }
4088
 
        /* establish the connection if not already */
4089
 
 
4090
 
        if (!cli) {
4091
 
                cli = cli_cm_open(talloc_tos(), NULL,
4092
 
                                have_ip ? dest_ss_str : desthost,
4093
 
                                service, auth_info,
4094
 
                                true, smb_encrypt,
4095
 
                                max_protocol, port, name_type);
4096
 
                if (!cli) {
4097
 
                        return 1;
4098
 
                }
4099
 
        }
4100
 
 
4101
 
        while (cmd[0] != '\0')    {
4102
 
                char *line;
4103
 
                char *p;
4104
 
                char *tok;
4105
 
                int i;
4106
 
 
4107
 
                if ((p = strchr_m(cmd, ';')) == 0) {
4108
 
                        line = cmd;
4109
 
                        cmd += strlen(cmd);
4110
 
                } else {
4111
 
                        *p = '\0';
4112
 
                        line = cmd;
4113
 
                        cmd = p + 1;
4114
 
                }
4115
 
 
4116
 
                /* and get the first part of the command */
4117
 
                cmd_ptr = line;
4118
 
                if (!next_token_talloc(ctx, &cmd_ptr,&tok,NULL)) {
4119
 
                        continue;
4120
 
                }
4121
 
 
4122
 
                if ((i = process_tok(tok)) >= 0) {
4123
 
                        rc = commands[i].fn();
4124
 
                } else if (i == -2) {
4125
 
                        d_printf("%s: command abbreviation ambiguous\n",tok);
4126
 
                } else {
4127
 
                        d_printf("%s: command not found\n",tok);
4128
 
                }
4129
 
        }
4130
 
 
4131
 
        return rc;
4132
 
}
4133
 
 
4134
 
#define MAX_COMPLETIONS 100
4135
 
 
4136
 
typedef struct {
4137
 
        char *dirmask;
4138
 
        char **matches;
4139
 
        int count, samelen;
4140
 
        const char *text;
4141
 
        int len;
4142
 
} completion_remote_t;
4143
 
 
4144
 
static void completion_remote_filter(const char *mnt,
4145
 
                                file_info *f,
4146
 
                                const char *mask,
4147
 
                                void *state)
4148
 
{
4149
 
        completion_remote_t *info = (completion_remote_t *)state;
4150
 
 
4151
 
        if ((info->count < MAX_COMPLETIONS - 1) &&
4152
 
                        (strncmp(info->text, f->name, info->len) == 0) &&
4153
 
                        (strcmp(f->name, ".") != 0) &&
4154
 
                        (strcmp(f->name, "..") != 0)) {
4155
 
                if ((info->dirmask[0] == 0) && !(f->mode & aDIR))
4156
 
                        info->matches[info->count] = SMB_STRDUP(f->name);
4157
 
                else {
4158
 
                        TALLOC_CTX *ctx = talloc_stackframe();
4159
 
                        char *tmp;
4160
 
 
4161
 
                        tmp = talloc_strdup(ctx,info->dirmask);
4162
 
                        if (!tmp) {
4163
 
                                TALLOC_FREE(ctx);
4164
 
                                return;
4165
 
                        }
4166
 
                        tmp = talloc_asprintf_append(tmp, "%s", f->name);
4167
 
                        if (!tmp) {
4168
 
                                TALLOC_FREE(ctx);
4169
 
                                return;
4170
 
                        }
4171
 
                        if (f->mode & aDIR) {
4172
 
                                tmp = talloc_asprintf_append(tmp, "%s", CLI_DIRSEP_STR);
4173
 
                        }
4174
 
                        if (!tmp) {
4175
 
                                TALLOC_FREE(ctx);
4176
 
                                return;
4177
 
                        }
4178
 
                        info->matches[info->count] = SMB_STRDUP(tmp);
4179
 
                        TALLOC_FREE(ctx);
4180
 
                }
4181
 
                if (info->matches[info->count] == NULL) {
4182
 
                        return;
4183
 
                }
4184
 
                if (f->mode & aDIR) {
4185
 
                        smb_readline_ca_char(0);
4186
 
                }
4187
 
                if (info->count == 1) {
4188
 
                        info->samelen = strlen(info->matches[info->count]);
4189
 
                } else {
4190
 
                        while (strncmp(info->matches[info->count],
4191
 
                                                info->matches[info->count-1],
4192
 
                                                info->samelen) != 0) {
4193
 
                                info->samelen--;
4194
 
                        }
4195
 
                }
4196
 
                info->count++;
4197
 
        }
4198
 
}
4199
 
 
4200
 
static char **remote_completion(const char *text, int len)
4201
 
{
4202
 
        TALLOC_CTX *ctx = talloc_stackframe();
4203
 
        char *dirmask = NULL;
4204
 
        char *targetpath = NULL;
4205
 
        struct cli_state *targetcli = NULL;
4206
 
        int i;
4207
 
        completion_remote_t info = { NULL, NULL, 1, 0, NULL, 0 };
4208
 
 
4209
 
        /* can't have non-static intialisation on Sun CC, so do it
4210
 
           at run time here */
4211
 
        info.samelen = len;
4212
 
        info.text = text;
4213
 
        info.len = len;
4214
 
 
4215
 
        info.matches = SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS);
4216
 
        if (!info.matches) {
4217
 
                TALLOC_FREE(ctx);
4218
 
                return NULL;
4219
 
        }
4220
 
 
4221
 
        /*
4222
 
         * We're leaving matches[0] free to fill it later with the text to
4223
 
         * display: Either the one single match or the longest common subset
4224
 
         * of the matches.
4225
 
         */
4226
 
        info.matches[0] = NULL;
4227
 
        info.count = 1;
4228
 
 
4229
 
        for (i = len-1; i >= 0; i--) {
4230
 
                if ((text[i] == '/') || (text[i] == CLI_DIRSEP_CHAR)) {
4231
 
                        break;
4232
 
                }
4233
 
        }
4234
 
 
4235
 
        info.text = text+i+1;
4236
 
        info.samelen = info.len = len-i-1;
4237
 
 
4238
 
        if (i > 0) {
4239
 
                info.dirmask = SMB_MALLOC_ARRAY(char, i+2);
4240
 
                if (!info.dirmask) {
4241
 
                        goto cleanup;
4242
 
                }
4243
 
                strncpy(info.dirmask, text, i+1);
4244
 
                info.dirmask[i+1] = 0;
4245
 
                dirmask = talloc_asprintf(ctx,
4246
 
                                        "%s%*s*",
4247
 
                                        client_get_cur_dir(),
4248
 
                                        i-1,
4249
 
                                        text);
4250
 
        } else {
4251
 
                info.dirmask = SMB_STRDUP("");
4252
 
                if (!info.dirmask) {
4253
 
                        goto cleanup;
4254
 
                }
4255
 
                dirmask = talloc_asprintf(ctx,
4256
 
                                        "%s*",
4257
 
                                        client_get_cur_dir());
4258
 
        }
4259
 
        if (!dirmask) {
4260
 
                goto cleanup;
4261
 
        }
4262
 
 
4263
 
        if (!cli_resolve_path(ctx, "", auth_info, cli, dirmask, &targetcli, &targetpath)) {
4264
 
                goto cleanup;
4265
 
        }
4266
 
        if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN,
4267
 
                                completion_remote_filter, (void *)&info) < 0) {
4268
 
                goto cleanup;
4269
 
        }
4270
 
 
4271
 
        if (info.count == 1) {
4272
 
                /*
4273
 
                 * No matches at all, NULL indicates there is nothing
4274
 
                 */
4275
 
                SAFE_FREE(info.matches[0]);
4276
 
                SAFE_FREE(info.matches);
4277
 
                TALLOC_FREE(ctx);
4278
 
                return NULL;
4279
 
        }
4280
 
 
4281
 
        if (info.count == 2) {
4282
 
                /*
4283
 
                 * Exactly one match in matches[1], indicate this is the one
4284
 
                 * in matches[0].
4285
 
                 */
4286
 
                info.matches[0] = info.matches[1];
4287
 
                info.matches[1] = NULL;
4288
 
                info.count -= 1;
4289
 
                TALLOC_FREE(ctx);
4290
 
                return info.matches;
4291
 
        }
4292
 
 
4293
 
        /*
4294
 
         * We got more than one possible match, set the result to the maximum
4295
 
         * common subset
4296
 
         */
4297
 
 
4298
 
        info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
4299
 
        info.matches[info.count] = NULL;
4300
 
        return info.matches;
4301
 
 
4302
 
cleanup:
4303
 
        for (i = 0; i < info.count; i++) {
4304
 
                SAFE_FREE(info.matches[i]);
4305
 
        }
4306
 
        SAFE_FREE(info.matches);
4307
 
        SAFE_FREE(info.dirmask);
4308
 
        TALLOC_FREE(ctx);
4309
 
        return NULL;
4310
 
}
4311
 
 
4312
 
static char **completion_fn(const char *text, int start, int end)
4313
 
{
4314
 
        smb_readline_ca_char(' ');
4315
 
 
4316
 
        if (start) {
4317
 
                const char *buf, *sp;
4318
 
                int i;
4319
 
                char compl_type;
4320
 
 
4321
 
                buf = smb_readline_get_line_buffer();
4322
 
                if (buf == NULL)
4323
 
                        return NULL;
4324
 
 
4325
 
                sp = strchr(buf, ' ');
4326
 
                if (sp == NULL)
4327
 
                        return NULL;
4328
 
 
4329
 
                for (i = 0; commands[i].name; i++) {
4330
 
                        if ((strncmp(commands[i].name, buf, sp - buf) == 0) &&
4331
 
                            (commands[i].name[sp - buf] == 0)) {
4332
 
                                break;
4333
 
                        }
4334
 
                }
4335
 
                if (commands[i].name == NULL)
4336
 
                        return NULL;
4337
 
 
4338
 
                while (*sp == ' ')
4339
 
                        sp++;
4340
 
 
4341
 
                if (sp == (buf + start))
4342
 
                        compl_type = commands[i].compl_args[0];
4343
 
                else
4344
 
                        compl_type = commands[i].compl_args[1];
4345
 
 
4346
 
                if (compl_type == COMPL_REMOTE)
4347
 
                        return remote_completion(text, end - start);
4348
 
                else /* fall back to local filename completion */
4349
 
                        return NULL;
4350
 
        } else {
4351
 
                char **matches;
4352
 
                int i, len, samelen = 0, count=1;
4353
 
 
4354
 
                matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
4355
 
                if (!matches) {
4356
 
                        return NULL;
4357
 
                }
4358
 
                matches[0] = NULL;
4359
 
 
4360
 
                len = strlen(text);
4361
 
                for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
4362
 
                        if (strncmp(text, commands[i].name, len) == 0) {
4363
 
                                matches[count] = SMB_STRDUP(commands[i].name);
4364
 
                                if (!matches[count])
4365
 
                                        goto cleanup;
4366
 
                                if (count == 1)
4367
 
                                        samelen = strlen(matches[count]);
4368
 
                                else
4369
 
                                        while (strncmp(matches[count], matches[count-1], samelen) != 0)
4370
 
                                                samelen--;
4371
 
                                count++;
4372
 
                        }
4373
 
                }
4374
 
 
4375
 
                switch (count) {
4376
 
                case 0: /* should never happen */
4377
 
                case 1:
4378
 
                        goto cleanup;
4379
 
                case 2:
4380
 
                        matches[0] = SMB_STRDUP(matches[1]);
4381
 
                        break;
4382
 
                default:
4383
 
                        matches[0] = (char *)SMB_MALLOC(samelen+1);
4384
 
                        if (!matches[0])
4385
 
                                goto cleanup;
4386
 
                        strncpy(matches[0], matches[1], samelen);
4387
 
                        matches[0][samelen] = 0;
4388
 
                }
4389
 
                matches[count] = NULL;
4390
 
                return matches;
4391
 
 
4392
 
cleanup:
4393
 
                for (i = 0; i < count; i++)
4394
 
                        free(matches[i]);
4395
 
 
4396
 
                free(matches);
4397
 
                return NULL;
4398
 
        }
4399
 
}
4400
 
 
4401
 
static bool finished;
4402
 
 
4403
 
/****************************************************************************
4404
 
 Make sure we swallow keepalives during idle time.
4405
 
****************************************************************************/
4406
 
 
4407
 
static void readline_callback(void)
4408
 
{
4409
 
        fd_set fds;
4410
 
        struct timeval timeout;
4411
 
        static time_t last_t;
4412
 
        time_t t;
4413
 
 
4414
 
        t = time(NULL);
4415
 
 
4416
 
        if (t - last_t < 5)
4417
 
                return;
4418
 
 
4419
 
        last_t = t;
4420
 
 
4421
 
 again:
4422
 
 
4423
 
        if (cli->fd == -1)
4424
 
                return;
4425
 
 
4426
 
        FD_ZERO(&fds);
4427
 
        FD_SET(cli->fd,&fds);
4428
 
 
4429
 
        timeout.tv_sec = 0;
4430
 
        timeout.tv_usec = 0;
4431
 
        sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
4432
 
 
4433
 
        /* We deliberately use receive_smb_raw instead of
4434
 
           client_receive_smb as we want to receive
4435
 
           session keepalives and then drop them here.
4436
 
        */
4437
 
        if (FD_ISSET(cli->fd,&fds)) {
4438
 
                NTSTATUS status;
4439
 
                size_t len;
4440
 
 
4441
 
                set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
4442
 
 
4443
 
                status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, 0, 0, &len);
4444
 
 
4445
 
                if (!NT_STATUS_IS_OK(status)) {
4446
 
                        DEBUG(0, ("Read from server failed, maybe it closed "
4447
 
                                  "the connection\n"));
4448
 
 
4449
 
                        finished = true;
4450
 
                        smb_readline_done();
4451
 
                        if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
4452
 
                                set_smb_read_error(&cli->smb_rw_error,
4453
 
                                                   SMB_READ_EOF);
4454
 
                                return;
4455
 
                        }
4456
 
 
4457
 
                        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4458
 
                                set_smb_read_error(&cli->smb_rw_error,
4459
 
                                                   SMB_READ_TIMEOUT);
4460
 
                                return;
4461
 
                        }
4462
 
 
4463
 
                        set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
4464
 
                        return;
4465
 
                }
4466
 
                if(CVAL(cli->inbuf,0) != SMBkeepalive) {
4467
 
                        DEBUG(0, ("Read from server "
4468
 
                                "returned unexpected packet!\n"));
4469
 
                        return;
4470
 
                }
4471
 
 
4472
 
                goto again;
4473
 
        }
4474
 
 
4475
 
        /* Ping the server to keep the connection alive using SMBecho. */
4476
 
        {
4477
 
                NTSTATUS status;
4478
 
                unsigned char garbage[16];
4479
 
                memset(garbage, 0xf0, sizeof(garbage));
4480
 
                status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
4481
 
 
4482
 
                if (!NT_STATUS_IS_OK(status)) {
4483
 
                        DEBUG(0, ("SMBecho failed. Maybe server has closed "
4484
 
                                "the connection\n"));
4485
 
                        finished = true;
4486
 
                        smb_readline_done();
4487
 
                }
4488
 
        }
4489
 
}
4490
 
 
4491
 
/****************************************************************************
4492
 
 Process commands on stdin.
4493
 
****************************************************************************/
4494
 
 
4495
 
static int process_stdin(void)
4496
 
{
4497
 
        int rc = 0;
4498
 
 
4499
 
        while (!finished) {
4500
 
                TALLOC_CTX *frame = talloc_stackframe();
4501
 
                char *tok = NULL;
4502
 
                char *the_prompt = NULL;
4503
 
                char *line = NULL;
4504
 
                int i;
4505
 
 
4506
 
                /* display a prompt */
4507
 
                if (asprintf(&the_prompt, "smb: %s> ", client_get_cur_dir()) < 0) {
4508
 
                        TALLOC_FREE(frame);
4509
 
                        break;
4510
 
                }
4511
 
                line = smb_readline(the_prompt, readline_callback, completion_fn);
4512
 
                SAFE_FREE(the_prompt);
4513
 
                if (!line) {
4514
 
                        TALLOC_FREE(frame);
4515
 
                        break;
4516
 
                }
4517
 
 
4518
 
                /* special case - first char is ! */
4519
 
                if (*line == '!') {
4520
 
                        if (system(line + 1) == -1) {
4521
 
                                d_printf("system() command %s failed.\n",
4522
 
                                        line+1);
4523
 
                        }
4524
 
                        SAFE_FREE(line);
4525
 
                        TALLOC_FREE(frame);
4526
 
                        continue;
4527
 
                }
4528
 
 
4529
 
                /* and get the first part of the command */
4530
 
                cmd_ptr = line;
4531
 
                if (!next_token_talloc(frame, &cmd_ptr,&tok,NULL)) {
4532
 
                        TALLOC_FREE(frame);
4533
 
                        SAFE_FREE(line);
4534
 
                        continue;
4535
 
                }
4536
 
 
4537
 
                if ((i = process_tok(tok)) >= 0) {
4538
 
                        rc = commands[i].fn();
4539
 
                } else if (i == -2) {
4540
 
                        d_printf("%s: command abbreviation ambiguous\n",tok);
4541
 
                } else {
4542
 
                        d_printf("%s: command not found\n",tok);
4543
 
                }
4544
 
                SAFE_FREE(line);
4545
 
                TALLOC_FREE(frame);
4546
 
        }
4547
 
        return rc;
4548
 
}
4549
 
 
4550
 
/****************************************************************************
4551
 
 Process commands from the client.
4552
 
****************************************************************************/
4553
 
 
4554
 
static int process(const char *base_directory)
4555
 
{
4556
 
        int rc = 0;
4557
 
 
4558
 
        cli = cli_cm_open(talloc_tos(), NULL,
4559
 
                        have_ip ? dest_ss_str : desthost,
4560
 
                        service, auth_info, true, smb_encrypt,
4561
 
                        max_protocol, port, name_type);
4562
 
        if (!cli) {
4563
 
                return 1;
4564
 
        }
4565
 
 
4566
 
        if (base_directory && *base_directory) {
4567
 
                rc = do_cd(base_directory);
4568
 
                if (rc) {
4569
 
                        cli_shutdown(cli);
4570
 
                        return rc;
4571
 
                }
4572
 
        }
4573
 
 
4574
 
        if (cmdstr) {
4575
 
                rc = process_command_string(cmdstr);
4576
 
        } else {
4577
 
                process_stdin();
4578
 
        }
4579
 
 
4580
 
        cli_shutdown(cli);
4581
 
        return rc;
4582
 
}
4583
 
 
4584
 
/****************************************************************************
4585
 
 Handle a -L query.
4586
 
****************************************************************************/
4587
 
 
4588
 
static int do_host_query(const char *query_host)
4589
 
{
4590
 
        cli = cli_cm_open(talloc_tos(), NULL,
4591
 
                        query_host, "IPC$", auth_info, true, smb_encrypt,
4592
 
                        max_protocol, port, name_type);
4593
 
        if (!cli)
4594
 
                return 1;
4595
 
 
4596
 
        browse_host(true);
4597
 
 
4598
 
        /* Ensure that the host can do IPv4 */
4599
 
 
4600
 
        if (!interpret_addr(query_host)) {
4601
 
                struct sockaddr_storage ss;
4602
 
                if (interpret_string_addr(&ss, query_host, 0) &&
4603
 
                                (ss.ss_family != AF_INET)) {
4604
 
                        d_printf("%s is an IPv6 address -- no workgroup available\n",
4605
 
                                query_host);
4606
 
                        return 1;
4607
 
                }
4608
 
        }
4609
 
 
4610
 
        if (port != 139) {
4611
 
 
4612
 
                /* Workgroups simply don't make sense over anything
4613
 
                   else but port 139... */
4614
 
 
4615
 
                cli_shutdown(cli);
4616
 
                cli = cli_cm_open(talloc_tos(), NULL,
4617
 
                                query_host, "IPC$", auth_info, true, smb_encrypt,
4618
 
                                max_protocol, 139, name_type);
4619
 
        }
4620
 
 
4621
 
        if (cli == NULL) {
4622
 
                d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
4623
 
                return 1;
4624
 
        }
4625
 
 
4626
 
        list_servers(lp_workgroup());
4627
 
 
4628
 
        cli_shutdown(cli);
4629
 
 
4630
 
        return(0);
4631
 
}
4632
 
 
4633
 
/****************************************************************************
4634
 
 Handle a tar operation.
4635
 
****************************************************************************/
4636
 
 
4637
 
static int do_tar_op(const char *base_directory)
4638
 
{
4639
 
        int ret;
4640
 
 
4641
 
        /* do we already have a connection? */
4642
 
        if (!cli) {
4643
 
                cli = cli_cm_open(talloc_tos(), NULL,
4644
 
                        have_ip ? dest_ss_str : desthost,
4645
 
                        service, auth_info, true, smb_encrypt,
4646
 
                        max_protocol, port, name_type);
4647
 
                if (!cli)
4648
 
                        return 1;
4649
 
        }
4650
 
 
4651
 
        recurse=true;
4652
 
 
4653
 
        if (base_directory && *base_directory)  {
4654
 
                ret = do_cd(base_directory);
4655
 
                if (ret) {
4656
 
                        cli_shutdown(cli);
4657
 
                        return ret;
4658
 
                }
4659
 
        }
4660
 
 
4661
 
        ret=process_tar();
4662
 
 
4663
 
        cli_shutdown(cli);
4664
 
 
4665
 
        return(ret);
4666
 
}
4667
 
 
4668
 
/****************************************************************************
4669
 
 Handle a message operation.
4670
 
****************************************************************************/
4671
 
 
4672
 
static int do_message_op(struct user_auth_info *a_info)
4673
 
{
4674
 
        struct sockaddr_storage ss;
4675
 
        struct nmb_name called, calling;
4676
 
        fstring server_name;
4677
 
        char name_type_hex[10];
4678
 
        int msg_port;
4679
 
        NTSTATUS status;
4680
 
 
4681
 
        make_nmb_name(&calling, calling_name, 0x0);
4682
 
        make_nmb_name(&called , desthost, name_type);
4683
 
 
4684
 
        fstrcpy(server_name, desthost);
4685
 
        snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
4686
 
        fstrcat(server_name, name_type_hex);
4687
 
 
4688
 
        zero_sockaddr(&ss);
4689
 
        if (have_ip)
4690
 
                ss = dest_ss;
4691
 
 
4692
 
        /* we can only do messages over port 139 (to windows clients at least) */
4693
 
 
4694
 
        msg_port = port ? port : 139;
4695
 
 
4696
 
        if (!(cli=cli_initialise())) {
4697
 
                d_printf("Connection to %s failed\n", desthost);
4698
 
                return 1;
4699
 
        }
4700
 
        cli_set_port(cli, msg_port);
4701
 
 
4702
 
        status = cli_connect(cli, server_name, &ss);
4703
 
        if (!NT_STATUS_IS_OK(status)) {
4704
 
                d_printf("Connection to %s failed. Error %s\n", desthost, nt_errstr(status));
4705
 
                return 1;
4706
 
        }
4707
 
 
4708
 
        if (!cli_session_request(cli, &calling, &called)) {
4709
 
                d_printf("session request failed\n");
4710
 
                cli_shutdown(cli);
4711
 
                return 1;
4712
 
        }
4713
 
 
4714
 
        send_message(get_cmdline_auth_info_username(a_info));
4715
 
        cli_shutdown(cli);
4716
 
 
4717
 
        return 0;
4718
 
}
4719
 
 
4720
 
/****************************************************************************
4721
 
  main program
4722
 
****************************************************************************/
4723
 
 
4724
 
 int main(int argc,char *argv[])
4725
 
{
4726
 
        char *base_directory = NULL;
4727
 
        int opt;
4728
 
        char *query_host = NULL;
4729
 
        bool message = false;
4730
 
        static const char *new_name_resolve_order = NULL;
4731
 
        poptContext pc;
4732
 
        char *p;
4733
 
        int rc = 0;
4734
 
        fstring new_workgroup;
4735
 
        bool tar_opt = false;
4736
 
        bool service_opt = false;
4737
 
        struct poptOption long_options[] = {
4738
 
                POPT_AUTOHELP
4739
 
 
4740
 
                { "name-resolve", 'R', POPT_ARG_STRING, &new_name_resolve_order, 'R', "Use these name resolution services only", "NAME-RESOLVE-ORDER" },
4741
 
                { "message", 'M', POPT_ARG_STRING, NULL, 'M', "Send message", "HOST" },
4742
 
                { "ip-address", 'I', POPT_ARG_STRING, NULL, 'I', "Use this IP to connect to", "IP" },
4743
 
                { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
4744
 
                { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
4745
 
                { "max-protocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set the max protocol level", "LEVEL" },
4746
 
                { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "<c|x>IXFqgbNan" },
4747
 
                { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
4748
 
                { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, 
4749
 
                { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
4750
 
                { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
4751
 
                { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
4752
 
                { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" },
4753
 
                POPT_COMMON_SAMBA
4754
 
                POPT_COMMON_CONNECTION
4755
 
                POPT_COMMON_CREDENTIALS
4756
 
                POPT_TABLEEND
4757
 
        };
4758
 
        TALLOC_CTX *frame = talloc_stackframe();
4759
 
 
4760
 
        if (!client_set_cur_dir("\\")) {
4761
 
                exit(ENOMEM);
4762
 
        }
4763
 
 
4764
 
        /* initialize the workgroup name so we can determine whether or
4765
 
           not it was set by a command line option */
4766
 
 
4767
 
        set_global_myworkgroup( "" );
4768
 
        set_global_myname( "" );
4769
 
 
4770
 
        /* set default debug level to 1 regardless of what smb.conf sets */
4771
 
        setup_logging( "smbclient", true );
4772
 
        DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
4773
 
        if ((dbf = x_fdup(x_stderr))) {
4774
 
                x_setbuf( dbf, NULL );
4775
 
        }
4776
 
 
4777
 
        load_case_tables();
4778
 
 
4779
 
        auth_info = user_auth_info_init(frame);
4780
 
        if (auth_info == NULL) {
4781
 
                exit(1);
4782
 
        }
4783
 
        popt_common_set_auth_info(auth_info);
4784
 
 
4785
 
        /* skip argv(0) */
4786
 
        pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
4787
 
        poptSetOtherOptionHelp(pc, "service <password>");
4788
 
 
4789
 
        lp_set_in_client(true); /* Make sure that we tell lp_load we are */
4790
 
 
4791
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
4792
 
 
4793
 
                /* if the tar option has been called previouslt, now we need to eat out the leftovers */
4794
 
                /* I see no other way to keep things sane --SSS */
4795
 
                if (tar_opt == true) {
4796
 
                        while (poptPeekArg(pc)) {
4797
 
                                poptGetArg(pc);
4798
 
                        }
4799
 
                        tar_opt = false;
4800
 
                }
4801
 
 
4802
 
                /* if the service has not yet been specified lets see if it is available in the popt stack */
4803
 
                if (!service_opt && poptPeekArg(pc)) {
4804
 
                        service = talloc_strdup(frame, poptGetArg(pc));
4805
 
                        if (!service) {
4806
 
                                exit(ENOMEM);
4807
 
                        }
4808
 
                        service_opt = true;
4809
 
                }
4810
 
 
4811
 
                /* if the service has already been retrieved then check if we have also a password */
4812
 
                if (service_opt
4813
 
                    && (!get_cmdline_auth_info_got_pass(auth_info))
4814
 
                    && poptPeekArg(pc)) {
4815
 
                        set_cmdline_auth_info_password(auth_info,
4816
 
                                                       poptGetArg(pc));
4817
 
                }
4818
 
 
4819
 
                switch (opt) {
4820
 
                case 'M':
4821
 
                        /* Messages are sent to NetBIOS name type 0x3
4822
 
                         * (Messenger Service).  Make sure we default
4823
 
                         * to port 139 instead of port 445. srl,crh
4824
 
                         */
4825
 
                        name_type = 0x03;
4826
 
                        desthost = talloc_strdup(frame,poptGetOptArg(pc));
4827
 
                        if (!desthost) {
4828
 
                                exit(ENOMEM);
4829
 
                        }
4830
 
                        if( !port )
4831
 
                                port = 139;
4832
 
                        message = true;
4833
 
                        break;
4834
 
                case 'I':
4835
 
                        {
4836
 
                                if (!interpret_string_addr(&dest_ss, poptGetOptArg(pc), 0)) {
4837
 
                                        exit(1);
4838
 
                                }
4839
 
                                have_ip = true;
4840
 
                                print_sockaddr(dest_ss_str, sizeof(dest_ss_str), &dest_ss);
4841
 
                        }
4842
 
                        break;
4843
 
                case 'E':
4844
 
                        if (dbf) {
4845
 
                                x_fclose(dbf);
4846
 
                        }
4847
 
                        dbf = x_stderr;
4848
 
                        display_set_stderr();
4849
 
                        break;
4850
 
 
4851
 
                case 'L':
4852
 
                        query_host = talloc_strdup(frame, poptGetOptArg(pc));
4853
 
                        if (!query_host) {
4854
 
                                exit(ENOMEM);
4855
 
                        }
4856
 
                        break;
4857
 
                case 'm':
4858
 
                        max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol);
4859
 
                        break;
4860
 
                case 'T':
4861
 
                        /* We must use old option processing for this. Find the
4862
 
                         * position of the -T option in the raw argv[]. */
4863
 
                        {
4864
 
                                int i;
4865
 
                                for (i = 1; i < argc; i++) {
4866
 
                                        if (strncmp("-T", argv[i],2)==0)
4867
 
                                                break;
4868
 
                                }
4869
 
                                i++;
4870
 
                                if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
4871
 
                                        poptPrintUsage(pc, stderr, 0);
4872
 
                                        exit(1);
4873
 
                                }
4874
 
                        }
4875
 
                        /* this must be the last option, mark we have parsed it so that we know we have */
4876
 
                        tar_opt = true;
4877
 
                        break;
4878
 
                case 'D':
4879
 
                        base_directory = talloc_strdup(frame, poptGetOptArg(pc));
4880
 
                        if (!base_directory) {
4881
 
                                exit(ENOMEM);
4882
 
                        }
4883
 
                        break;
4884
 
                case 'g':
4885
 
                        grepable=true;
4886
 
                        break;
4887
 
                case 'e':
4888
 
                        smb_encrypt=true;
4889
 
                        break;
4890
 
                case 'B':
4891
 
                        return(do_smb_browse());
4892
 
 
4893
 
                }
4894
 
        }
4895
 
 
4896
 
        /* We may still have some leftovers after the last popt option has been called */
4897
 
        if (tar_opt == true) {
4898
 
                while (poptPeekArg(pc)) {
4899
 
                        poptGetArg(pc);
4900
 
                }
4901
 
                tar_opt = false;
4902
 
        }
4903
 
 
4904
 
        /* if the service has not yet been specified lets see if it is available in the popt stack */
4905
 
        if (!service_opt && poptPeekArg(pc)) {
4906
 
                service = talloc_strdup(frame,poptGetArg(pc));
4907
 
                if (!service) {
4908
 
                        exit(ENOMEM);
4909
 
                }
4910
 
                service_opt = true;
4911
 
        }
4912
 
 
4913
 
        /* if the service has already been retrieved then check if we have also a password */
4914
 
        if (service_opt
4915
 
            && !get_cmdline_auth_info_got_pass(auth_info)
4916
 
            && poptPeekArg(pc)) {
4917
 
                set_cmdline_auth_info_password(auth_info,
4918
 
                                               poptGetArg(pc));
4919
 
        }
4920
 
 
4921
 
        /*
4922
 
         * Don't load debug level from smb.conf. It should be
4923
 
         * set by cmdline arg or remain default (0)
4924
 
         */
4925
 
        AllowDebugChange = false;
4926
 
 
4927
 
        /* save the workgroup...
4928
 
 
4929
 
           FIXME!! do we need to do this for other options as well
4930
 
           (or maybe a generic way to keep lp_load() from overwriting
4931
 
           everything)?  */
4932
 
 
4933
 
        fstrcpy( new_workgroup, lp_workgroup() );
4934
 
        calling_name = talloc_strdup(frame, global_myname() );
4935
 
        if (!calling_name) {
4936
 
                exit(ENOMEM);
4937
 
        }
4938
 
 
4939
 
        if ( override_logfile )
4940
 
                setup_logging( lp_logfile(), false );
4941
 
 
4942
 
        if (!lp_load(get_dyn_CONFIGFILE(),true,false,false,true)) {
4943
 
                fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
4944
 
                        argv[0], get_dyn_CONFIGFILE());
4945
 
        }
4946
 
 
4947
 
        if (get_cmdline_auth_info_use_machine_account(auth_info) &&
4948
 
            !set_cmdline_auth_info_machine_account_creds(auth_info)) {
4949
 
                exit(-1);
4950
 
        }
4951
 
 
4952
 
        load_interfaces();
4953
 
 
4954
 
        if (service_opt && service) {
4955
 
                size_t len;
4956
 
 
4957
 
                /* Convert any '/' characters in the service name to '\' characters */
4958
 
                string_replace(service, '/','\\');
4959
 
                if (count_chars(service,'\\') < 3) {
4960
 
                        d_printf("\n%s: Not enough '\\' characters in service\n",service);
4961
 
                        poptPrintUsage(pc, stderr, 0);
4962
 
                        exit(1);
4963
 
                }
4964
 
                /* Remove trailing slashes */
4965
 
                len = strlen(service);
4966
 
                while(len > 0 && service[len - 1] == '\\') {
4967
 
                        --len;
4968
 
                        service[len] = '\0';
4969
 
                }
4970
 
        }
4971
 
 
4972
 
        if ( strlen(new_workgroup) != 0 ) {
4973
 
                set_global_myworkgroup( new_workgroup );
4974
 
        }
4975
 
 
4976
 
        if ( strlen(calling_name) != 0 ) {
4977
 
                set_global_myname( calling_name );
4978
 
        } else {
4979
 
                TALLOC_FREE(calling_name);
4980
 
                calling_name = talloc_strdup(frame, global_myname() );
4981
 
        }
4982
 
 
4983
 
        smb_encrypt = get_cmdline_auth_info_smb_encrypt(auth_info);
4984
 
        if (!init_names()) {
4985
 
                fprintf(stderr, "init_names() failed\n");
4986
 
                exit(1);
4987
 
        }
4988
 
 
4989
 
        if(new_name_resolve_order)
4990
 
                lp_set_name_resolve_order(new_name_resolve_order);
4991
 
 
4992
 
        if (!tar_type && !query_host && !service && !message) {
4993
 
                poptPrintUsage(pc, stderr, 0);
4994
 
                exit(1);
4995
 
        }
4996
 
 
4997
 
        poptFreeContext(pc);
4998
 
 
4999
 
        DEBUG(3,("Client started (version %s).\n", samba_version_string()));
5000
 
 
5001
 
        /* Ensure we have a password (or equivalent). */
5002
 
        set_cmdline_auth_info_getpass(auth_info);
5003
 
 
5004
 
        if (tar_type) {
5005
 
                if (cmdstr)
5006
 
                        process_command_string(cmdstr);
5007
 
                return do_tar_op(base_directory);
5008
 
        }
5009
 
 
5010
 
        if (query_host && *query_host) {
5011
 
                char *qhost = query_host;
5012
 
                char *slash;
5013
 
 
5014
 
                while (*qhost == '\\' || *qhost == '/')
5015
 
                        qhost++;
5016
 
 
5017
 
                if ((slash = strchr_m(qhost, '/'))
5018
 
                    || (slash = strchr_m(qhost, '\\'))) {
5019
 
                        *slash = 0;
5020
 
                }
5021
 
 
5022
 
                if ((p=strchr_m(qhost, '#'))) {
5023
 
                        *p = 0;
5024
 
                        p++;
5025
 
                        sscanf(p, "%x", &name_type);
5026
 
                }
5027
 
 
5028
 
                return do_host_query(qhost);
5029
 
        }
5030
 
 
5031
 
        if (message) {
5032
 
                return do_message_op(auth_info);
5033
 
        }
5034
 
 
5035
 
        if (process(base_directory)) {
5036
 
                return 1;
5037
 
        }
5038
 
 
5039
 
        TALLOC_FREE(frame);
5040
 
        return rc;
5041
 
}