Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/source3/client
Files:
3 added
6 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/client/client.c

    r860 r988  
    2727#include "rpc_client/cli_pipe.h"
    2828#include "client/client_proto.h"
     29#include "client/clitar_proto.h"
    2930#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
    3031#include "../lib/util/select.h"
     
    3738#include "trans2.h"
    3839#include "libsmb/nmblib.h"
     40#include "include/ntioctl.h"
     41#include "../libcli/smb/smbXcli_base.h"
    3942
    4043#ifndef REGISTER
     
    4548
    4649extern bool override_logfile;
    47 extern char tar_type;
    4850
    4951static int port = 0;
    5052static char *service;
    5153static char *desthost;
    52 static char *calling_name;
    5354static bool grepable = false;
    5455static char *cmdstr = NULL;
    5556const char *cmd_ptr = NULL;
    5657
    57 static int io_bufsize = 524288;
     58static int io_bufsize = 0; /* we use the default size */
     59static int io_timeout = (CLIENT_TIMEOUT/1000); /* Per operation timeout (in seconds). */
    5860
    5961static int name_type = 0x20;
    60 static int max_protocol = PROTOCOL_NT1;
     62static int max_protocol = -1;
    6163
    6264static int process_tok(char *tok);
     
    6567#define CREATE_ACCESS_READ READ_CONTROL_ACCESS
    6668
    67 /* 30 second timeout on most commands */
    68 #define CLIENT_TIMEOUT (30*1000)
    69 #define SHORT_TIMEOUT (5*1000)
    70 
    7169/* value for unused fid field in trans2 secondary request */
    7270#define FID_UNUSED (0xFFFF)
     
    7775static bool translation = false;
    7876static bool have_ip;
    79 
    80 /* clitar bits insert */
    81 extern int blocksize;
    82 extern bool tar_inc;
    83 extern bool tar_reset;
    84 /* clitar bits end */
    8577
    8678static bool prompt = true;
     
    8981static bool showacls = false;
    9082bool lowercase = false;
     83static bool backup_intent = false;
    9184
    9285static struct sockaddr_storage dest_ss;
     
    234227
    235228        i = 0;
    236         while (i < (n - 1) && (i < BUFFER_SIZE)) {
     229        while (i < (n - 1)) {
    237230                if ((c = x_getc(f)) == EOF) {
    238231                        break;
     
    251244struct push_state {
    252245        XFILE *f;
    253         SMB_OFF_T nread;
     246        off_t nread;
    254247};
    255248
     
    306299static int do_dskattr(void)
    307300{
    308         int total, bsize, avail;
     301        uint64_t total, bsize, avail;
    309302        struct cli_state *targetcli = NULL;
    310303        char *targetpath = NULL;
     
    312305        NTSTATUS status;
    313306
    314         if ( !cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(), &targetcli, &targetpath)) {
    315                 d_printf("Error in dskattr: %s\n", cli_errstr(cli));
    316                 return 1;
    317         }
    318 
    319         status = cli_dskattr(targetcli, &bsize, &total, &avail);
     307        status = cli_resolve_path(ctx, "", auth_info, cli,
     308                                  client_get_cur_dir(), &targetcli,
     309                                  &targetpath);
    320310        if (!NT_STATUS_IS_OK(status)) {
    321311                d_printf("Error in dskattr: %s\n", nt_errstr(status));
     
    323313        }
    324314
    325         d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
    326                  total, bsize, avail);
     315        status = cli_disk_size(targetcli, targetpath, &bsize, &total, &avail);
     316        if (!NT_STATUS_IS_OK(status)) {
     317                d_printf("Error in dskattr: %s\n", nt_errstr(status));
     318                return 1;
     319        }
     320
     321        d_printf("\n\t\t%" PRIu64
     322                " blocks of size %" PRIu64
     323                ". %" PRIu64 " blocks available\n",
     324                total, bsize, avail);
    327325
    328326        return 0;
     
    363361        struct cli_state *targetcli = NULL;
    364362        SMB_STRUCT_STAT sbuf;
    365         uint32 attributes;
     363        uint32_t attributes;
    366364        int ret = 1;
    367365        TALLOC_CTX *ctx = talloc_stackframe();
     366        NTSTATUS status;
    368367
    369368        newdir = talloc_strdup(ctx, new_dir);
     
    407406        client_set_cur_dir(new_cd);
    408407
    409         if ( !cli_resolve_path(ctx, "", auth_info, cli, new_cd, &targetcli, &targetpath)) {
    410                 d_printf("cd %s: %s\n", new_cd, cli_errstr(cli));
     408        status = cli_resolve_path(ctx, "", auth_info, cli, new_cd,
     409                                  &targetcli, &targetpath);
     410        if (!NT_STATUS_IS_OK(status)) {
     411                d_printf("cd %s: %s\n", new_cd, nt_errstr(status));
    411412                client_set_cur_dir(saved_dir);
    412413                goto out;
     
    421422           Except Win9x doesn't support the qpathinfo_basic() call..... */
    422423
    423         if (targetcli->protocol > PROTOCOL_LANMAN2 && !targetcli->win95) {
    424                 NTSTATUS status;
     424        if (smbXcli_conn_protocol(targetcli->conn) > PROTOCOL_LANMAN2 && !targetcli->win95) {
    425425
    426426                status = cli_qpathinfo_basic(targetcli, targetpath, &sbuf,
     
    438438                }
    439439        } else {
    440                 NTSTATUS status;
    441440
    442441                targetpath = talloc_asprintf(ctx,
     
    549548                d_printf("  %-30s%7.7s %8.0f  %s",
    550549                         finfo->name,
    551                          attrib_string(finfo->mode),
     550                         attrib_string(talloc_tos(), finfo->mode),
    552551                        (double)finfo->size,
    553552                        time_to_asc(t));
     
    571570                /* print file meta date header */
    572571                d_printf( "FILENAME:%s\n", finfo->name);
    573                 d_printf( "MODE:%s\n", attrib_string(finfo->mode));
     572                d_printf( "MODE:%s\n", attrib_string(talloc_tos(), finfo->mode));
    574573                d_printf( "SIZE:%.0f\n", (double)finfo->size);
    575574                d_printf( "MTIME:%s", time_to_asc(t));
     
    577576                                      CREATE_ACCESS_READ, 0,
    578577                                      FILE_SHARE_READ|FILE_SHARE_WRITE,
    579                                       FILE_OPEN, 0x0, 0x0, &fnum);
     578                                      FILE_OPEN, 0x0, 0x0, &fnum, NULL);
    580579                if (!NT_STATUS_IS_OK(status)) {
    581580                        DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
     
    583582                } else {
    584583                        struct security_descriptor *sd = NULL;
    585                         sd = cli_query_secdesc(cli_state, fnum, ctx);
    586                         if (!sd) {
     584                        status = cli_query_secdesc(cli_state, fnum,
     585                                                   ctx, &sd);
     586                        if (!NT_STATUS_IS_OK(status)) {
    587587                                DEBUG( 0, ("display_finfo() failed to "
    588                                         "get security descriptor: %s",
    589                                         cli_errstr(cli_state)));
    590                                 status = cli_nt_error(cli_state);
     588                                           "get security descriptor: %s",
     589                                           nt_errstr(status)));
    591590                        } else {
    592591                                display_sec_desc(sd);
     
    704703        }
    705704        if (do_list_queue) {
    706                 safe_strcpy_base(do_list_queue + do_list_queue_end,
     705                strlcpy_base(do_list_queue + do_list_queue_end,
    707706                                 entry, do_list_queue, do_list_queue_size);
    708707                do_list_queue_end = new_end;
     
    815814
    816815NTSTATUS do_list(const char *mask,
    817                         uint16 attribute,
     816                        uint16_t attribute,
    818817                        NTSTATUS (*fn)(struct cli_state *cli_state, struct file_info *,
    819818                                   const char *dir),
     
    859858                        /* check for dfs */
    860859
    861                         if ( !cli_resolve_path(ctx, "", auth_info, cli, head, &targetcli, &targetpath ) ) {
    862                                 d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
     860                        status = cli_resolve_path(ctx, "", auth_info, cli,
     861                                                  head, &targetcli,
     862                                                  &targetpath);
     863                        if (!NT_STATUS_IS_OK(status)) {
     864                                d_printf("do_list: [%s] %s\n", head,
     865                                         nt_errstr(status));
    863866                                remove_do_list_queue_head();
    864867                                continue;
     
    898901        } else {
    899902                /* check for dfs */
    900                 if (cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetpath)) {
    901 
     903                status = cli_resolve_path(ctx, "", auth_info, cli, mask,
     904                                          &targetcli, &targetpath);
     905                if (NT_STATUS_IS_OK(status)) {
    902906                        status = cli_list(targetcli, targetpath, attribute,
    903907                                          do_list_helper, targetcli);
     
    909913                        TALLOC_FREE(targetpath);
    910914                } else {
    911                         d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli));
    912                         ret_status = cli_nt_error(cli);
     915                        d_printf("do_list: [%s] %s\n", mask, nt_errstr(status));
     916                        ret_status = status;
    913917                }
    914918        }
     
    926930{
    927931        TALLOC_CTX *ctx = talloc_tos();
    928         uint16 attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     932        uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
    929933        char *mask = NULL;
    930934        char *buf = NULL;
     
    976980{
    977981        TALLOC_CTX *ctx = talloc_tos();
    978         uint16 attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     982        uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
    979983        char *mask = NULL;
    980984        char *buf = NULL;
     
    10601064        bool newhandle = false;
    10611065        struct timespec tp_start;
    1062         uint16 attr;
    1063         SMB_OFF_T size;
     1066        uint16_t attr;
     1067        off_t size;
    10641068        off_t start = 0;
    1065         SMB_OFF_T nread = 0;
     1069        off_t nread = 0;
    10661070        int rc = 0;
    10671071        struct cli_state *targetcli = NULL;
     
    10761080
    10771081        if (lowercase) {
    1078                 strlower_m(lname);
    1079         }
    1080 
    1081         if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname ) ) {
    1082                 d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
     1082                if (!strlower_m(lname)) {
     1083                        d_printf("strlower_m %s failed\n", lname);
     1084                        return 1;
     1085                }
     1086        }
     1087
     1088        status = cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli,
     1089                                  &targetname);
     1090        if (!NT_STATUS_IS_OK(status)) {
     1091                d_printf("Failed to open %s: %s\n", rname, nt_errstr(status));
    10831092                return 1;
    10841093        }
     
    10971106        } else {
    10981107                if (reget) {
    1099                         handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
     1108                        handle = open(lname, O_WRONLY|O_CREAT, 0644);
    11001109                        if (handle >= 0) {
    1101                                 start = sys_lseek(handle, 0, SEEK_END);
     1110                                start = lseek(handle, 0, SEEK_END);
    11021111                                if (start == -1) {
    11031112                                        d_printf("Error seeking local file\n");
     
    11061115                        }
    11071116                } else {
    1108                         handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
     1117                        handle = open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
    11091118                }
    11101119                newhandle = true;
     
    11501159
    11511160        if (archive_level >= 2 && (attr & FILE_ATTRIBUTE_ARCHIVE)) {
    1152                 cli_setatr(cli, rname, attr & ~(uint16)FILE_ATTRIBUTE_ARCHIVE, 0);
     1161                cli_setatr(cli, rname, attr & ~(uint16_t)FILE_ATTRIBUTE_ARCHIVE, 0);
    11531162        }
    11541163
     
    12841293        string_replace(finfo->name,'\\','/');
    12851294        if (lowercase) {
    1286                 strlower_m(finfo->name);
     1295                if (!strlower_m(finfo->name)) {
     1296                        return NT_STATUS_INVALID_PARAMETER;
     1297                }
    12871298        }
    12881299
     
    13481359        int fd;
    13491360        int rc = 0;
     1361        mode_t mask;
    13501362
    13511363        rname = talloc_strdup(ctx, client_get_cur_dir());
     
    13581370                return 1;
    13591371        }
     1372        mask = umask(S_IRWXO | S_IRWXG);
    13601373        fd = mkstemp(lname);
     1374        umask(mask);
    13611375        if (fd == -1) {
    13621376                d_printf("failed to create temporary file for more\n");
     
    14061420{
    14071421        TALLOC_CTX *ctx = talloc_tos();
    1408         uint16 attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     1422        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
    14091423        char *mget_mask = NULL;
    14101424        char *buf = NULL;
     
    14701484        NTSTATUS status;
    14711485
    1472         if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
    1473                 d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
     1486        status = cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli,
     1487                                  &targetname);
     1488        if (!NT_STATUS_IS_OK(status)) {
     1489                d_printf("mkdir %s: %s\n", name, nt_errstr(status));
    14741490                return false;
    14751491        }
     
    15261542        char *mask = NULL;
    15271543        char *buf = NULL;
     1544        NTSTATUS status;
    15281545
    15291546        mask = talloc_strdup(ctx, client_get_cur_dir());
     
    15561573                }
    15571574
    1558                 if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
     1575                status = cli_resolve_path(ctx, "", auth_info, cli, mask,
     1576                                          &targetcli, &targetname);
     1577                if (!NT_STATUS_IS_OK(status)) {
    15591578                        return 1;
    15601579                }
     
    16161635static char *attr_str(TALLOC_CTX *mem_ctx, uint16_t mode)
    16171636{
    1618         char *attrs = TALLOC_ZERO_ARRAY(mem_ctx, char, 17);
     1637        char *attrs = talloc_zero_array(mem_ctx, char, 17);
    16191638        int i = 0;
    16201639
     
    16711690        fstring altname;
    16721691        struct timespec b_time, a_time, m_time, c_time;
    1673         SMB_OFF_T size;
     1692        off_t size;
    16741693        uint16_t mode;
    1675         SMB_INO_T ino;
    16761694        NTTIME tmp;
    16771695        uint16_t fnum;
     
    16871705                d_printf("%s getting alt name for %s\n", nt_errstr(status),
    16881706                         name);
    1689                 return false;
     1707                /*
     1708                 * Ignore not supported or not implemented, it does not
     1709                 * hurt if we can't list alternate names.
     1710                 */
     1711                if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
     1712                    NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
     1713                        altname[0] = '\0';
     1714                } else {
     1715                        return false;
     1716                }
    16901717        }
    16911718        d_printf("altname: %s\n", altname);
    16921719
    1693         status = cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time,
    1694                                 &size, &mode, &ino);
     1720        status = cli_qpathinfo3(cli, name, &b_time, &a_time, &m_time, &c_time,
     1721                                &size, &mode, NULL);
    16951722        if (!NT_STATUS_IS_OK(status)) {
    16961723                d_printf("%s getting pathinfo for %s\n", nt_errstr(status),
     
    16991726        }
    17001727
    1701         unix_timespec_to_nt_time(&tmp, b_time);
     1728        tmp = unix_timespec_to_nt_time(b_time);
    17021729        d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
    17031730
    1704         unix_timespec_to_nt_time(&tmp, a_time);
     1731        tmp = unix_timespec_to_nt_time(a_time);
    17051732        d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
    17061733
    1707         unix_timespec_to_nt_time(&tmp, m_time);
     1734        tmp = unix_timespec_to_nt_time(m_time);
    17081735        d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
    17091736
    1710         unix_timespec_to_nt_time(&tmp, c_time);
     1737        tmp = unix_timespec_to_nt_time(c_time);
    17111738        d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
    17121739
     
    17241751                d_printf("stream: [%s], %lld bytes\n", streams[i].name,
    17251752                         (unsigned long long)streams[i].size);
     1753        }
     1754
     1755        if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
     1756                char *subst, *print;
     1757                uint32_t flags;
     1758
     1759                status = cli_readlink(cli, name, talloc_tos(), &subst, &print,
     1760                                      &flags);
     1761                if (!NT_STATUS_IS_OK(status)) {
     1762                        d_fprintf(stderr, "cli_readlink returned %s\n",
     1763                                  nt_errstr(status));
     1764                } else {
     1765                        d_printf("symlink: subst=[%s], print=[%s], flags=%x\n",
     1766                                 subst, print, flags);
     1767                        TALLOC_FREE(subst);
     1768                        TALLOC_FREE(print);
     1769                }
    17261770        }
    17271771
     
    17311775                              FILE_SHARE_READ|FILE_SHARE_WRITE
    17321776                              |FILE_SHARE_DELETE,
    1733                               FILE_OPEN, 0x0, 0x0, &fnum);
     1777                              FILE_OPEN, 0x0, 0x0, &fnum, NULL);
    17341778        if (!NT_STATUS_IS_OK(status)) {
    17351779                /*
     
    17521796                snap_name = talloc_asprintf(talloc_tos(), "%s%s",
    17531797                                            snapshots[i], name);
    1754                 status = cli_qpathinfo2(cli, snap_name, &b_time, &a_time,
     1798                status = cli_qpathinfo3(cli, snap_name, &b_time, &a_time,
    17551799                                        &m_time, &c_time, &size,
    17561800                                        NULL, NULL);
     
    17611805                        continue;
    17621806                }
    1763                 unix_timespec_to_nt_time(&tmp, b_time);
     1807                tmp = unix_timespec_to_nt_time(b_time);
    17641808                d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
    1765                 unix_timespec_to_nt_time(&tmp, a_time);
     1809                tmp = unix_timespec_to_nt_time(a_time);
    17661810                d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
    1767                 unix_timespec_to_nt_time(&tmp, m_time);
     1811                tmp =unix_timespec_to_nt_time(m_time);
    17681812                d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
    1769                 unix_timespec_to_nt_time(&tmp, c_time);
     1813                tmp = unix_timespec_to_nt_time(c_time);
    17701814                d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
    17711815                d_printf("size: %d\n", (int)size);
     
    17731817
    17741818        TALLOC_FREE(snapshots);
     1819        cli_close(cli, fnum);
    17751820
    17761821        return 0;
     
    18151860        uint16_t fnum;
    18161861        XFILE *f;
    1817         SMB_OFF_T start = 0;
     1862        off_t start = 0;
    18181863        int rc = 0;
    18191864        struct timespec tp_start;
     
    18231868        NTSTATUS status;
    18241869
    1825         if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname)) {
    1826                 d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
     1870        status = cli_resolve_path(ctx, "", auth_info, cli, rname,
     1871                                  &targetcli, &targetname);
     1872        if (!NT_STATUS_IS_OK(status)) {
     1873                d_printf("Failed to open %s: %s\n", rname, nt_errstr(status));
    18271874                return 1;
    18281875        }
     
    20492096                      const char *expression, bool match)
    20502097{
    2051         SMB_STRUCT_DIR *dir;
     2098        DIR *dir;
    20522099        struct file_list *entry;
    20532100        struct stat statbuf;
     
    20572104        const char *dname;
    20582105
    2059         dir = sys_opendir(directory);
     2106        dir = opendir(directory);
    20602107        if (!dir)
    20612108                return -1;
     
    20862133                                if (ret == -1) {
    20872134                                        SAFE_FREE(path);
    2088                                         sys_closedir(dir);
     2135                                        closedir(dir);
    20892136                                        return -1;
    20902137                                }
     
    20932140                        if (!entry) {
    20942141                                d_printf("Out of memory in file_find\n");
    2095                                 sys_closedir(dir);
     2142                                closedir(dir);
    20962143                                return -1;
    20972144                        }
     
    21042151        }
    21052152
    2106         sys_closedir(dir);
     2153        closedir(dir);
    21072154        return 0;
    21082155}
     
    22132260                return 0;
    22142261        } else {
    2215                 d_printf("Error cancelling job %d : %s\n",job,cli_errstr(cli));
     2262                NTSTATUS status = cli_nt_error(cli);
     2263                d_printf("Error cancelling job %d : %s\n",
     2264                         job, nt_errstr(status));
    22162265                return 1;
    22172266        }
     
    22652314                                        "%s-%d",
    22662315                                        p+1,
    2267                                         (int)sys_getpid());
     2316                                        (int)getpid());
    22682317        }
    22692318        if (strequal(lname,"-")) {
    22702319                rname = talloc_asprintf(ctx,
    22712320                                "stdin-%d",
    2272                                 (int)sys_getpid());
     2321                                (int)getpid());
    22732322        }
    22742323        if (!rname) {
     
    23422391        char *buf = NULL;
    23432392        NTSTATUS status = NT_STATUS_OK;
    2344         uint16 attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
     2393        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
    23452394
    23462395        if (recurse) {
     
    23772426        char *mask = NULL;
    23782427        char *buf = NULL;
    2379         uint16 attribute;
     2428        uint16_t attribute;
    23802429        struct cli_state *targetcli;
    23812430        char *targetname = NULL;
     
    23872436        }
    23882437
    2389         attribute = (uint16)strtol(buf, (char **)NULL, 16);
     2438        attribute = (uint16_t)strtol(buf, (char **)NULL, 16);
    23902439
    23912440        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    24012450        }
    24022451
    2403         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2404                 d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
     2452        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2453                                  &targetname);
     2454        if (!NT_STATUS_IS_OK(status)) {
     2455                d_printf("cmd_wdel %s: %s\n", mask, nt_errstr(status));
    24052456                return 1;
    24062457        }
     
    24252476        struct cli_state *targetcli;
    24262477        uint16_t fnum = (uint16_t)-1;
     2478        NTSTATUS status;
    24272479
    24282480        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    24382490        }
    24392491
    2440         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2441                 d_printf("open %s: %s\n", mask, cli_errstr(cli));
    2442                 return 1;
    2443         }
    2444 
    2445         if (!NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetname, 0,
     2492        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2493                                  &targetname);
     2494        if (!NT_STATUS_IS_OK(status)) {
     2495                d_printf("open %s: %s\n", mask, nt_errstr(status));
     2496                return 1;
     2497        }
     2498
     2499        status = cli_ntcreate(targetcli, targetname, 0,
    24462500                        FILE_READ_DATA|FILE_WRITE_DATA, 0,
    2447                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
    2448                 if (NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetname, 0,
     2501                        FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
     2502                        0x0, 0x0, &fnum, NULL);
     2503        if (!NT_STATUS_IS_OK(status)) {
     2504                status = cli_ntcreate(targetcli, targetname, 0,
    24492505                                FILE_READ_DATA, 0,
    2450                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
     2506                                FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
     2507                                0x0, 0x0, &fnum, NULL);
     2508                if (NT_STATUS_IS_OK(status)) {
    24512509                        d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
    24522510                } else {
    2453                         d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
     2511                        d_printf("Failed to open file %s. %s\n",
     2512                                 targetname, nt_errstr(status));
    24542513                }
    24552514        } else {
     
    25142573        mode_t mode;
    25152574        uint16_t fnum;
     2575        NTSTATUS status;
    25162576
    25172577        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    25332593        mode = (mode_t)strtol(buf, (char **)NULL, 8);
    25342594
    2535         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2536                 d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
    2537                 return 1;
    2538         }
    2539 
    2540         if (!NT_STATUS_IS_OK(cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode, &fnum))) {
    2541                 if (NT_STATUS_IS_OK(cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode, &fnum))) {
    2542                         d_printf("posix_open file %s: for readonly fnum %d\n", targetname, fnum);
     2595        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2596                                  &targetname);
     2597        if (!NT_STATUS_IS_OK(status)) {
     2598                d_printf("posix_open %s: %s\n", mask, nt_errstr(status));
     2599                return 1;
     2600        }
     2601
     2602        status = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode,
     2603                                &fnum);
     2604        if (!NT_STATUS_IS_OK(status)) {
     2605                status = cli_posix_open(targetcli, targetname,
     2606                                        O_CREAT|O_RDONLY, mode, &fnum);
     2607                if (!NT_STATUS_IS_OK(status)) {
     2608                        d_printf("Failed to open file %s. %s\n", targetname,
     2609                                 nt_errstr(status));
    25432610                } else {
    2544                         d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
     2611                        d_printf("posix_open file %s: for readonly fnum %d\n",
     2612                                 targetname, fnum);
    25452613                }
    25462614        } else {
    2547                 d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
     2615                d_printf("posix_open file %s: for read/write fnum %d\n",
     2616                         targetname, fnum);
    25482617        }
    25492618
     
    25592628        struct cli_state *targetcli;
    25602629        mode_t mode;
     2630        NTSTATUS status;
    25612631
    25622632        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    25782648        mode = (mode_t)strtol(buf, (char **)NULL, 8);
    25792649
    2580         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2581                 d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
    2582                 return 1;
    2583         }
    2584 
    2585         if (!NT_STATUS_IS_OK(cli_posix_mkdir(targetcli, targetname, mode))) {
    2586                 d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
     2650        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2651                                  &targetname);
     2652        if (!NT_STATUS_IS_OK(status)) {
     2653                d_printf("posix_mkdir %s: %s\n", mask, nt_errstr(status));
     2654                return 1;
     2655        }
     2656
     2657        status = cli_posix_mkdir(targetcli, targetname, mode);
     2658        if (!NT_STATUS_IS_OK(status)) {
     2659                d_printf("Failed to open file %s. %s\n",
     2660                         targetname, nt_errstr(status));
    25872661        } else {
    25882662                d_printf("posix_mkdir created directory %s\n", targetname);
     
    25982672        char *targetname = NULL;
    25992673        struct cli_state *targetcli;
     2674        NTSTATUS status;
    26002675
    26012676        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    26112686        }
    26122687
    2613         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2614                 d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
    2615                 return 1;
    2616         }
    2617 
    2618         if (!NT_STATUS_IS_OK(cli_posix_unlink(targetcli, targetname))) {
    2619                 d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
     2688        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2689                                  &targetname);
     2690        if (!NT_STATUS_IS_OK(status)) {
     2691                d_printf("posix_unlink %s: %s\n", mask, nt_errstr(status));
     2692                return 1;
     2693        }
     2694
     2695        status = cli_posix_unlink(targetcli, targetname);
     2696        if (!NT_STATUS_IS_OK(status)) {
     2697                d_printf("Failed to unlink file %s. %s\n",
     2698                         targetname, nt_errstr(status));
    26202699        } else {
    26212700                d_printf("posix_unlink deleted file %s\n", targetname);
     
    26322711        char *targetname = NULL;
    26332712        struct cli_state *targetcli;
     2713        NTSTATUS status;
    26342714
    26352715        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    26452725        }
    26462726
    2647         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2648                 d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
    2649                 return 1;
    2650         }
    2651 
    2652         if (!NT_STATUS_IS_OK(cli_posix_rmdir(targetcli, targetname))) {
    2653                 d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
     2727        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2728                                  &targetname);
     2729        if (!NT_STATUS_IS_OK(status)) {
     2730                d_printf("posix_rmdir %s: %s\n", mask, nt_errstr(status));
     2731                return 1;
     2732        }
     2733
     2734        status = cli_posix_rmdir(targetcli, targetname);
     2735        if (!NT_STATUS_IS_OK(status)) {
     2736                d_printf("Failed to unlink directory %s. %s\n",
     2737                         targetname, nt_errstr(status));
    26542738        } else {
    26552739                d_printf("posix_rmdir deleted directory %s\n", targetname);
     
    26642748        char *buf = NULL;
    26652749        int fnum;
     2750        NTSTATUS status;
    26662751
    26672752        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    26722757        fnum = atoi(buf);
    26732758        /* We really should use the targetcli here.... */
    2674         if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
    2675                 d_printf("close %d: %s\n", fnum, cli_errstr(cli));
     2759        status = cli_close(cli, fnum);
     2760        if (!NT_STATUS_IS_OK(status)) {
     2761                d_printf("close %d: %s\n", fnum, nt_errstr(status));
    26762762                return 1;
    26772763        }
     
    26822768{
    26832769        TALLOC_CTX *ctx = talloc_tos();
    2684         uint16 major, minor;
    2685         uint32 caplow, caphigh;
     2770        uint16_t major, minor;
     2771        uint32_t caplow, caphigh;
    26862772        char *caps;
    26872773        NTSTATUS status;
     
    27912877        enum brl_type lock_type;
    27922878        int fnum;
     2879        NTSTATUS status;
    27932880
    27942881        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    28262913        len = (uint64_t)strtol(buf, (char **)NULL, 16);
    28272914
    2828         if (!NT_STATUS_IS_OK(cli_posix_lock(cli, fnum, start, len, true, lock_type))) {
    2829                 d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
     2915        status = cli_posix_lock(cli, fnum, start, len, true, lock_type);
     2916        if (!NT_STATUS_IS_OK(status)) {
     2917                d_printf("lock failed %d: %s\n", fnum, nt_errstr(status));
    28302918        }
    28312919
     
    28392927        uint64_t start, len;
    28402928        int fnum;
     2929        NTSTATUS status;
    28412930
    28422931        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    28602949        len = (uint64_t)strtol(buf, (char **)NULL, 16);
    28612950
    2862         if (!NT_STATUS_IS_OK(cli_posix_unlock(cli, fnum, start, len))) {
    2863                 d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
     2951        status = cli_posix_unlock(cli, fnum, start, len);
     2952        if (!NT_STATUS_IS_OK(status)) {
     2953                d_printf("unlock failed %d: %s\n", fnum, nt_errstr(status));
    28642954        }
    28652955
     
    28792969        char *targetname = NULL;
    28802970        struct cli_state *targetcli;
     2971        NTSTATUS status;
    28812972
    28822973        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    28922983        }
    28932984
    2894         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
    2895                 d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
    2896                 return 1;
    2897         }
    2898 
    2899         if (!NT_STATUS_IS_OK(cli_rmdir(targetcli, targetname))) {
     2985        status = cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli,
     2986                                  &targetname);
     2987        if (!NT_STATUS_IS_OK(status)) {
     2988                d_printf("rmdir %s: %s\n", mask, nt_errstr(status));
     2989                return 1;
     2990        }
     2991
     2992        status = cli_rmdir(targetcli, targetname);
     2993        if (!NT_STATUS_IS_OK(status)) {
    29002994                d_printf("%s removing remote directory file %s\n",
    2901                          cli_errstr(targetcli),mask);
     2995                         nt_errstr(status), mask);
    29022996        }
    29032997
     
    29183012        char *targetname = NULL;
    29193013        struct cli_state *targetcli;
     3014        NTSTATUS status;
    29203015
    29213016        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
     
    29393034        }
    29403035
    2941         if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
    2942                 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
     3036        status = cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli,
     3037                                  &targetname);
     3038        if (!NT_STATUS_IS_OK(status)) {
     3039                d_printf("link %s: %s\n", oldname, nt_errstr(status));
    29433040                return 1;
    29443041        }
     
    29493046        }
    29503047
    2951         if (!NT_STATUS_IS_OK(cli_posix_hardlink(targetcli, targetname, newname))) {
    2952                 d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
     3048        status = cli_posix_hardlink(targetcli, targetname, newname);
     3049        if (!NT_STATUS_IS_OK(status)) {
     3050                d_printf("%s linking files (%s -> %s)\n",
     3051                         nt_errstr(status), newname, oldname);
    29533052                return 1;
    29543053        }
     
    29683067        char linkname[PATH_MAX+1];
    29693068        struct cli_state *targetcli;
     3069        NTSTATUS status;
    29703070
    29713071        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     
    29813081        }
    29823082
    2983         if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
    2984                 d_printf("readlink %s: %s\n", name, cli_errstr(cli));
     3083        status = cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli,
     3084                                  &targetname);
     3085        if (!NT_STATUS_IS_OK(status)) {
     3086                d_printf("readlink %s: %s\n", name, nt_errstr(status));
    29853087                return 1;
    29863088        }
     
    29913093        }
    29923094
    2993         if (!NT_STATUS_IS_OK(cli_posix_readlink(targetcli, name,
    2994                         linkname, PATH_MAX+1))) {
     3095        status = cli_posix_readlink(targetcli, name, linkname, PATH_MAX+1);
     3096        if (!NT_STATUS_IS_OK(status)) {
    29953097                d_printf("%s readlink on file %s\n",
    2996                         cli_errstr(targetcli), name);
     3098                         nt_errstr(status), name);
    29973099                return 1;
    29983100        }
     
    30163118        char *buf2 = NULL;
    30173119        struct cli_state *newcli;
     3120        NTSTATUS status;
    30183121
    30193122        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
     
    30253128        oldname = buf;
    30263129
    3027         newname = talloc_asprintf(ctx,
    3028                         "%s%s",
    3029                         client_get_cur_dir(),
    3030                         buf2);
    3031         if (!newname) {
    3032                 return 1;
    3033         }
    3034 
    3035         /* New name must be present in share namespace. */
    3036         if (!cli_resolve_path(ctx, "", auth_info, cli, newname, &newcli, &newname)) {
    3037                 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
    3038                 return 1;
    3039         }
    3040 
    3041         if (!SERVER_HAS_UNIX_CIFS(newcli)) {
    3042                 d_printf("Server doesn't support UNIX CIFS calls.\n");
    3043                 return 1;
    3044         }
    3045 
    3046         if (!NT_STATUS_IS_OK(cli_posix_symlink(newcli, oldname, newname))) {
     3130        if (SERVER_HAS_UNIX_CIFS(cli)) {
     3131                newname = talloc_asprintf(ctx, "%s%s", client_get_cur_dir(),
     3132                                          buf2);
     3133                if (!newname) {
     3134                        return 1;
     3135                }
     3136                /* New name must be present in share namespace. */
     3137                status = cli_resolve_path(ctx, "", auth_info, cli, newname,
     3138                                          &newcli, &newname);
     3139                if (!NT_STATUS_IS_OK(status)) {
     3140                        d_printf("link %s: %s\n", oldname, nt_errstr(status));
     3141                        return 1;
     3142                }
     3143                status = cli_posix_symlink(newcli, oldname, newname);
     3144        } else {
     3145                status = cli_symlink(
     3146                        cli, oldname, buf2,
     3147                        buf2[0] == '\\' ? 0 : SYMLINK_FLAG_RELATIVE);
     3148        }
     3149
     3150        if (!NT_STATUS_IS_OK(status)) {
    30473151                d_printf("%s symlinking files (%s -> %s)\n",
    3048                         cli_errstr(newcli), newname, newname);
     3152                         nt_errstr(status), oldname, newname);
    30493153                return 1;
    30503154        }
     
    30663170        struct cli_state *targetcli;
    30673171        mode_t mode;
     3172        NTSTATUS status;
    30683173
    30693174        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
     
    30823187        mode = (mode_t)strtol(buf, NULL, 8);
    30833188
    3084         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
    3085                 d_printf("chmod %s: %s\n", src, cli_errstr(cli));
     3189        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3190                                  &targetname);
     3191        if (!NT_STATUS_IS_OK(status)) {
     3192                d_printf("chmod %s: %s\n", src, nt_errstr(status));
    30863193                return 1;
    30873194        }
     
    30923199        }
    30933200
    3094         if (!NT_STATUS_IS_OK(cli_posix_chmod(targetcli, targetname, mode))) {
     3201        status = cli_posix_chmod(targetcli, targetname, mode);
     3202        if (!NT_STATUS_IS_OK(status)) {
    30953203                d_printf("%s chmod file %s 0%o\n",
    3096                         cli_errstr(targetcli), src, (unsigned int)mode);
     3204                         nt_errstr(status), src, (unsigned int)mode);
    30973205                return 1;
    30983206        }
     
    32143322        char *targetname = NULL;
    32153323        struct cli_state *targetcli;
    3216         uint16 major, minor;
    3217         uint32 caplow, caphigh;
     3324        uint16_t major, minor;
     3325        uint32_t caplow, caphigh;
    32183326        char *retbuf = NULL;
    32193327        size_t rb_size = 0;
    32203328        SMB_STRUCT_STAT sbuf;
    3221         uint16 num_file_acls = 0;
    3222         uint16 num_dir_acls = 0;
    3223         uint16 i;
     3329        uint16_t num_file_acls = 0;
     3330        uint16_t num_dir_acls = 0;
     3331        uint16_t i;
    32243332        NTSTATUS status;
    32253333
     
    32363344        }
    32373345
    3238         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
    3239                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
     3346        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3347                                  &targetname);
     3348        if (!NT_STATUS_IS_OK(status)) {
     3349                d_printf("stat %s: %s\n", src, nt_errstr(status));
    32403350                return 1;
    32413351        }
     
    32603370        }
    32613371
     3372        status = cli_posix_stat(targetcli, targetname, &sbuf);
    32623373        if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) {
    32633374                d_printf("%s getfacl doing a stat on file %s\n",
    3264                         cli_errstr(targetcli), src);
    3265                 return 1;
    3266         }
    3267 
    3268         if (!NT_STATUS_IS_OK(cli_posix_getfacl(targetcli, targetname, ctx, &rb_size, &retbuf))) {
     3375                         nt_errstr(status), src);
     3376                return 1;
     3377        }
     3378
     3379        status = cli_posix_getacl(targetcli, targetname, ctx, &rb_size, &retbuf);
     3380        if (!NT_STATUS_IS_OK(status)) {
    32693381                d_printf("%s getfacl file %s\n",
    3270                         cli_errstr(targetcli), src);
     3382                         nt_errstr(status), src);
    32713383                return 1;
    32723384        }
     
    32973409
    32983410        for (i = 0; i < num_file_acls; i++) {
    3299                 uint32 uorg;
     3411                uint32_t uorg;
    33003412                fstring permstring;
    33013413                unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE));
     
    33343446
    33353447        for (i = 0; i < num_dir_acls; i++) {
    3336                 uint32 uorg;
     3448                uint32_t uorg;
    33373449                fstring permstring;
    33383450                unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE));
     
    33733485}
    33743486
    3375 static void printf_cb(const char *buf, void *private_data)
    3376 {
    3377         printf("%s", buf);
    3378 }
    3379 
    33803487/****************************************************************************
    33813488 Get the EA list of a file
     
    34053512        }
    34063513
    3407         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
    3408                               &targetname)) {
    3409                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
     3514        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3515                                  &targetname);
     3516        if (!NT_STATUS_IS_OK(status)) {
     3517                d_printf("stat %s: %s\n", src, nt_errstr(status));
    34103518                return 1;
    34113519        }
     
    34203528        for (i=0; i<num_eas; i++) {
    34213529                d_printf("%s (%d) =\n", eas[i].name, (int)eas[i].flags);
    3422                 dump_data_cb(eas[i].value.data, eas[i].value.length, false,
    3423                              printf_cb, NULL);
     3530                dump_data_file(eas[i].value.data, eas[i].value.length, false,
     3531                               stdout);
    34243532                d_printf("\n");
    34253533        }
     
    34613569        }
    34623570
    3463         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
    3464                               &targetname)) {
    3465                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
     3571        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3572                                  &targetname);
     3573        if (!NT_STATUS_IS_OK(status)) {
     3574                d_printf("stat %s: %s\n", src, nt_errstr(status));
    34663575                return 1;
    34673576        }
     
    34923601        struct tm *lt;
    34933602        time_t tmp_time;
     3603        NTSTATUS status;
    34943604
    34953605        if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
     
    35053615        }
    35063616
    3507         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
    3508                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
     3617        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3618                                  &targetname);
     3619        if (!NT_STATUS_IS_OK(status)) {
     3620                d_printf("stat %s: %s\n", src, nt_errstr(status));
    35093621                return 1;
    35103622        }
     
    35153627        }
    35163628
    3517         if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) {
     3629        status = cli_posix_stat(targetcli, targetname, &sbuf);
     3630        if (!NT_STATUS_IS_OK(status)) {
    35183631                d_printf("%s stat file %s\n",
    3519                         cli_errstr(targetcli), src);
     3632                         nt_errstr(status), src);
    35203633                return 1;
    35213634        }
     
    35913704        struct cli_state *targetcli;
    35923705        char *targetname = NULL;
     3706        NTSTATUS status;
    35933707
    35943708        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
     
    36093723                return 1;
    36103724        }
    3611         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname) ) {
    3612                 d_printf("chown %s: %s\n", src, cli_errstr(cli));
     3725        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3726                                  &targetname);
     3727        if (!NT_STATUS_IS_OK(status)) {
     3728                d_printf("chown %s: %s\n", src, nt_errstr(status));
    36133729                return 1;
    36143730        }
     
    36193735        }
    36203736
    3621         if (!NT_STATUS_IS_OK(cli_posix_chown(targetcli, targetname, uid, gid))) {
     3737        status = cli_posix_chown(targetcli, targetname, uid, gid);
     3738        if (!NT_STATUS_IS_OK(status)) {
    36223739                d_printf("%s chown file %s uid=%d, gid=%d\n",
    3623                         cli_errstr(targetcli), src, (int)uid, (int)gid);
     3740                         nt_errstr(status), src, (int)uid, (int)gid);
    36243741                return 1;
    36253742        }
     
    36403757        char *targetsrc;
    36413758        char *targetdest;
     3759        NTSTATUS status;
    36423760
    36433761        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
     
    36633781        }
    36643782
    3665         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetsrc)) {
    3666                 d_printf("rename %s: %s\n", src, cli_errstr(cli));
    3667                 return 1;
    3668         }
    3669 
    3670         if (!cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli, &targetdest)) {
    3671                 d_printf("rename %s: %s\n", dest, cli_errstr(cli));
    3672                 return 1;
    3673         }
    3674 
    3675         if (!NT_STATUS_IS_OK(cli_rename(targetcli, targetsrc, targetdest))) {
     3783        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3784                                  &targetsrc);
     3785        if (!NT_STATUS_IS_OK(status)) {
     3786                d_printf("rename %s: %s\n", src, nt_errstr(status));
     3787                return 1;
     3788        }
     3789
     3790        status = cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli,
     3791                                  &targetdest);
     3792        if (!NT_STATUS_IS_OK(status)) {
     3793                d_printf("rename %s: %s\n", dest, nt_errstr(status));
     3794                return 1;
     3795        }
     3796
     3797        status = cli_rename(targetcli, targetsrc, targetdest);
     3798        if (!NT_STATUS_IS_OK(status)) {
    36763799                d_printf("%s renaming files %s -> %s \n",
    3677                         cli_errstr(targetcli),
     3800                        nt_errstr(status),
    36783801                        targetsrc,
    36793802                        targetdest);
     
    36843807}
    36853808
    3686 /****************************************************************************
    3687  Print the volume name.
    3688 ****************************************************************************/
    3689 
    3690 static int cmd_volume(void)
    3691 {
    3692         fstring volname;
    3693         uint32 serial_num;
    3694         time_t create_date;
    3695         NTSTATUS status;
    3696 
    3697         status = cli_get_fs_volume_info(cli, volname, &serial_num,
    3698                                         &create_date);
    3699         if (!NT_STATUS_IS_OK(status)) {
    3700                 d_printf("Error %s getting volume info\n", nt_errstr(status));
    3701                 return 1;
    3702         }
    3703 
    3704         d_printf("Volume: |%s| serial number 0x%x\n",
    3705                         volname, (unsigned int)serial_num);
    3706         return 0;
    3707 }
    3708 
    3709 /****************************************************************************
    3710  Hard link files using the NT call.
    3711 ****************************************************************************/
    3712 
    3713 static int cmd_hardlink(void)
     3809struct scopy_timing {
     3810        struct timespec tp_start;
     3811};
     3812
     3813static int scopy_status(off_t written, void *priv)
     3814{
     3815        struct timespec tp_end;
     3816        unsigned int scopy_total_time_ms;
     3817        struct scopy_timing *st = priv;
     3818
     3819        clock_gettime_mono(&tp_end);
     3820        scopy_total_time_ms = nsec_time_diff(&tp_end,&st->tp_start)/1000000;
     3821
     3822        DEBUG(5,("Copied %jd bytes at an average %3.1f kb/s\n",
     3823                 (intmax_t)written, written / (1.024*scopy_total_time_ms)));
     3824
     3825        return true;
     3826}
     3827
     3828/****************************************************************************
     3829 Server-Side copy some file.
     3830****************************************************************************/
     3831
     3832static int cmd_scopy(void)
    37143833{
    37153834        TALLOC_CTX *ctx = talloc_tos();
     
    37173836        char *buf, *buf2;
    37183837        struct cli_state *targetcli;
    3719         char *targetname;
     3838        char *targetsrc;
     3839        char *targetdest;
     3840        uint32_t DesiredAccess, ShareAccess, CreateDisposition, CreateOptions;
     3841        struct smb_create_returns cr;
     3842        uint16_t destfnum = (uint16_t)-1;
     3843        uint16_t srcfnum = (uint16_t)-1;
     3844        off_t written = 0;
     3845        struct scopy_timing st;
     3846        int rc = 0;
     3847        NTSTATUS status;
    37203848
    37213849        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
    3722             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
    3723                 d_printf("hardlink <src> <dest>\n");
     3850                        !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
     3851                d_printf("scopy <src> <dest>\n");
    37243852                return 1;
    37253853        }
     
    37413869        }
    37423870
    3743         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
    3744                 d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
    3745                 return 1;
    3746         }
    3747 
    3748         if (!NT_STATUS_IS_OK(cli_nt_hardlink(targetcli, targetname, dest))) {
    3749                 d_printf("%s doing an NT hard link of files\n",cli_errstr(targetcli));
     3871        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     3872                        &targetsrc);
     3873        if (!NT_STATUS_IS_OK(status)) {
     3874                d_printf("scopy %s: %s\n", src, nt_errstr(status));
     3875                return 1;
     3876        }
     3877
     3878        status = cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli,
     3879                        &targetdest);
     3880        if (!NT_STATUS_IS_OK(status)) {
     3881                d_printf("scopy %s: %s\n", dest, nt_errstr(status));
     3882                return 1;
     3883        }
     3884
     3885
     3886        DesiredAccess = (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES|
     3887                        READ_CONTROL_ACCESS|SYNCHRONIZE_ACCESS);
     3888        ShareAccess = FILE_SHARE_READ|FILE_SHARE_DELETE;
     3889        CreateDisposition = FILE_OPEN;
     3890        CreateOptions = (FILE_SEQUENTIAL_ONLY|FILE_NON_DIRECTORY_FILE|
     3891                        FILE_OPEN_REPARSE_POINT);
     3892        status = cli_ntcreate(targetcli, targetsrc, 0, DesiredAccess, 0,
     3893                        ShareAccess, CreateDisposition, CreateOptions, 0x0,
     3894                        &srcfnum, &cr);
     3895        if (!NT_STATUS_IS_OK(status)) {
     3896                d_printf("Failed to open file %s. %s\n",
     3897                                targetsrc, nt_errstr(status));
     3898                return 1;
     3899        }
     3900
     3901        DesiredAccess = (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_READ_EA|
     3902                        FILE_WRITE_EA|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|
     3903                        DELETE_ACCESS|READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|SYNCHRONIZE_ACCESS);
     3904        ShareAccess = FILE_SHARE_NONE;
     3905        CreateDisposition = FILE_CREATE;
     3906        CreateOptions = FILE_SEQUENTIAL_ONLY|FILE_NON_DIRECTORY_FILE;
     3907        status = cli_ntcreate(targetcli, targetdest, 0, DesiredAccess,
     3908                        FILE_ATTRIBUTE_ARCHIVE, ShareAccess, CreateDisposition,
     3909                        CreateOptions, 0x0, &destfnum, NULL);
     3910        if (!NT_STATUS_IS_OK(status)) {
     3911                d_printf("Failed to create file %s. %s\n",
     3912                                targetdest, nt_errstr(status));
     3913                cli_close(targetcli, srcfnum);
     3914                return 1;
     3915        }
     3916
     3917        clock_gettime_mono(&st.tp_start);
     3918        status = cli_splice(targetcli, targetcli, srcfnum, destfnum,
     3919                        cr.end_of_file, 0, 0, &written, scopy_status, &st);
     3920        if (!NT_STATUS_IS_OK(status)) {
     3921                d_printf("%s copying file %s -> %s \n",
     3922                                nt_errstr(status),
     3923                                targetsrc,
     3924                                targetdest);
     3925                rc = 1;
     3926        }
     3927
     3928        status = cli_close(targetcli, srcfnum);
     3929        if (!NT_STATUS_IS_OK(status)) {
     3930                d_printf("Error %s closing remote source file\n", nt_errstr(status));
     3931                rc = 1;
     3932        }
     3933        status = cli_close(targetcli, destfnum);
     3934        if (!NT_STATUS_IS_OK(status)) {
     3935                d_printf("Error %s closing remote dest file\n", nt_errstr(status));
     3936                rc = 1;
     3937        }
     3938
     3939        return rc;
     3940}
     3941
     3942/****************************************************************************
     3943 Print the volume name.
     3944****************************************************************************/
     3945
     3946static int cmd_volume(void)
     3947{
     3948        char *volname;
     3949        uint32_t serial_num;
     3950        time_t create_date;
     3951        NTSTATUS status;
     3952
     3953        status = cli_get_fs_volume_info(cli, talloc_tos(),
     3954                                        &volname, &serial_num,
     3955                                        &create_date);
     3956        if (!NT_STATUS_IS_OK(status)) {
     3957                d_printf("Error %s getting volume info\n", nt_errstr(status));
     3958                return 1;
     3959        }
     3960
     3961        d_printf("Volume: |%s| serial number 0x%x\n",
     3962                        volname, (unsigned int)serial_num);
     3963        return 0;
     3964}
     3965
     3966/****************************************************************************
     3967 Hard link files using the NT call.
     3968****************************************************************************/
     3969
     3970static int cmd_hardlink(void)
     3971{
     3972        TALLOC_CTX *ctx = talloc_tos();
     3973        char *src, *dest;
     3974        char *buf, *buf2;
     3975        struct cli_state *targetcli;
     3976        char *targetname;
     3977        NTSTATUS status;
     3978
     3979        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
     3980            !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
     3981                d_printf("hardlink <src> <dest>\n");
     3982                return 1;
     3983        }
     3984
     3985        src = talloc_asprintf(ctx,
     3986                        "%s%s",
     3987                        client_get_cur_dir(),
     3988                        buf);
     3989        if (!src) {
     3990                return 1;
     3991        }
     3992
     3993        dest = talloc_asprintf(ctx,
     3994                        "%s%s",
     3995                        client_get_cur_dir(),
     3996                        buf2);
     3997        if (!dest) {
     3998                return 1;
     3999        }
     4000
     4001        status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
     4002                                  &targetname);
     4003        if (!NT_STATUS_IS_OK(status)) {
     4004                d_printf("hardlink %s: %s\n", src, nt_errstr(status));
     4005                return 1;
     4006        }
     4007
     4008        status = cli_nt_hardlink(targetcli, targetname, dest);
     4009        if (!NT_STATUS_IS_OK(status)) {
     4010                d_printf("%s doing an NT hard link of files\n",
     4011                         nt_errstr(status));
    37504012                return 1;
    37514013        }
     
    37944056
    37954057/****************************************************************************
     4058 Watch directory changes
     4059****************************************************************************/
     4060
     4061static int cmd_notify(void)
     4062{
     4063        TALLOC_CTX *frame = talloc_stackframe();
     4064        char *name, *buf;
     4065        NTSTATUS status;
     4066        uint16_t fnum;
     4067
     4068        name = talloc_strdup(talloc_tos(), client_get_cur_dir());
     4069        if (name == NULL) {
     4070                goto fail;
     4071        }
     4072        if (!next_token_talloc(talloc_tos(), &cmd_ptr, &buf, NULL)) {
     4073                goto usage;
     4074        }
     4075        name = talloc_asprintf_append(name, "%s", buf);
     4076        if (name == NULL) {
     4077                goto fail;
     4078        }
     4079        status = cli_ntcreate(
     4080                cli, name, 0, FILE_READ_DATA, 0,
     4081                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
     4082                FILE_OPEN, 0, 0, &fnum, NULL);
     4083        if (!NT_STATUS_IS_OK(status)) {
     4084                d_printf("Could not open file: %s\n", nt_errstr(status));
     4085                goto fail;
     4086        }
     4087
     4088        while (1) {
     4089                uint32_t i, num_changes;
     4090                struct notify_change *changes;
     4091
     4092                status = cli_notify(cli, fnum, 1000, FILE_NOTIFY_CHANGE_ALL,
     4093                                    true,
     4094                                    talloc_tos(), &num_changes, &changes);
     4095                if (!NT_STATUS_IS_OK(status)) {
     4096                        d_printf("notify returned %s\n",
     4097                                 nt_errstr(status));
     4098                        goto fail;
     4099                }
     4100                for (i=0; i<num_changes; i++) {
     4101                        printf("%4.4x %s\n", changes[i].action,
     4102                               changes[i].name);
     4103                }
     4104                TALLOC_FREE(changes);
     4105        }
     4106usage:
     4107        d_printf("notify <file>\n");
     4108fail:
     4109        TALLOC_FREE(frame);
     4110        return 1;
     4111}
     4112
     4113/****************************************************************************
    37964114 Set the archive level.
    37974115****************************************************************************/
     
    38124130
    38134131/****************************************************************************
     4132 Toggle the backup_intent state.
     4133****************************************************************************/
     4134
     4135static int cmd_backup(void)
     4136{
     4137        backup_intent = !backup_intent;
     4138        cli_set_backup_intent(cli, backup_intent);
     4139        DEBUG(2,("backup intent is now %s\n",backup_intent?"on":"off"));
     4140        return 1;
     4141}
     4142
     4143/****************************************************************************
    38144144 Toggle the lowercaseflag.
    38154145****************************************************************************/
     
    38874217                }
    38884218        }
    3889         d = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
     4219        d = sys_getwd();
    38904220        if (!d) {
    38914221                return 1;
    38924222        }
    3893         DEBUG(2,("the local directory is now %s\n",sys_getwd(d)));
     4223        DEBUG(2,("the local directory is now %s\n",d));
     4224        SAFE_FREE(d);
    38944225        return 0;
    38954226}
     
    39844315 ****************************************************************************/
    39854316
    3986 static void browse_fn(const char *name, uint32 m,
     4317static void browse_fn(const char *name, uint32_t m,
    39874318                      const char *comment, void *state)
    39884319{
     
    40274358        struct dcerpc_binding_handle *b;
    40284359
    4029         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
     4360        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc,
    40304361                                          &pipe_hnd);
    40314362
     
    40854416        }
    40864417
    4087         if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1)
    4088                 d_printf("Error returning browse list: %s\n", cli_errstr(cli));
     4418        if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1) {
     4419                NTSTATUS status = cli_nt_error(cli);
     4420                d_printf("Error returning browse list: %s\n",
     4421                         nt_errstr(status));
     4422        }
    40894423
    40904424        return (ret != -1);
     
    40954429****************************************************************************/
    40964430
    4097 static void server_fn(const char *name, uint32 m,
     4431static void server_fn(const char *name, uint32_t m,
    40984432                      const char *comment, void *state)
    40994433{
     
    41464480
    41474481        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    4148                 d_printf("Current VUID is %d\n", cli->vuid);
     4482                d_printf("Current VUID is %d\n",
     4483                         cli_state_get_uid(cli));
    41494484                return 0;
    41504485        }
    41514486
    4152         cli->vuid = atoi(buf);
     4487        cli_state_set_uid(cli, atoi(buf));
    41534488        return 0;
    41544489}
     
    41704505
    41714506        if (!next_token_talloc(ctx, &cmd_ptr,&l_password,NULL)) {
    4172                 char *pass = getpass("Password: ");
    4173                 if (pass) {
    4174                         l_password = talloc_strdup(ctx,pass);
     4507                char pwd[256] = {0};
     4508                int rc;
     4509
     4510                rc = samba_getpass("Password: ", pwd, sizeof(pwd), false, false);
     4511                if (rc == 0) {
     4512                        l_password = talloc_strdup(ctx, pwd);
    41754513                }
    41764514        }
     
    41884526        }
    41894527
    4190         d_printf("Current VUID is %d\n", cli->vuid);
     4528        d_printf("Current VUID is %d\n", cli_state_get_uid(cli));
     4529        return 0;
     4530}
     4531
     4532/**
     4533 * close the session
     4534 */
     4535
     4536static int cmd_logoff(void)
     4537{
     4538        NTSTATUS status;
     4539
     4540        status = cli_ulogoff(cli);
     4541        if (!NT_STATUS_IS_OK(status)) {
     4542                d_printf("logoff failed: %s\n", nt_errstr(status));
     4543                return -1;
     4544        }
     4545
     4546        d_printf("logoff successful\n");
     4547        return 0;
     4548}
     4549
     4550
     4551/**
     4552 * tree connect (connect to a share)
     4553 */
     4554
     4555static int cmd_tcon(void)
     4556{
     4557        TALLOC_CTX *ctx = talloc_tos();
     4558        char *sharename;
     4559        NTSTATUS status;
     4560
     4561        if (!next_token_talloc(ctx, &cmd_ptr, &sharename, NULL)) {
     4562                d_printf("tcon <sharename>\n");
     4563                return 0;
     4564        }
     4565
     4566        if (!sharename) {
     4567                return 1;
     4568        }
     4569
     4570        status = cli_tree_connect(cli, sharename, "?????", "", 0);
     4571        if (!NT_STATUS_IS_OK(status)) {
     4572                d_printf("tcon failed: %s\n", nt_errstr(status));
     4573                return -1;
     4574        }
     4575
     4576        talloc_free(sharename);
     4577
     4578        d_printf("tcon to %s successful, tid: %u\n", sharename,
     4579                 cli_state_get_tid(cli));
     4580        return 0;
     4581}
     4582
     4583/**
     4584 * tree disconnect (disconnect from a share)
     4585 */
     4586
     4587static int cmd_tdis(void)
     4588{
     4589        NTSTATUS status;
     4590
     4591        status = cli_tdis(cli);
     4592        if (!NT_STATUS_IS_OK(status)) {
     4593                d_printf("tdis failed: %s\n", nt_errstr(status));
     4594                return -1;
     4595        }
     4596
     4597        d_printf("tdis successful\n");
     4598        return 0;
     4599}
     4600
     4601
     4602/**
     4603 * get or set tid
     4604 */
     4605
     4606static int cmd_tid(void)
     4607{
     4608        TALLOC_CTX *ctx = talloc_tos();
     4609        char *tid_str;
     4610
     4611        if (!next_token_talloc(ctx, &cmd_ptr, &tid_str, NULL)) {
     4612                if (cli_state_has_tcon(cli)) {
     4613                        d_printf("current tid is %d\n", cli_state_get_tid(cli));
     4614                } else {
     4615                        d_printf("no tcon currently\n");
     4616                }
     4617        } else {
     4618                uint16_t tid = atoi(tid_str);
     4619                cli_state_set_tid(cli, tid);
     4620        }
     4621
    41914622        return 0;
    41924623}
     
    42124643        struct cli_state *targetcli;
    42134644        char *targetpath;
    4214 
    4215         if (!cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(),
    4216                                 &targetcli, &targetpath ) ) {
    4217                 d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
    4218                 return 1;
    4219         }
    4220 
    4221         d_printf("//%s/%s\n", targetcli->desthost, targetcli->share);
    4222         return 0;
     4645        NTSTATUS status;
     4646
     4647        status = cli_resolve_path(ctx, "", auth_info, cli,
     4648                                  client_get_cur_dir(), &targetcli,
     4649                                  &targetpath);
     4650        if (!NT_STATUS_IS_OK(status)) {
     4651                d_printf("showconnect %s: %s\n", cur_dir, nt_errstr(status));
     4652                return 1;
     4653        }
     4654
     4655        d_printf("//%s/%s\n", smbXcli_conn_remote_name(targetcli->conn), targetcli->share);
     4656        return 0;
     4657}
     4658
     4659/**
     4660 * set_remote_attr - set DOS attributes of a remote file
     4661 * @filename: path to the file name
     4662 * @new_attr: attribute bit mask to use
     4663 * @mode: one of ATTR_SET or ATTR_UNSET
     4664 *
     4665 * Update the file attributes with the one provided.
     4666 */
     4667int set_remote_attr(const char *filename, uint16_t new_attr, int mode)
     4668{
     4669        extern struct cli_state *cli;
     4670        uint16_t old_attr;
     4671        NTSTATUS status;
     4672
     4673        status = cli_getatr(cli, filename, &old_attr, NULL, NULL);
     4674        if (!NT_STATUS_IS_OK(status)) {
     4675                d_printf("cli_getatr failed: %s\n", nt_errstr(status));
     4676                return 1;
     4677        }
     4678
     4679        if (mode == ATTR_SET) {
     4680                new_attr |= old_attr;
     4681        } else {
     4682                new_attr = old_attr & ~new_attr;
     4683        }
     4684
     4685        status = cli_setatr(cli, filename, new_attr, 0);
     4686        if (!NT_STATUS_IS_OK(status)) {
     4687                d_printf("cli_setatr failed: %s\n", nt_errstr(status));
     4688                return 1;
     4689        }
     4690
     4691        return 0;
     4692}
     4693
     4694/**
     4695 * cmd_setmode - interactive command to set DOS attributes
     4696 *
     4697 * Read a filename and mode from the client command line and update
     4698 * the file DOS attributes.
     4699 */
     4700int cmd_setmode(void)
     4701{
     4702        const extern char *cmd_ptr;
     4703        char *buf;
     4704        char *fname = NULL;
     4705        uint16_t attr[2] = {0};
     4706        int mode = ATTR_SET;
     4707        int err = 0;
     4708        bool ok;
     4709        TALLOC_CTX *ctx = talloc_new(NULL);
     4710        if (ctx == NULL) {
     4711                return 1;
     4712        }
     4713
     4714        ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
     4715        if (!ok) {
     4716                d_printf("setmode <filename> <[+|-]rsha>\n");
     4717                err = 1;
     4718                goto out;
     4719        }
     4720
     4721        fname = talloc_asprintf(ctx,
     4722                                "%s%s",
     4723                                client_get_cur_dir(),
     4724                                buf);
     4725        if (fname == NULL) {
     4726                err = 1;
     4727                goto out;
     4728        }
     4729
     4730        while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
     4731                const char *s = buf;
     4732
     4733                while (*s) {
     4734                        switch (*s++) {
     4735                        case '+':
     4736                                mode = ATTR_SET;
     4737                                break;
     4738                        case '-':
     4739                                mode = ATTR_UNSET;
     4740                                break;
     4741                        case 'r':
     4742                                attr[mode] |= FILE_ATTRIBUTE_READONLY;
     4743                                break;
     4744                        case 'h':
     4745                                attr[mode] |= FILE_ATTRIBUTE_HIDDEN;
     4746                                break;
     4747                        case 's':
     4748                                attr[mode] |= FILE_ATTRIBUTE_SYSTEM;
     4749                                break;
     4750                        case 'a':
     4751                                attr[mode] |= FILE_ATTRIBUTE_ARCHIVE;
     4752                                break;
     4753                        default:
     4754                                d_printf("setmode <filename> <perm=[+|-]rsha>\n");
     4755                                err = 1;
     4756                                goto out;
     4757                        }
     4758                }
     4759        }
     4760
     4761        if (attr[ATTR_SET] == 0 && attr[ATTR_UNSET] == 0) {
     4762                d_printf("setmode <filename> <[+|-]rsha>\n");
     4763                err = 1;
     4764                goto out;
     4765        }
     4766
     4767        DEBUG(2, ("perm set %d %d\n", attr[ATTR_SET], attr[ATTR_UNSET]));
     4768
     4769        /* ignore return value: server might not store DOS attributes */
     4770        set_remote_attr(fname, attr[ATTR_SET], ATTR_SET);
     4771        set_remote_attr(fname, attr[ATTR_UNSET], ATTR_UNSET);
     4772out:
     4773        talloc_free(ctx);
     4774        return err;
    42234775}
    42244776
     
    42344786
    42354787        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    4236                 if (!smb_encrypt) {
    4237                         d_printf("iosize <n> or iosize 0x<n>. "
    4238                                 "Minimum is 16384 (0x4000), "
    4239                                 "max is 16776960 (0xFFFF00)\n");
     4788                if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
     4789                        if (!smb_encrypt) {
     4790                                d_printf("iosize <n> or iosize 0x<n>. "
     4791                                        "Minimum is 0 (default), "
     4792                                        "max is 16776960 (0xFFFF00)\n");
     4793                        } else {
     4794                                d_printf("iosize <n> or iosize 0x<n>. "
     4795                                        "(Encrypted connection) ,"
     4796                                        "Minimum is 0 (default), "
     4797                                        "max is 130048 (0x1FC00)\n");
     4798                        }
    42404799                } else {
    4241                         d_printf("iosize <n> or iosize 0x<n>. "
    4242                                 "(Encrypted connection) ,"
    4243                                 "Minimum is 16384 (0x4000), "
    4244                                 "max is 130048 (0x1FC00)\n");
     4800                        d_printf("iosize <n> or iosize 0x<n>.\n");
    42454801                }
    42464802                return 1;
     
    42484804
    42494805        iosize = strtol(buf,NULL,0);
    4250         if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
    4251                 d_printf("iosize out of range for encrypted "
    4252                         "connection (min = 16384 (0x4000), "
    4253                         "max = 130048 (0x1FC00)");
    4254                 return 1;
    4255         } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
    4256                 d_printf("iosize out of range (min = 16384 (0x4000), "
    4257                         "max = 16776960 (0xFFFF00)");
    4258                 return 1;
     4806        if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
     4807                if (smb_encrypt && (iosize < 0 || iosize > 0xFC00)) {
     4808                        d_printf("iosize out of range for encrypted "
     4809                                "connection (min = 0 (default), "
     4810                                "max = 130048 (0x1FC00)\n");
     4811                        return 1;
     4812                } else if (!smb_encrypt && (iosize < 0 || iosize > 0xFFFF00)) {
     4813                        d_printf("iosize out of range (min = 0 (default), "
     4814                                "max = 16776960 (0xFFFF00)\n");
     4815                        return 1;
     4816                }
    42594817        }
    42604818
     
    42634821        return 0;
    42644822}
     4823
     4824/****************************************************************************
     4825 timeout command
     4826***************************************************************************/
     4827
     4828static int cmd_timeout(void)
     4829{
     4830        TALLOC_CTX *ctx = talloc_tos();
     4831        char *buf;
     4832
     4833        if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
     4834                unsigned int old_timeout = cli_set_timeout(cli, 0);
     4835                cli_set_timeout(cli, old_timeout);
     4836                d_printf("timeout <n> (per-operation timeout "
     4837                        "in seconds - currently %u).\n",
     4838                        old_timeout/1000);
     4839                return 1;
     4840        }
     4841
     4842        io_timeout = strtol(buf,NULL,0);
     4843        cli_set_timeout(cli, io_timeout*1000);
     4844        d_printf("io_timeout per operation is now %d\n", io_timeout);
     4845        return 0;
     4846}
     4847
    42654848
    42664849/****************************************************************************
     
    43074890  {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
    43084891  {"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}},
     4892  {"backup",cmd_backup,"toggle backup intent state",{COMPL_NONE,COMPL_NONE}},
    43094893  {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
    43104894  {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
    43114895  {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
    43124896  {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
    4313   {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
    4314   {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
    4315   {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_REMOTE}},
     4897  {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_NONE}},
     4898  {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_NONE}},
     4899  {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_NONE}},
    43164900  {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
    43174901  {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
     
    43204904  {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
    43214905  {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
    4322   {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_LOCAL}},
     4906  {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_NONE}},
    43234907  {"geteas", cmd_geteas, "<file name> get the EA list of a file",
    4324    {COMPL_REMOTE, COMPL_LOCAL}},
     4908   {COMPL_REMOTE, COMPL_NONE}},
    43254909  {"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
    43264910  {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
     
    43304914  {"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
    43314915  {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
    4332   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}}, 
     4916  {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},
    43334917  {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
    43344918  {"l",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
     
    43374921  {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
    43384922  {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
    4339   {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}}, 
     4923  {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
    43404924  {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
    43414925  {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
     4926  {"notify",cmd_notify,"<file>Get notified of dir changes",{COMPL_REMOTE,COMPL_NONE}},
    43424927  {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
    43434928  {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
     
    43484933  {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
    43494934  {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
    4350   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}}, 
     4935  {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
    43514936  {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
    43524937  {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
     
    43564941  {"readlink",cmd_readlink,"filename Do a UNIX extensions readlink call on a symlink",{COMPL_REMOTE,COMPL_REMOTE}},
    43574942  {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
    4358   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}}, 
     4943  {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},
    43594944  {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
    43604945  {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
    43614946  {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
    43624947  {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
    4363   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
    4364   {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}}, 
     4948  {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_REMOTE,COMPL_NONE}},
     4949  {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}},
    43654950  {"setea", cmd_setea, "<file name> <eaname> <eaval> Set an EA of a file",
    43664951   {COMPL_REMOTE, COMPL_LOCAL}},
    4367   {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
    4368   {"stat",cmd_stat,"filename Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_REMOTE}},
     4952  {"setmode",cmd_setmode,"<file name> <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
     4953  {"scopy",cmd_scopy,"<src> <dest> server-side copy file",{COMPL_REMOTE,COMPL_REMOTE}},
     4954  {"stat",cmd_stat,"<file name> Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_NONE}},
    43694955  {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
    43704956  {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
    43714957  {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
     4958  {"timeout",cmd_timeout,"timeout <number> - set the per-operation timeout in seconds (default 20)",{COMPL_NONE,COMPL_NONE}},
    43724959  {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
    43734960  {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
     
    43784965  {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
    43794966  {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
     4967  {"tcon",cmd_tcon,"connect to a share" ,{COMPL_NONE,COMPL_NONE}},
     4968  {"tdis",cmd_tdis,"disconnect from a share",{COMPL_NONE,COMPL_NONE}},
     4969  {"tid",cmd_tid,"show or set the current tid (tree-id)",{COMPL_NONE,COMPL_NONE}},
     4970  {"logoff",cmd_logoff,"log off (close the session)",{COMPL_NONE,COMPL_NONE}},
    43804971  {"..",cmd_cd_oneup,"change the remote directory (up one level)",{COMPL_REMOTE,COMPL_NONE}},
    43814972
     
    44585049
    44595050        if (!cli) {
    4460                 cli = cli_cm_open(talloc_tos(), NULL,
    4461                                 have_ip ? dest_ss_str : desthost,
    4462                                 service, auth_info,
    4463                                 true, smb_encrypt,
    4464                                 max_protocol, port, name_type);
    4465                 if (!cli) {
     5051                NTSTATUS status;
     5052
     5053                status = cli_cm_open(talloc_tos(), NULL,
     5054                                     have_ip ? dest_ss_str : desthost,
     5055                                     service, auth_info,
     5056                                     true, smb_encrypt,
     5057                                     max_protocol, port, name_type,
     5058                                     &cli);
     5059                if (!NT_STATUS_IS_OK(status)) {
    44665060                        return 1;
    44675061                }
     5062                cli_set_timeout(cli, io_timeout*1000);
    44685063        }
    44695064
     
    46385233        }
    46395234
    4640         if (!cli_resolve_path(ctx, "", auth_info, cli, dirmask, &targetcli, &targetpath)) {
     5235        status = cli_resolve_path(ctx, "", auth_info, cli, dirmask, &targetcli,
     5236                                  &targetpath);
     5237        if (!NT_STATUS_IS_OK(status)) {
    46415238                goto cleanup;
    46425239        }
     
    46765273        info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
    46775274        info.matches[info.count] = NULL;
     5275        TALLOC_FREE(ctx);
    46785276        return info.matches;
    46795277
     
    47885386        struct timespec now;
    47895387        time_t t;
    4790         int ret, revents;
     5388        NTSTATUS status;
     5389        unsigned char garbage[16];
    47915390
    47925391        clock_gettime_mono(&now);
     
    47985397        last_t = t;
    47995398
    4800  again:
    4801 
    4802         if (cli->fd == -1)
     5399        /* Ping the server to keep the connection alive using SMBecho. */
     5400        memset(garbage, 0xf0, sizeof(garbage));
     5401        status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
     5402        if (NT_STATUS_IS_OK(status)) {
    48035403                return;
    4804 
    4805         /* We deliberately use receive_smb_raw instead of
    4806            client_receive_smb as we want to receive
    4807            session keepalives and then drop them here.
    4808         */
    4809 
    4810         ret = poll_intr_one_fd(cli->fd, POLLIN|POLLHUP, 0, &revents);
    4811 
    4812         if ((ret > 0) && (revents & (POLLIN|POLLHUP|POLLERR))) {
    4813                 NTSTATUS status;
    4814                 size_t len;
    4815 
    4816                 set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
    4817 
    4818                 status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, 0, 0, &len);
    4819 
    4820                 if (!NT_STATUS_IS_OK(status)) {
    4821                         DEBUG(0, ("Read from server failed, maybe it closed "
    4822                                   "the connection\n"));
    4823 
    4824                         finished = true;
    4825                         smb_readline_done();
    4826                         if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
    4827                                 set_smb_read_error(&cli->smb_rw_error,
    4828                                                    SMB_READ_EOF);
    4829                                 return;
    4830                         }
    4831 
    4832                         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
    4833                                 set_smb_read_error(&cli->smb_rw_error,
    4834                                                    SMB_READ_TIMEOUT);
    4835                                 return;
    4836                         }
    4837 
    4838                         set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
    4839                         return;
    4840                 }
    4841                 if(CVAL(cli->inbuf,0) != SMBkeepalive) {
    4842                         DEBUG(0, ("Read from server "
    4843                                 "returned unexpected packet!\n"));
    4844                         return;
    4845                 }
    4846 
    4847                 goto again;
    4848         }
    4849 
    4850         /* Ping the server to keep the connection alive using SMBecho. */
    4851         {
    4852                 NTSTATUS status;
    4853                 unsigned char garbage[16];
    4854                 memset(garbage, 0xf0, sizeof(garbage));
    4855                 status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
    4856 
    4857                 if (NT_STATUS_IS_OK(status)) {
    4858                         return;
    4859                 }
    4860 
    4861                 if (!cli_state_is_connected(cli)) {
    4862                         DEBUG(0, ("SMBecho failed (%s). The connection is "
    4863                                 "disconnected now\n", nt_errstr(status)));
    4864                         finished = true;
    4865                         smb_readline_done();
    4866                 }
     5404        }
     5405
     5406        if (!cli_state_is_connected(cli)) {
     5407                DEBUG(0,("SMBecho failed (%s). The connection is "
     5408                         "disconnected now\n", nt_errstr(status)));
     5409                finished = true;
     5410                smb_readline_done();
    48675411        }
    48685412}
     
    49345478{
    49355479        int rc = 0;
    4936 
    4937         cli = cli_cm_open(talloc_tos(), NULL,
    4938                         have_ip ? dest_ss_str : desthost,
    4939                         service, auth_info, true, smb_encrypt,
    4940                         max_protocol, port, name_type);
    4941         if (!cli) {
    4942                 return 1;
    4943         }
     5480        NTSTATUS status;
     5481
     5482        status = cli_cm_open(talloc_tos(), NULL,
     5483                             have_ip ? dest_ss_str : desthost,
     5484                             service, auth_info, true, smb_encrypt,
     5485                             max_protocol, port, name_type, &cli);
     5486        if (!NT_STATUS_IS_OK(status)) {
     5487                return 1;
     5488        }
     5489
     5490        cli_set_timeout(cli, io_timeout*1000);
    49445491
    49455492        if (base_directory && *base_directory) {
     
    49675514static int do_host_query(const char *query_host)
    49685515{
    4969         cli = cli_cm_open(talloc_tos(), NULL,
    4970                         have_ip ? dest_ss_str : query_host, "IPC$", auth_info, true, smb_encrypt,
    4971                         max_protocol, port, name_type);
    4972         if (!cli)
    4973                 return 1;
    4974 
     5516        NTSTATUS status;
     5517
     5518        status = cli_cm_open(talloc_tos(), NULL,
     5519                             have_ip ? dest_ss_str : query_host,
     5520                             "IPC$", auth_info, true, smb_encrypt,
     5521                             max_protocol, port, name_type, &cli);
     5522        if (!NT_STATUS_IS_OK(status)) {
     5523                return 1;
     5524        }
     5525
     5526        cli_set_timeout(cli, io_timeout*1000);
    49755527        browse_host(true);
    49765528
     
    49875539        }
    49885540
    4989         if (port != 139) {
     5541        if (port != NBT_SMB_PORT) {
    49905542
    49915543                /* Workgroups simply don't make sense over anything
     
    49935545
    49945546                cli_shutdown(cli);
    4995                 cli = cli_cm_open(talloc_tos(), NULL,
    4996                                 have_ip ? dest_ss_str : query_host, "IPC$",
    4997                                 auth_info, true, smb_encrypt,
    4998                                 max_protocol, 139, name_type);
     5547                status = cli_cm_open(talloc_tos(), NULL,
     5548                                     have_ip ? dest_ss_str : query_host,
     5549                                     "IPC$", auth_info, true, smb_encrypt,
     5550                                     max_protocol, NBT_SMB_PORT, name_type,
     5551                                     &cli);
     5552                if (!NT_STATUS_IS_OK(status)) {
     5553                        cli = NULL;
     5554                }
    49995555        }
    50005556
    50015557        if (cli == NULL) {
    50025558                d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
    5003                 return 1;
    5004         }
    5005 
     5559                return 0;
     5560        }
     5561
     5562        cli_set_timeout(cli, io_timeout*1000);
    50065563        list_servers(lp_workgroup());
    50075564
     
    50175574static int do_tar_op(const char *base_directory)
    50185575{
    5019         int ret;
     5576        struct tar *tar_ctx = tar_get_ctx();
     5577        int ret = 0;
    50205578
    50215579        /* do we already have a connection? */
    50225580        if (!cli) {
    5023                 cli = cli_cm_open(talloc_tos(), NULL,
    5024                         have_ip ? dest_ss_str : desthost,
    5025                         service, auth_info, true, smb_encrypt,
    5026                         max_protocol, port, name_type);
    5027                 if (!cli)
    5028                         return 1;
    5029         }
    5030 
    5031         recurse=true;
     5581                NTSTATUS status;
     5582
     5583                status = cli_cm_open(talloc_tos(), NULL,
     5584                                     have_ip ? dest_ss_str : desthost,
     5585                                     service, auth_info, true, smb_encrypt,
     5586                                     max_protocol, port, name_type, &cli);
     5587                if (!NT_STATUS_IS_OK(status)) {
     5588            ret = 1;
     5589            goto out;
     5590                }
     5591                cli_set_timeout(cli, io_timeout*1000);
     5592        }
     5593
     5594        recurse = true;
    50325595
    50335596        if (base_directory && *base_directory)  {
    50345597                ret = do_cd(base_directory);
    50355598                if (ret) {
    5036                         cli_shutdown(cli);
    5037                         return ret;
    5038                 }
    5039         }
    5040 
    5041         ret=process_tar();
    5042 
     5599            goto out_cli;
     5600                }
     5601        }
     5602
     5603        ret = tar_process(tar_ctx);
     5604
     5605 out_cli:
    50435606        cli_shutdown(cli);
    5044 
    5045         return(ret);
     5607 out:
     5608        return ret;
    50465609}
    50475610
     
    50525615static int do_message_op(struct user_auth_info *a_info)
    50535616{
    5054         struct sockaddr_storage ss;
    5055         struct nmb_name called, calling;
    5056         fstring server_name;
    5057         char name_type_hex[10];
    5058         int msg_port;
    50595617        NTSTATUS status;
    50605618
    5061         make_nmb_name(&calling, calling_name, 0x0);
    5062         make_nmb_name(&called , desthost, name_type);
    5063 
    5064         fstrcpy(server_name, desthost);
    5065         snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
    5066         fstrcat(server_name, name_type_hex);
    5067 
    5068         zero_sockaddr(&ss);
    5069         if (have_ip)
    5070                 ss = dest_ss;
    5071 
    5072         /* we can only do messages over port 139 (to windows clients at least) */
    5073 
    5074         msg_port = port ? port : 139;
    5075 
    5076         if (!(cli=cli_initialise())) {
    5077                 d_printf("Connection to %s failed\n", desthost);
    5078                 return 1;
    5079         }
    5080         cli_set_port(cli, msg_port);
    5081 
    5082         status = cli_connect(cli, server_name, &ss);
     5619        status = cli_connect_nb(desthost, have_ip ? &dest_ss : NULL,
     5620                                port ? port : NBT_SMB_PORT, name_type,
     5621                                lp_netbios_name(), SMB_SIGNING_DEFAULT, 0, &cli);
    50835622        if (!NT_STATUS_IS_OK(status)) {
    50845623                d_printf("Connection to %s failed. Error %s\n", desthost, nt_errstr(status));
     
    50865625        }
    50875626
    5088         if (!cli_session_request(cli, &calling, &called)) {
    5089                 d_printf("session request failed\n");
    5090                 cli_shutdown(cli);
    5091                 return 1;
    5092         }
    5093 
     5627        cli_set_timeout(cli, io_timeout*1000);
    50945628        send_message(get_cmdline_auth_info_username(a_info));
    50955629        cli_shutdown(cli);
     
    51025636****************************************************************************/
    51035637
    5104  int main(int argc,char *argv[])
    5105 {
     5638int main(int argc,char *argv[])
     5639{
     5640        const char **const_argv = discard_const_p(const char *, argv);
    51065641        char *base_directory = NULL;
    51075642        int opt;
     
    51125647        char *p;
    51135648        int rc = 0;
    5114         fstring new_workgroup;
    51155649        bool tar_opt = false;
    51165650        bool service_opt = false;
     5651        struct tar *tar_ctx = tar_get_ctx();
     5652
    51175653        struct poptOption long_options[] = {
    51185654                POPT_AUTOHELP
     
    51265662                { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "<c|x>IXFqgbNan" },
    51275663                { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
    5128                 { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, 
     5664                { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" },
    51295665                { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
     5666                { "timeout", 't', POPT_ARG_INT, &io_timeout, 'b', "Changes the per-operation timeout", "SECONDS" },
    51305667                { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
    51315668                { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
     
    51425679        }
    51435680
    5144         /* initialize the workgroup name so we can determine whether or
    5145            not it was set by a command line option */
    5146 
    5147         set_global_myworkgroup( "" );
    5148         set_global_myname( "" );
    5149 
    51505681        /* set default debug level to 1 regardless of what smb.conf sets */
    51515682        setup_logging( "smbclient", DEBUG_DEFAULT_STDERR );
    5152         load_case_tables();
     5683        smb_init_locale();
    51535684
    51545685        lp_set_cmdline("log level", "1");
     
    51615692
    51625693        /* skip argv(0) */
    5163         pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
     5694        pc = poptGetContext("smbclient", argc, const_argv, long_options, 0);
    51645695        poptSetOtherOptionHelp(pc, "service <password>");
    5165 
    5166         lp_set_in_client(true); /* Make sure that we tell lp_load we are */
    51675696
    51685697        while ((opt = poptGetNextOpt(pc)) != -1) {
     
    51935722                                                       poptGetArg(pc));
    51945723                }
     5724
    51955725
    51965726                switch (opt) {
     
    52065736                        }
    52075737                        if( !port )
    5208                                 port = 139;
     5738                                port = NBT_SMB_PORT;
    52095739                        message = true;
    52105740                        break;
     
    52305760                        break;
    52315761                case 'm':
    5232                         max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol);
     5762                        lp_set_cmdline("client max protocol", poptGetOptArg(pc));
    52335763                        break;
    52345764                case 'T':
     
    52375767                        {
    52385768                                int i;
     5769
    52395770                                for (i = 1; i < argc; i++) {
    52405771                                        if (strncmp("-T", argv[i],2)==0)
     
    52425773                                }
    52435774                                i++;
    5244                                 if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
     5775                                if (tar_parse_args(tar_ctx, poptGetOptArg(pc),
     5776                                                   const_argv + i, argc - i)) {
    52455777                                        poptPrintUsage(pc, stderr, 0);
    52465778                                        exit(1);
     
    52935825        }
    52945826
    5295         /* save the workgroup...
    5296 
    5297            FIXME!! do we need to do this for other options as well
    5298            (or maybe a generic way to keep lp_load() from overwriting
    5299            everything)?  */
    5300 
    5301         fstrcpy( new_workgroup, lp_workgroup() );
    5302         calling_name = talloc_strdup(frame, global_myname() );
    5303         if (!calling_name) {
    5304                 exit(ENOMEM);
    5305         }
    5306 
    53075827        if ( override_logfile )
    5308                 setup_logging( lp_logfile(), DEBUG_FILE );
    5309 
    5310         if (!lp_load(get_dyn_CONFIGFILE(),true,false,false,true)) {
     5828                setup_logging( lp_logfile(talloc_tos()), DEBUG_FILE );
     5829
     5830        if (!lp_load_client(get_dyn_CONFIGFILE())) {
    53115831                fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
    53125832                        argv[0], get_dyn_CONFIGFILE());
     
    53385858        }
    53395859
    5340         if ( strlen(new_workgroup) != 0 ) {
    5341                 set_global_myworkgroup( new_workgroup );
    5342         }
    5343 
    5344         if ( strlen(calling_name) != 0 ) {
    5345                 set_global_myname( calling_name );
    5346         } else {
    5347                 TALLOC_FREE(calling_name);
    5348                 calling_name = talloc_strdup(frame, global_myname() );
    5349         }
    5350 
    53515860        smb_encrypt = get_cmdline_auth_info_smb_encrypt(auth_info);
    53525861        if (!init_names()) {
     
    53565865
    53575866        if(new_name_resolve_order)
    5358                 lp_set_name_resolve_order(new_name_resolve_order);
    5359 
    5360         if (!tar_type && !query_host && !service && !message) {
     5867                lp_set_cmdline("name resolve order", new_name_resolve_order);
     5868
     5869        if (!tar_to_process(tar_ctx) && !query_host && !service && !message) {
    53615870                poptPrintUsage(pc, stderr, 0);
    53625871                exit(1);
     
    53645873
    53655874        poptFreeContext(pc);
     5875        popt_burn_cmdline_password(argc, argv);
    53665876
    53675877        DEBUG(3,("Client started (version %s).\n", samba_version_string()));
     
    53705880        set_cmdline_auth_info_getpass(auth_info);
    53715881
    5372         if (tar_type) {
     5882        max_protocol = lp_client_max_protocol();
     5883
     5884        if (tar_to_process(tar_ctx)) {
    53735885                if (cmdstr)
    53745886                        process_command_string(cmdstr);
    5375                 return do_tar_op(base_directory);
    5376         }
    5377 
    5378         if (query_host && *query_host) {
     5887                rc = do_tar_op(base_directory);
     5888        } else if (query_host && *query_host) {
    53795889                char *qhost = query_host;
    53805890                char *slash;
     
    53945904                }
    53955905
    5396                 return do_host_query(qhost);
    5397         }
    5398 
    5399         if (message) {
    5400                 return do_message_op(auth_info);
    5401         }
    5402 
    5403         if (process(base_directory)) {
    5404                 return 1;
     5906                rc = do_host_query(qhost);
     5907        } else if (message) {
     5908                rc = do_message_op(auth_info);
     5909        } else if (process(base_directory)) {
     5910                rc = 1;
    54055911        }
    54065912
  • vendor/current/source3/client/client_proto.h

    r740 r988  
    2727struct file_info;
    2828
     29enum {
     30        ATTR_UNSET,
     31        ATTR_SET,
     32};
     33
    2934/* The following definitions come from client/client.c  */
    3035
     
    3237const char *client_set_cur_dir(const char *newdir);
    3338NTSTATUS do_list(const char *mask,
    34                         uint16 attribute,
     39                        uint16_t attribute,
    3540                        NTSTATUS (*fn)(struct cli_state *cli_state, struct file_info *,
    3641                                   const char *dir),
    3742                        bool rec,
    3843                        bool dirs);
     44int set_remote_attr(const char *filename, uint16_t new_attr, int mode);
    3945int cmd_iosize(void);
    40 
    41 /* The following definitions come from client/clitar.c  */
    42 
    43 int cmd_block(void);
    44 int cmd_tarmode(void);
    45 int cmd_setmode(void);
    46 int cmd_tar(void);
    47 int process_tar(void);
    48 int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind);
    4946
    5047/* The following definitions come from client/dnsbrowse.c  */
  • vendor/current/source3/client/clitar.c

    r746 r988  
    11/*
    22   Unix SMB/CIFS implementation.
    3    Tar Extensions
    4    Copyright (C) Ricky Poulten 1995-1998
    5    Copyright (C) Richard Sharpe 1998
     3   Tar backup command extension
     4   Copyright (C) Aurélien Aptel 2013
    65
    76   This program is free software; you can redistribute it and/or modify
     
    1817   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1918*/
    20 /* The following changes developed by Richard Sharpe for Canon Information
    21    Systems Research Australia (CISRA)
    22 
    23    1. Restore can now restore files with long file names
    24    2. Save now saves directory information so that we can restore
    25       directory creation times
    26    3. tar now accepts both UNIX path names and DOS path names. I prefer
    27       those lovely /'s to those UGLY \'s :-)
    28    4. the files to exclude can be specified as a regular expression by adding
    29       an r flag to the other tar flags. Eg:
    30 
    31          -TcrX file.tar "*.(obj|exe)"
    32 
    33       will skip all .obj and .exe files
    34 */
    35 
     19
     20/**
     21 * # General overview of the tar extension
     22 *
     23 * All tar_xxx() functions work on a `struct tar` which store most of
     24 * the context of the backup process.
     25 *
     26 * The current tar context can be accessed via the global variable
     27 * `tar_ctx`. It's publicly exported as an opaque handle via
     28 * tar_get_ctx().
     29 *
     30 * A tar context is first configured through tar_parse_args() which
     31 * can be called from either the CLI (in client.c) or the interactive
     32 * session (via the cmd_tar() callback).
     33 *
     34 * Once the configuration is done (successfully), the context is ready
     35 * for processing and tar_to_process() returns true.
     36 *
     37 * The next step is to call tar_process() which dispatch the
     38 * processing to either tar_create() or tar_extract(), depending on
     39 * the context.
     40 *
     41 * ## Archive creation
     42 *
     43 * tar_create() creates an archive using the libarchive API then
     44 *
     45 * - iterates on the requested paths if the context is in inclusion
     46 *   mode with tar_create_from_list()
     47 *
     48 * - or iterates on the whole share (starting from the current dir) if
     49 *   in exclusion mode or if no specific path were requested
     50 *
     51 * The do_list() function from client.c is used to list recursively
     52 * the share. In particular it takes a DOS path mask (eg. \mydir\*)
     53 * and a callback function which will be called with each file name
     54 * and attributes. The tar callback function is get_file_callback().
     55 *
     56 * The callback function checks whether the file should be skipped
     57 * according the the configuration via tar_create_skip_path(). If it's
     58 * not skipped it's downloaded and written to the archive in
     59 * tar_get_file().
     60 *
     61 * ## Archive extraction
     62 *
     63 * tar_extract() opens the archive and iterates on each file in
     64 * it. For each file tar_extract_skip_path() checks whether it should
     65 * be skipped according to the config. If it's not skipped it's
     66 * uploaded on the server in tar_send_file().
     67 */
    3668
    3769#include "includes.h"
    3870#include "system/filesys.h"
    39 #include "clitar.h"
    4071#include "client/client_proto.h"
     72#include "client/clitar_proto.h"
    4173#include "libsmb/libsmb.h"
    4274
    43 static int clipfind(char **aret, int ret, char *tok);
    44 
    45 typedef struct file_info_struct file_info2;
    46 
    47 struct file_info_struct {
    48         SMB_OFF_T size;
    49         uint16 mode;
    50         uid_t uid;
    51         gid_t gid;
    52         /* These times are normally kept in GMT */
    53         struct timespec mtime_ts;
    54         struct timespec atime_ts;
    55         struct timespec ctime_ts;
    56         char *name;     /* This is dynamically allocated */
    57         file_info2 *next, *prev;  /* Used in the stack ... */
     75#ifdef HAVE_LIBARCHIVE
     76
     77#include <archive.h>
     78#include <archive_entry.h>
     79
     80/* prepend module name and line number to debug messages */
     81#define DBG(a, b) (DEBUG(a, ("tar:%-4d ", __LINE__)), DEBUG(a, b))
     82
     83/* preprocessor magic to stringify __LINE__ (int) */
     84#define STR1(x) #x
     85#define STR2(x) STR1(x)
     86
     87/**
     88 * Number of byte in a block unit.
     89 */
     90#define TAR_BLOCK_UNIT 512
     91
     92/**
     93 * Default tar block size in TAR_BLOCK_UNIT.
     94 */
     95#define TAR_DEFAULT_BLOCK_SIZE 20
     96
     97/**
     98 * Maximum value for the blocksize field
     99 */
     100#define TAR_MAX_BLOCK_SIZE 0xffff
     101
     102/**
     103 * Size of the buffer used when downloading a file
     104 */
     105#define TAR_CLI_READ_SIZE 0xff00
     106
     107#define TAR_DO_LIST_ATTR (FILE_ATTRIBUTE_DIRECTORY \
     108                          | FILE_ATTRIBUTE_SYSTEM  \
     109                          | FILE_ATTRIBUTE_HIDDEN)
     110
     111
     112enum tar_operation {
     113        TAR_NO_OPERATION,
     114        TAR_CREATE,    /* c flag */
     115        TAR_EXTRACT,   /* x flag */
    58116};
    59117
    60 typedef struct {
    61         file_info2 *top;
    62         int items;
    63 } stack;
    64 
    65 #define SEPARATORS " \t\n\r"
    66 extern time_t newer_than;
    67 extern struct cli_state *cli;
    68 
    69 /* These defines are for the do_setrattr routine, to indicate
    70  * setting and reseting of file attributes in the function call */
    71 #define ATTRSET 1
    72 #define ATTRRESET 0
    73 
    74 static uint16 attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
    75 
    76 #ifndef CLIENT_TIMEOUT
    77 #define CLIENT_TIMEOUT (30*1000)
    78 #endif
    79 
    80 static char *tarbuf, *buffer_p;
    81 static int tp, ntarf, tbufsiz;
    82 static double ttarf;
    83 /* Incremental mode */
    84 static bool tar_inc=False;
    85 /* Reset archive bit */
    86 static bool tar_reset=False;
    87 /* Include / exclude mode (true=include, false=exclude) */
    88 static bool tar_excl=True;
    89 /* use regular expressions for search on file names */
    90 static bool tar_re_search=False;
    91 /* Do not dump anything, just calculate sizes */
    92 static bool dry_run=False;
    93 /* Dump files with System attribute */
    94 static bool tar_system=True;
    95 /* Dump files with Hidden attribute */
    96 static bool tar_hidden=True;
    97 /* Be noisy - make a catalogue */
    98 static bool tar_noisy=True;
    99 static bool tar_real_noisy=False;  /* Don't want to be really noisy by default */
    100 
    101 char tar_type='\0';
    102 static char **cliplist=NULL;
    103 static int clipn=0;
    104 static bool must_free_cliplist = False;
    105 extern const char *cmd_ptr;
    106 
    107 extern bool lowercase;
    108 extern uint16 cnum;
    109 extern bool readbraw_supported;
    110 extern int max_xmit;
    111 extern int get_total_time_ms;
    112 extern int get_total_size;
    113 
    114 static int blocksize=20;
    115 static int tarhandle;
    116 
    117 static void writetarheader(int f,  const char *aname, uint64_t size, time_t mtime,
    118                            const char *amode, unsigned char ftype);
    119 static NTSTATUS do_atar(const char *rname_in, char *lname,
    120                     struct file_info *finfo1);
    121 static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo,
    122                    const char *dir);
    123 static void oct_it(uint64_t value, int ndgs, char *p);
    124 static void fixtarname(char *tptr, const char *fp, size_t l);
    125 static int dotarbuf(int f, char *b, int n);
    126 static void dozerobuf(int f, int n);
    127 static void dotareof(int f);
    128 static void initarbuf(void);
    129 
    130 /* restore functions */
    131 static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefix);
    132 static long unoct(char *p, int ndgs);
    133 static void do_tarput(void);
    134 static void unfixtarname(char *tptr, char *fp, int l, bool first);
    135 
    136 /*
    137  * tar specific utitlities
    138  */
    139 
    140 /*******************************************************************
    141 Create  a string of size size+1 (for the null)
    142 *******************************************************************/
    143 
    144 static char *string_create_s(int size)
    145 {
    146         char *tmp;
    147 
    148         tmp = (char *)SMB_MALLOC(size+1);
    149 
    150         if (tmp == NULL) {
    151                 DEBUG(0, ("Out of memory in string_create_s\n"));
    152         }
    153 
    154         return(tmp);
    155 }
    156 
    157 /****************************************************************************
    158 Write a tar header to buffer
    159 ****************************************************************************/
    160 
    161 static void writetarheader(int f, const char *aname, uint64_t size, time_t mtime,
    162                            const char *amode, unsigned char ftype)
    163 {
    164         union hblock hb;
    165         int i, chk, l;
    166         char *jp;
    167 
    168         DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname));
    169 
    170         memset(hb.dummy, 0, sizeof(hb.dummy));
    171 
    172         l=strlen(aname);
    173         /* We will be prepending a '.' in fixtarheader so use +2 to
    174          * take care of the . and terminating zero. JRA.
    175          */
    176         if (l+2 >= NAMSIZ) {
    177                 /* write a GNU tar style long header */
    178                 char *b;
    179                 b = (char *)SMB_MALLOC(l+TBLOCK+100);
    180                 if (!b) {
    181                         DEBUG(0,("out of memory\n"));
    182                         exit(1);
    183                 }
    184                 writetarheader(f, "/./@LongLink", l+2, 0, "     0 \0", 'L');
    185                 memset(b, 0, l+TBLOCK+100);
    186                 fixtarname(b, aname, l+2);
    187                 i = strlen(b)+1;
    188                 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b)));
    189                 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
    190                 SAFE_FREE(b);
    191         }
    192 
    193         fixtarname(hb.dbuf.name, aname, (l+2 >= NAMSIZ) ? NAMSIZ : l + 2);
    194 
    195         if (lowercase)
    196                 strlower_m(hb.dbuf.name);
    197 
    198         /* write out a "standard" tar format header */
    199 
    200         hb.dbuf.name[NAMSIZ-1]='\0';
    201         safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1);
    202         oct_it((uint64_t)0, 8, hb.dbuf.uid);
    203         oct_it((uint64_t)0, 8, hb.dbuf.gid);
    204         oct_it((uint64_t) size, 13, hb.dbuf.size);
    205         if (size > (uint64_t)077777777777LL) {
    206                 /* This is a non-POSIX compatible extention to store files
    207                         greater than 8GB. */
    208 
    209                 memset(hb.dbuf.size, 0, 4);
    210                 hb.dbuf.size[0]=128;
    211                 for (i = 8; i; i--) {
    212                         hb.dbuf.size[i+3] = size & 0xff;
    213                         size >>= 8;
    214                 }
    215         }
    216         oct_it((uint64_t) mtime, 13, hb.dbuf.mtime);
    217         memcpy(hb.dbuf.chksum, "        ", sizeof(hb.dbuf.chksum));
    218         memset(hb.dbuf.linkname, 0, NAMSIZ);
    219         hb.dbuf.linkflag=ftype;
    220 
    221         for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;)
    222                 chk+=(0xFF & *jp++);
    223 
    224         oct_it((uint64_t) chk, 8, hb.dbuf.chksum);
    225         hb.dbuf.chksum[6] = '\0';
    226 
    227         (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
    228 }
    229 
    230 /****************************************************************************
    231 Read a tar header into a hblock structure, and validate
    232 ***************************************************************************/
    233 
    234 static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefix)
    235 {
    236         long chk, fchk;
     118enum tar_selection {
     119        TAR_NO_SELECTION,
     120        TAR_INCLUDE,       /* I and F flag, default */
     121        TAR_EXCLUDE,       /* X flag */
     122};
     123
     124struct tar {
     125        TALLOC_CTX *talloc_ctx;
     126
     127        /* in state that needs/can be processed? */
     128        bool to_process;
     129
     130        /* flags */
     131        struct tar_mode {
     132                enum tar_operation operation; /* create, extract */
     133                enum tar_selection selection; /* include, exclude */
     134                int blocksize;    /* size in TAR_BLOCK_UNIT of a tar file block */
     135                bool hidden;      /* backup hidden file? */
     136                bool system;      /* backup system file? */
     137                bool incremental; /* backup _only_ archived file? */
     138                bool reset;       /* unset archive bit? */
     139                bool dry;         /* don't write tar file? */
     140                bool regex;       /* XXX: never actually using regex... */
     141                bool verbose;     /* XXX: ignored */
     142        } mode;
     143
     144        /* nb of bytes received */
     145        uint64_t total_size;
     146
     147        /* path to tar archive name */
     148        char *tar_path;
     149
     150        /* list of path to include or exclude */
     151        char **path_list;
     152        int path_list_size;
     153
     154        /* archive handle */
     155        struct archive *archive;
     156};
     157
     158/**
     159 * Global context imported in client.c when needed.
     160 *
     161 * Default options.
     162 */
     163struct tar tar_ctx = {
     164        .mode.selection   = TAR_INCLUDE,
     165        .mode.blocksize   = TAR_DEFAULT_BLOCK_SIZE,
     166        .mode.hidden      = true,
     167        .mode.system      = true,
     168        .mode.incremental = false,
     169        .mode.reset       = false,
     170        .mode.dry         = false,
     171        .mode.regex       = false,
     172        .mode.verbose     = false,
     173};
     174
     175/* tar, local function */
     176static int tar_create(struct tar* t);
     177static int tar_create_from_list(struct tar *t);
     178static int tar_extract(struct tar *t);
     179static int tar_read_inclusion_file(struct tar *t, const char* filename);
     180static int tar_send_file(struct tar *t, struct archive_entry *entry);
     181static int tar_set_blocksize(struct tar *t, int size);
     182static int tar_set_newer_than(struct tar *t, const char *filename);
     183static NTSTATUS tar_add_selection_path(struct tar *t, const char *path);
     184static void tar_dump(struct tar *t);
     185static NTSTATUS tar_extract_skip_path(struct tar *t,
     186                                      struct archive_entry *entry,
     187                                      bool *_skip);
     188static TALLOC_CTX *tar_reset_mem_context(struct tar *t);
     189static void tar_free_mem_context(struct tar *t);
     190static NTSTATUS tar_create_skip_path(struct tar *t,
     191                                     const char *fullpath,
     192                                     const struct file_info *finfo,
     193                                     bool *_skip);
     194
     195static NTSTATUS tar_path_in_list(struct tar *t, const char *path,
     196                                 bool reverse, bool *_is_in_list);
     197
     198static int tar_get_file(struct tar *t,
     199                        const char *full_dos_path,
     200                        struct file_info *finfo);
     201
     202static NTSTATUS get_file_callback(struct cli_state *cli,
     203                                  struct file_info *finfo,
     204                                  const char *dir);
     205
     206/* utilities */
     207static char *fix_unix_path(char *path, bool removeprefix);
     208static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base);
     209static const char* skip_useless_char_in_path(const char *p);
     210static int make_remote_path(const char *full_path);
     211static int max_token (const char *str);
     212static NTSTATUS is_subpath(const char *sub, const char *full,
     213                           bool *_subpath_match);
     214
     215/**
     216 * tar_get_ctx - retrieve global tar context handle
     217 */
     218struct tar *tar_get_ctx()
     219{
     220        return &tar_ctx;
     221}
     222
     223/**
     224 * cmd_block - interactive command to change tar blocksize
     225 *
     226 * Read a size from the client command line and update the current
     227 * blocksize.
     228 */
     229int cmd_block(void)
     230{
     231        /* XXX: from client.c */
     232        const extern char *cmd_ptr;
     233        char *buf;
     234        int err = 0;
     235        bool ok;
     236        TALLOC_CTX *ctx = talloc_new(NULL);
     237        if (ctx == NULL) {
     238                return 1;
     239        }
     240
     241        ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
     242        if (!ok) {
     243                DBG(0, ("blocksize <n>\n"));
     244                err = 1;
     245                goto out;
     246        }
     247
     248        ok = tar_set_blocksize(&tar_ctx, atoi(buf));
     249        if (ok) {
     250                DBG(0, ("invalid blocksize\n"));
     251                err = 1;
     252                goto out;
     253        }
     254
     255        DBG(2, ("blocksize is now %d\n", tar_ctx.mode.blocksize));
     256
     257out:
     258        talloc_free(ctx);
     259        return err;
     260}
     261
     262/**
     263 * cmd_tarmode - interactive command to change tar behaviour
     264 *
     265 * Read one or more modes from the client command line and update the
     266 * current tar mode.
     267 */
     268int cmd_tarmode(void)
     269{
     270        const extern char *cmd_ptr;
     271        char *buf;
    237272        int i;
    238         char *jp;
    239 
    240         /*
    241          * read in a "standard" tar format header - we're not that interested
    242          * in that many fields, though
    243          */
    244 
    245         /* check the checksum */
    246         for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;)
    247                 chk+=(0xFF & *jp++);
    248 
    249         if (chk == 0)
    250                 return chk;
    251 
    252         /* compensate for blanks in chksum header */
    253         for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
    254                 chk-=(0xFF & *jp++);
    255 
    256         chk += ' ' * sizeof(hb->dbuf.chksum);
    257 
    258         fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
    259 
    260         DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
    261                         chk, fchk, hb->dbuf.chksum));
    262 
    263         if (fchk != chk) {
    264                 DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk));
    265                 dump_data(5, (uint8 *)hb - TBLOCK, TBLOCK *3);
    266                 return -1;
    267         }
    268 
    269         if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
    270                 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
    271                 return(-1);
    272         }
    273 
    274         safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3);
    275 
    276         /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
    277         unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
    278                 strlen(hb->dbuf.name) + 1, True);
    279 
    280         /* can't handle some links at present */
    281         if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
    282                 if (hb->dbuf.linkflag == 0) {
    283                         DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
    284                                 finfo->name));
    285                 } else {
    286                         if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
    287                                 /* Do nothing here at the moment. do_tarput will handle this
    288                                         as long as the longlink gets back to it, as it has to advance
    289                                         the buffer pointer, etc */
    290                         } else {
    291                                 DEBUG(0, ("this tar file appears to contain some kind \
    292 of link other than a GNUtar Longlink - ignoring\n"));
    293                                 return -2;
    294                         }
    295                 }
    296         }
    297 
    298         if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) ||
    299                                 (*(finfo->name+strlen(finfo->name)-1) == '\\')) {
    300                 finfo->mode=FILE_ATTRIBUTE_DIRECTORY;
    301         } else {
    302                 finfo->mode=0; /* we don't care about mode at the moment, we'll
    303                                 * just make it a regular file */
    304         }
    305 
    306         /*
    307          * Bug fix by richard@sj.co.uk
    308          *
    309          * REC: restore times correctly (as does tar)
    310          * We only get the modification time of the file; set the creation time
    311          * from the mod. time, and the access time to current time
    312          */
    313         finfo->mtime_ts = finfo->ctime_ts =
    314                 convert_time_t_to_timespec((time_t)strtol(hb->dbuf.mtime, NULL, 8));
    315         finfo->atime_ts = convert_time_t_to_timespec(time(NULL));
    316         if ((hb->dbuf.size[0] & 0xff) == 0x80) {
    317                 /* This is a non-POSIX compatible extention to extract files
    318                         greater than 8GB. */
    319                 finfo->size = 0;
    320                 for (i = 0; i < 8; i++) {
    321                         finfo->size <<= 8;
    322                         finfo->size |= hb->dbuf.size[i+4] & 0xff;
    323                 }
    324         } else {
    325                 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
    326         }
    327 
    328         return True;
    329 }
    330 
    331 /****************************************************************************
    332 Write out the tar buffer to tape or wherever
    333 ****************************************************************************/
    334 
    335 static int dotarbuf(int f, char *b, int n)
    336 {
    337         int fail=1, writ=n;
    338 
    339         if (dry_run) {
    340                 return writ;
    341         }
    342         /* This routine and the next one should be the only ones that do write()s */
    343         if (tp + n >= tbufsiz) {
    344                 int diff;
    345 
    346                 diff=tbufsiz-tp;
    347                 memcpy(tarbuf + tp, b, diff);
    348                 fail=fail && (1+sys_write(f, tarbuf, tbufsiz));
    349                 n-=diff;
    350                 b+=diff;
    351                 tp=0;
    352 
    353                 while (n >= tbufsiz) {
    354                         fail=fail && (1 + sys_write(f, b, tbufsiz));
    355                         n-=tbufsiz;
    356                         b+=tbufsiz;
    357                 }
    358         }
    359 
    360         if (n>0) {
    361                 memcpy(tarbuf+tp, b, n);
    362                 tp+=n;
    363         }
    364 
    365         return(fail ? writ : 0);
    366 }
    367 
    368 /****************************************************************************
    369 Write zeros to buffer / tape
    370 ****************************************************************************/
    371 
    372 static void dozerobuf(int f, int n)
    373 {
    374         /* short routine just to write out n zeros to buffer -
    375          * used to round files to nearest block
    376          * and to do tar EOFs */
    377 
    378         if (dry_run)
    379                 return;
    380 
    381         if (n+tp >= tbufsiz) {
    382                 memset(tarbuf+tp, 0, tbufsiz-tp);
    383                 if (sys_write(f, tarbuf, tbufsiz) != tbufsiz) {
    384                         DEBUG(0, ("dozerobuf: sys_write fail\n"));
    385                         return;
    386                 }
    387                 memset(tarbuf, 0, (tp+=n-tbufsiz));
    388         } else {
    389                 memset(tarbuf+tp, 0, n);
    390                 tp+=n;
    391         }
    392 }
    393 
    394 /****************************************************************************
    395 Malloc tape buffer
    396 ****************************************************************************/
    397 
    398 static void initarbuf(void)
    399 {
    400         /* initialize tar buffer */
    401         tbufsiz=blocksize*TBLOCK;
    402         tarbuf=(char *)SMB_MALLOC(tbufsiz);      /* FIXME: We might not get the buffer */
    403 
    404         /* reset tar buffer pointer and tar file counter and total dumped */
    405         tp=0; ntarf=0; ttarf=0;
    406 }
    407 
    408 /****************************************************************************
    409 Write two zero blocks at end of file
    410 ****************************************************************************/
    411 
    412 static void dotareof(int f)
    413 {
    414         SMB_STRUCT_STAT stbuf;
    415         /* Two zero blocks at end of file, write out full buffer */
    416 
    417         if (dry_run)
    418                 return;
    419 
    420         (void) dozerobuf(f, TBLOCK);
    421         (void) dozerobuf(f, TBLOCK);
    422 
    423         if (sys_fstat(f, &stbuf, false) == -1) {
    424                 DEBUG(0, ("Couldn't stat file handle\n"));
    425                 return;
    426         }
    427 
    428         /* Could be a pipe, in which case S_ISREG should fail,
    429                 * and we should write out at full size */
    430         if (tp > 0) {
    431                 size_t towrite = S_ISREG(stbuf.st_ex_mode) ? tp : tbufsiz;
    432                 if (sys_write(f, tarbuf, towrite) != towrite) {
    433                         DEBUG(0,("dotareof: sys_write fail\n"));
    434                 }
    435         }
    436 }
    437 
    438 /****************************************************************************
    439 (Un)mangle DOS pathname, make nonabsolute
    440 ****************************************************************************/
    441 
    442 static void fixtarname(char *tptr, const char *fp, size_t l)
    443 {
    444         /* add a '.' to start of file name, convert from ugly dos \'s in path
    445          * to lovely unix /'s :-} */
    446         *tptr++='.';
    447         l--;
    448 
    449         StrnCpy(tptr, fp, l-1);
    450         string_replace(tptr, '\\', '/');
    451 }
    452 
    453 /****************************************************************************
    454 Convert from decimal to octal string
    455 ****************************************************************************/
    456 
    457 static void oct_it (uint64_t value, int ndgs, char *p)
    458 {
    459         /* Converts long to octal string, pads with leading zeros */
    460 
    461         /* skip final null, but do final space */
    462         --ndgs;
    463         p[--ndgs] = ' ';
    464 
    465         /* Loop does at least one digit */
    466         do {
    467                 p[--ndgs] = '0' + (char) (value & 7);
    468                 value >>= 3;
    469         } while (ndgs > 0 && value != 0);
    470 
    471         /* Do leading zeros */
    472         while (ndgs > 0)
    473                 p[--ndgs] = '0';
    474 }
    475 
    476 /****************************************************************************
    477 Convert from octal string to long
    478 ***************************************************************************/
    479 
    480 static long unoct(char *p, int ndgs)
    481 {
    482         long value=0;
    483         /* Converts octal string to long, ignoring any non-digit */
    484 
    485         while (--ndgs) {
    486                 if (isdigit((int)*p))
    487                         value = (value << 3) | (long) (*p - '0');
    488 
    489                 p++;
    490         }
    491 
    492         return value;
    493 }
    494 
    495 /****************************************************************************
    496 Compare two strings in a slash insensitive way, allowing s1 to match s2
    497 if s1 is an "initial" string (up to directory marker).  Thus, if s2 is
    498 a file in any subdirectory of s1, declare a match.
    499 ***************************************************************************/
    500 
    501 static int strslashcmp(char *s1, char *s2)
    502 {
    503         char *s1_0=s1;
    504 
    505         while(*s1 && *s2 && (*s1 == *s2 || tolower_m(*s1) == tolower_m(*s2) ||
    506                                 (*s1 == '\\' && *s2=='/') || (*s1 == '/' && *s2=='\\'))) {
    507                 s1++; s2++;
    508         }
    509 
    510         /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
    511                 string of s2.
    512         */
    513         if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\'))
    514                 return 0;
    515 
    516         /* ignore trailing slash on s1 */
    517         if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1))
    518                 return 0;
    519 
    520         /* check for s1 is an "initial" string of s2 */
    521         if ((*s2 == '/' || *s2 == '\\') && !*s1)
    522                 return 0;
    523 
    524         return *s1-*s2;
    525 }
    526 
    527 /****************************************************************************
    528 Ensure a remote path exists (make if necessary)
    529 ***************************************************************************/
    530 
    531 static bool ensurepath(const char *fname)
    532 {
    533         /* *must* be called with buffer ready malloc'ed */
    534         /* ensures path exists */
    535 
    536         char *partpath, *ffname;
    537         const char *p=fname;
    538         char *basehack;
    539         char *saveptr;
    540 
    541         DEBUG(5, ( "Ensurepath called with: %s\n", fname));
    542 
    543         partpath = string_create_s(strlen(fname));
    544         ffname = string_create_s(strlen(fname));
    545 
    546         if ((partpath == NULL) || (ffname == NULL)){
    547                 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
    548                 SAFE_FREE(partpath);
    549                 SAFE_FREE(ffname);
    550                 return(False);
    551         }
    552 
    553         *partpath = 0;
    554 
    555         /* fname copied to ffname so can strtok_r */
    556 
    557         safe_strcpy(ffname, fname, strlen(fname));
    558 
    559         /* do a `basename' on ffname, so don't try and make file name directory */
    560         if ((basehack=strrchr_m(ffname, '\\')) == NULL) {
    561                 SAFE_FREE(partpath);
    562                 SAFE_FREE(ffname);
    563                 return True;
    564         } else {
    565                 *basehack='\0';
    566         }
    567 
    568         p=strtok_r(ffname, "\\", &saveptr);
    569 
    570         while (p) {
    571                 safe_strcat(partpath, p, strlen(fname) + 1);
    572 
    573                 if (!NT_STATUS_IS_OK(cli_chkpath(cli, partpath))) {
    574                         if (!NT_STATUS_IS_OK(cli_mkdir(cli, partpath))) {
    575                                 SAFE_FREE(partpath);
    576                                 SAFE_FREE(ffname);
    577                                 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli)));
    578                                 return False;
    579                         } else {
    580                                 DEBUG(3, ("mkdirhiering %s\n", partpath));
    581                         }
    582                 }
    583 
    584                 safe_strcat(partpath, "\\", strlen(fname) + 1);
    585                 p = strtok_r(NULL, "/\\", &saveptr);
    586         }
    587 
    588         SAFE_FREE(partpath);
    589         SAFE_FREE(ffname);
    590         return True;
    591 }
    592 
    593 static int padit(char *buf, uint64_t bufsize, uint64_t padsize)
    594 {
    595         int berr= 0;
    596         int bytestowrite;
    597 
    598         DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize));
    599         memset(buf, 0, (size_t)bufsize);
    600         while( !berr && padsize > 0 ) {
    601                 bytestowrite= (int)MIN(bufsize, padsize);
    602                 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
    603                 padsize -= bytestowrite;
    604         }
    605 
    606         return berr;
    607 }
    608 
    609 static void do_setrattr(char *name, uint16 attr, int set)
    610 {
    611         uint16 oldattr;
    612 
    613         if (!NT_STATUS_IS_OK(cli_getatr(cli, name, &oldattr, NULL, NULL))) {
    614                 return;
    615         }
    616 
    617         if (set == ATTRSET) {
    618                 attr |= oldattr;
    619         } else {
    620                 attr = oldattr & ~attr;
    621         }
    622 
    623         if (!NT_STATUS_IS_OK(cli_setatr(cli, name, attr, 0))) {
    624                 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli)));
    625         }
    626 }
    627 
    628 /****************************************************************************
    629 append one remote file to the tar file
    630 ***************************************************************************/
    631 
    632 static NTSTATUS do_atar(const char *rname_in, char *lname,
    633                     struct file_info *finfo1)
    634 {
    635         uint16_t fnum = (uint16_t)-1;
    636         uint64_t nread=0;
    637         char ftype;
    638         file_info2 finfo;
    639         bool shallitime=True;
    640         char *data = NULL;
    641         int read_size = 65520;
    642         int datalen=0;
    643         char *rname = NULL;
    644         TALLOC_CTX *ctx = talloc_stackframe();
    645         NTSTATUS status = NT_STATUS_OK;
    646         struct timespec tp_start;
    647 
    648         clock_gettime_mono(&tp_start);
    649 
    650         data = SMB_MALLOC_ARRAY(char, read_size);
    651         if (!data) {
    652                 DEBUG(0,("do_atar: out of memory.\n"));
    653                 status = NT_STATUS_NO_MEMORY;
    654                 goto cleanup;
    655         }
    656 
    657         ftype = '0'; /* An ordinary file ... */
    658 
    659         ZERO_STRUCT(finfo);
    660 
    661         finfo.size  = finfo1 -> size;
    662         finfo.mode  = finfo1 -> mode;
    663         finfo.uid   = finfo1 -> uid;
    664         finfo.gid   = finfo1 -> gid;
    665         finfo.mtime_ts = finfo1 -> mtime_ts;
    666         finfo.atime_ts = finfo1 -> atime_ts;
    667         finfo.ctime_ts = finfo1 -> ctime_ts;
    668 
    669         if (dry_run) {
    670                 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1->name,
    671                                 (double)finfo.size));
    672                 shallitime=0;
    673                 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
    674                 ntarf++;
    675                 goto cleanup;
    676         }
    677 
    678         rname = clean_name(ctx, rname_in);
    679         if (!rname) {
    680                 status = NT_STATUS_NO_MEMORY;
    681                 goto cleanup;
    682         }
    683 
    684         status = cli_open(cli, rname, O_RDONLY, DENY_NONE, &fnum);
    685         if (!NT_STATUS_IS_OK(status)) {
    686                 DEBUG(0,("%s opening remote file %s (%s)\n",
    687                                 cli_errstr(cli),rname, client_get_cur_dir()));
    688                 goto cleanup;
    689         }
    690 
    691         finfo.name = string_create_s(strlen(rname));
    692         if (finfo.name == NULL) {
    693                 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
    694                 status = NT_STATUS_NO_MEMORY;
    695                 goto cleanup;
    696         }
    697 
    698         safe_strcpy(finfo.name,rname, strlen(rname));
    699 
    700         DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
    701 
    702         if (tar_inc && !(finfo.mode & FILE_ATTRIBUTE_ARCHIVE)) {
    703                 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
    704                 shallitime=0;
    705         } else if (!tar_system && (finfo.mode & FILE_ATTRIBUTE_SYSTEM)) {
    706                 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
    707                 shallitime=0;
    708         } else if (!tar_hidden && (finfo.mode & FILE_ATTRIBUTE_HIDDEN)) {
    709                 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
    710                 shallitime=0;
    711         } else {
    712                 bool wrote_tar_header = False;
    713 
    714                 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
    715                         finfo.name, (double)finfo.size, lname));
    716 
    717                 do {
    718 
    719                         DEBUG(3,("nread=%.0f\n",(double)nread));
    720 
    721                         datalen = cli_read(cli, fnum, data, nread, read_size);
    722 
    723                         if (datalen == -1) {
    724                                 DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli)));
    725                                 status = cli_nt_error(cli);
     273        TALLOC_CTX *ctx;
     274
     275        struct {
     276                const char *cmd;
     277                bool *p;
     278                bool value;
     279        } table[] = {
     280                {"full",      &tar_ctx.mode.incremental, false},
     281                {"inc",       &tar_ctx.mode.incremental, true },
     282                {"reset",     &tar_ctx.mode.reset,       true },
     283                {"noreset",   &tar_ctx.mode.reset,       false},
     284                {"system",    &tar_ctx.mode.system,      true },
     285                {"nosystem",  &tar_ctx.mode.system,      false},
     286                {"hidden",    &tar_ctx.mode.hidden,      true },
     287                {"nohidden",  &tar_ctx.mode.hidden,      false},
     288                {"verbose",   &tar_ctx.mode.verbose,     true },
     289                {"noquiet",   &tar_ctx.mode.verbose,     true },
     290                {"quiet",     &tar_ctx.mode.verbose,     false},
     291                {"noverbose", &tar_ctx.mode.verbose,     false},
     292        };
     293
     294        ctx = talloc_new(NULL);
     295        if (ctx == NULL) {
     296                return 1;
     297        }
     298
     299        while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
     300                for (i = 0; i < ARRAY_SIZE(table); i++) {
     301                        if (strequal(table[i].cmd, buf)) {
     302                                *table[i].p = table[i].value;
    726303                                break;
    727304                        }
    728 
    729                         nread += datalen;
    730 
    731                         /* Only if the first read succeeds, write out the tar header. */
    732                         if (!wrote_tar_header) {
    733                                 /* write a tar header, don't bother with mode - just set to 100644 */
    734                                 writetarheader(tarhandle, rname, finfo.size,
    735                                         finfo.mtime_ts.tv_sec, "100644 \0", ftype);
    736                                 wrote_tar_header = True;
     305                }
     306
     307                if (i == ARRAY_SIZE(table))
     308                        DBG(0, ("tarmode: unrecognised option %s\n", buf));
     309        }
     310
     311        DBG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
     312                                tar_ctx.mode.incremental ? "incremental" : "full",
     313                                tar_ctx.mode.system      ? "system"      : "nosystem",
     314                                tar_ctx.mode.hidden      ? "hidden"      : "nohidden",
     315                                tar_ctx.mode.reset       ? "reset"       : "noreset",
     316                                tar_ctx.mode.verbose     ? "verbose"     : "quiet"));
     317
     318        talloc_free(ctx);
     319        return 0;
     320}
     321
     322/**
     323 * cmd_tar - interactive command to start a tar backup/restoration
     324 *
     325 * Check presence of argument, parse them and handle the request.
     326 */
     327int cmd_tar(void)
     328{
     329        const extern char *cmd_ptr;
     330        const char *flag;
     331        const char **val;
     332        char *buf;
     333        int maxtok = max_token(cmd_ptr);
     334        int i = 0;
     335        int err = 0;
     336        bool ok;
     337        int rc;
     338        TALLOC_CTX *ctx = talloc_new(NULL);
     339        if (ctx == NULL) {
     340                return 1;
     341        }
     342
     343        ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
     344        if (!ok) {
     345                DBG(0, ("tar <c|x>[IXFbganN] [options] <tar file> [path list]\n"));
     346                err = 1;
     347                goto out;
     348        }
     349
     350        flag = buf;
     351        val = talloc_array(ctx, const char *, maxtok);
     352        if (val == NULL) {
     353                err = 1;
     354                goto out;
     355        }
     356
     357        while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
     358                val[i++] = buf;
     359        }
     360
     361        rc = tar_parse_args(&tar_ctx, flag, val, i);
     362        if (rc != 0) {
     363                DBG(0, ("parse_args failed\n"));
     364                err = 1;
     365                goto out;
     366        }
     367
     368        rc = tar_process(&tar_ctx);
     369        if (rc != 0) {
     370                DBG(0, ("tar_process failed\n"));
     371                err = 1;
     372                goto out;
     373        }
     374
     375out:
     376        talloc_free(ctx);
     377        return err;
     378}
     379
     380
     381/**
     382 * tar_parse_args - parse and set tar command line arguments
     383 * @flag: string pointing to tar options
     384 * @val: number of tar arguments
     385 * @valsize: table of arguments after the flags (number of element in val)
     386 *
     387 * tar arguments work in a weird way. For each flag f that takes a
     388 * value v, the user is supposed to type:
     389 *
     390 * on the CLI:
     391 *   -Tf1f2f3 v1 v2 v3 TARFILE PATHS...
     392 *
     393 * in the interactive session:
     394 *   tar f1f2f3 v1 v2 v3 TARFILE PATHS...
     395 *
     396 * @flag has only flags (eg. "f1f2f3") and @val has the arguments
     397 * (values) following them (eg. ["v1", "v2", "v3", "TARFILE", "PATH1",
     398 * "PATH2"]).
     399 *
     400 * There are only 2 flags that take an arg: b and N. The other flags
     401 * just change the semantic of PATH or TARFILE.
     402 *
     403 * PATH can be a list of included/excluded paths, the path to a file
     404 * containing a list of included/excluded paths to use (F flag). If no
     405 * PATH is provided, the whole share is used (/).
     406 */
     407int tar_parse_args(struct tar* t,
     408                   const char *flag,
     409                   const char **val,
     410                   int valsize)
     411{
     412        TALLOC_CTX *ctx;
     413        bool do_read_list = false;
     414        /* index of next value to use */
     415        int ival = 0;
     416        int rc;
     417
     418        if (t == NULL) {
     419                DBG(0, ("Invalid tar context\n"));
     420                return 1;
     421        }
     422
     423        ctx = tar_reset_mem_context(t);
     424        if (ctx == NULL) {
     425                return 1;
     426        }
     427        /*
     428         * Reset back some options - could be from interactive version
     429         * all other modes are left as they are
     430         */
     431        t->mode.operation = TAR_NO_OPERATION;
     432        t->mode.selection = TAR_NO_SELECTION;
     433        t->mode.dry = false;
     434        t->to_process = false;
     435        t->total_size = 0;
     436
     437        while (flag[0] != '\0') {
     438                switch(flag[0]) {
     439                /* operation */
     440                case 'c':
     441                        if (t->mode.operation != TAR_NO_OPERATION) {
     442                                printf("Tar must be followed by only one of c or x.\n");
     443                                return 1;
    737444                        }
    738 
    739                         /* if file size has increased since we made file size query, truncate
    740                                 read so tar header for this file will be correct.
    741                         */
    742 
    743                         if (nread > finfo.size) {
    744                                 datalen -= nread - finfo.size;
    745                                 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
    746                                                         finfo.name, (double)finfo.size));
     445                        t->mode.operation = TAR_CREATE;
     446                        break;
     447                case 'x':
     448                        if (t->mode.operation != TAR_NO_OPERATION) {
     449                                printf("Tar must be followed by only one of c or x.\n");
     450                                return 1;
    747451                        }
    748 
    749                         /* add received bits of file to buffer - dotarbuf will
    750                         * write out in 512 byte intervals */
    751 
    752                         if (dotarbuf(tarhandle,data,datalen) != datalen) {
    753                                 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
    754                                 status = map_nt_error_from_unix(errno);
    755                                 break;
     452                        t->mode.operation = TAR_EXTRACT;
     453                        break;
     454
     455                        /* selection  */
     456                case 'I':
     457                        if (t->mode.selection != TAR_NO_SELECTION) {
     458                                DBG(0,("Only one of I,X,F must be specified\n"));
     459                                return 1;
    756460                        }
    757 
    758                         if ( (datalen == 0) && (finfo.size != 0) ) {
    759                                 status = NT_STATUS_UNSUCCESSFUL;
    760                                 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
    761                                 break;
     461                        t->mode.selection = TAR_INCLUDE;
     462                        break;
     463                case 'X':
     464                        if (t->mode.selection != TAR_NO_SELECTION) {
     465                                DBG(0,("Only one of I,X,F must be specified\n"));
     466                                return 1;
    762467                        }
    763 
    764                         datalen=0;
    765                 } while ( nread < finfo.size );
    766 
    767                 if (wrote_tar_header) {
    768                         /* pad tar file with zero's if we couldn't get entire file */
    769                         if (nread < finfo.size) {
    770                                 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
    771                                                         (double)finfo.size, (int)nread));
    772                                 if (padit(data, (uint64_t)sizeof(data), finfo.size - nread)) {
    773                                         status = map_nt_error_from_unix(errno);
    774                                         DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
    775                                 }
     468                        t->mode.selection = TAR_EXCLUDE;
     469                        break;
     470                case 'F':
     471                        if (t->mode.selection != TAR_NO_SELECTION) {
     472                                DBG(0,("Only one of I,X,F must be specified\n"));
     473                                return 1;
    776474                        }
    777 
    778                         /* round tar file to nearest block */
    779                         if (finfo.size % TBLOCK)
    780                                 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
    781 
    782                         ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
    783                         ntarf++;
     475                        t->mode.selection = TAR_INCLUDE;
     476                        do_read_list = true;
     477                        break;
     478
     479                        /* blocksize */
     480                case 'b':
     481                        if (ival >= valsize) {
     482                                DBG(0, ("Option b must be followed by a blocksize\n"));
     483                                return 1;
     484                        }
     485
     486                        if (tar_set_blocksize(t, atoi(val[ival]))) {
     487                                DBG(0, ("Option b must be followed by a valid blocksize\n"));
     488                                return 1;
     489                        }
     490
     491                        ival++;
     492                        break;
     493
     494                        /* incremental mode */
     495                case 'g':
     496                        t->mode.incremental = true;
     497                        break;
     498
     499                        /* newer than */
     500                case 'N':
     501                        if (ival >= valsize) {
     502                                DBG(0, ("Option N must be followed by valid file name\n"));
     503                                return 1;
     504                        }
     505
     506                        if (tar_set_newer_than(t, val[ival])) {
     507                                DBG(0,("Error setting newer-than time\n"));
     508                                return 1;
     509                        }
     510
     511                        ival++;
     512                        break;
     513
     514                        /* reset mode */
     515                case 'a':
     516                        t->mode.reset = true;
     517                        break;
     518
     519                        /* verbose */
     520                case 'q':
     521                        t->mode.verbose = true;
     522                        break;
     523
     524                        /* regex match  */
     525                case 'r':
     526                        t->mode.regex = true;
     527                        break;
     528
     529                        /* dry run mode */
     530                case 'n':
     531                        if (t->mode.operation != TAR_CREATE) {
     532                                DBG(0, ("n is only meaningful when creating a tar-file\n"));
     533                                return 1;
     534                        }
     535
     536                        t->mode.dry = true;
     537                        DBG(0, ("dry_run set\n"));
     538                        break;
     539
     540                default:
     541                        DBG(0,("Unknown tar option\n"));
     542                        return 1;
     543                }
     544
     545                flag++;
     546        }
     547
     548        /* no selection given? default selection is include */
     549        if (t->mode.selection == TAR_NO_SELECTION) {
     550                t->mode.selection = TAR_INCLUDE;
     551        }
     552
     553        if (valsize - ival < 1) {
     554                DBG(0, ("No tar file given.\n"));
     555                return 1;
     556        }
     557
     558        /* handle TARFILE */
     559        t->tar_path = talloc_strdup(ctx, val[ival]);
     560        if (t->tar_path == NULL) {
     561                return 1;
     562        }
     563        ival++;
     564
     565        /*
     566         * Make sure that dbf points to stderr if we are using stdout for
     567         * tar output
     568         */
     569        if (t->mode.operation == TAR_CREATE && strequal(t->tar_path, "-")) {
     570                setup_logging("smbclient", DEBUG_STDERR);
     571        }
     572
     573        /* handle PATHs... */
     574
     575        /* flag F -> read file list */
     576        if (do_read_list) {
     577                if (valsize - ival != 1) {
     578                        DBG(0,("Option F must be followed by exactly one filename.\n"));
     579                        return 1;
     580                }
     581
     582                rc = tar_read_inclusion_file(t, val[ival]);
     583                if (rc != 0) {
     584                        return 1;
     585                }
     586                ival++;
     587        /* otherwise store all the PATHs on the command line */
     588        } else {
     589                int i;
     590                for (i = ival; i < valsize; i++) {
     591                        NTSTATUS status;
     592                        status = tar_add_selection_path(t, val[i]);
     593                        if (!NT_STATUS_IS_OK(status)) {
     594                                return 1;
     595                        }
     596                }
     597        }
     598
     599        t->to_process = true;
     600        tar_dump(t);
     601        return 0;
     602}
     603
     604/**
     605 * tar_process - start processing archive
     606 *
     607 * The talloc context of the fields is freed at the end of the call.
     608 */
     609int tar_process(struct tar *t)
     610{
     611        int rc = 0;
     612
     613        if (t == NULL) {
     614                DBG(0, ("Invalid tar context\n"));
     615                return 1;
     616        }
     617
     618        switch(t->mode.operation) {
     619        case TAR_EXTRACT:
     620                rc = tar_extract(t);
     621                break;
     622        case TAR_CREATE:
     623                rc = tar_create(t);
     624                break;
     625        default:
     626                DBG(0, ("Invalid tar state\n"));
     627                rc = 1;
     628        }
     629
     630        t->to_process = false;
     631        tar_free_mem_context(t);
     632        DBG(5, ("tar_process done, err = %d\n", rc));
     633        return rc;
     634}
     635
     636/**
     637 * tar_create - create archive and fetch files
     638 */
     639static int tar_create(struct tar* t)
     640{
     641        int r;
     642        int err = 0;
     643        NTSTATUS status;
     644        const char *mask;
     645        TALLOC_CTX *ctx = talloc_new(NULL);
     646        if (ctx == NULL) {
     647                return 1;
     648        }
     649
     650        t->archive = archive_write_new();
     651
     652        if (!t->mode.dry) {
     653                const int bsize = t->mode.blocksize * TAR_BLOCK_UNIT;
     654                r = archive_write_set_bytes_per_block(t->archive, bsize);
     655                if (r != ARCHIVE_OK) {
     656                        DBG(0, ("Can't use a block size of %d bytes", bsize));
     657                        err = 1;
     658                        goto out;
     659                }
     660
     661                /*
     662                 * Use PAX restricted format which is not the most
     663                 * conservative choice but has useful extensions and is widely
     664                 * supported
     665                 */
     666                r = archive_write_set_format_pax_restricted(t->archive);
     667                if (r != ARCHIVE_OK) {
     668                        DBG(0, ("Can't use pax restricted format: %s\n",
     669                                                archive_error_string(t->archive)));
     670                        err = 1;
     671                        goto out;
     672                }
     673
     674                if (strequal(t->tar_path, "-")) {
     675                        r = archive_write_open_fd(t->archive, STDOUT_FILENO);
    784676                } else {
    785                         DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo.name));
    786                         shallitime=0;
     677                        r = archive_write_open_filename(t->archive, t->tar_path);
     678                }
     679
     680                if (r != ARCHIVE_OK) {
     681                        DBG(0, ("Can't open %s: %s\n", t->tar_path,
     682                                                archive_error_string(t->archive)));
     683                        err = 1;
     684                        goto out_close;
     685                }
     686        }
     687
     688        /*
     689         * In inclusion mode, iterate on the inclusion list
     690         */
     691        if (t->mode.selection == TAR_INCLUDE && t->path_list_size > 0) {
     692                if (tar_create_from_list(t)) {
     693                        err = 1;
     694                        goto out_close;
     695                }
     696        } else {
     697                mask = talloc_asprintf(ctx, "%s\\*", client_get_cur_dir());
     698                if (mask == NULL) {
     699                        err = 1;
     700                        goto out_close;
     701                }
     702                DBG(5, ("tar_process do_list with mask: %s\n", mask));
     703                status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
     704                if (!NT_STATUS_IS_OK(status)) {
     705                        DBG(0, ("do_list fail %s\n", nt_errstr(status)));
     706                        err = 1;
     707                        goto out_close;
     708                }
     709        }
     710
     711out_close:
     712        DBG(0, ("Total bytes received: %" PRIu64 "\n", t->total_size));
     713
     714        if (!t->mode.dry) {
     715                r = archive_write_close(t->archive);
     716                if (r != ARCHIVE_OK) {
     717                        DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
     718                        err = 1;
     719                        goto out;
     720                }
     721        }
     722out:
     723#ifdef HAVE_ARCHIVE_READ_FREE
     724        archive_write_free(t->archive);
     725#else
     726        archive_write_finish(t->archive);
     727#endif
     728        talloc_free(ctx);
     729        return err;
     730}
     731
     732/**
     733 * tar_create_from_list - fetch from path list in include mode
     734 */
     735static int tar_create_from_list(struct tar *t)
     736{
     737        int err = 0;
     738        NTSTATUS status;
     739        char *base;
     740        const char *path, *mask, *start_dir;
     741        int i;
     742        TALLOC_CTX *ctx = talloc_new(NULL);
     743        if (ctx == NULL) {
     744                return 1;
     745        }
     746
     747        start_dir = talloc_strdup(ctx, client_get_cur_dir());
     748        if (start_dir == NULL) {
     749                err = 1;
     750                goto out;
     751        }
     752
     753        for (i = 0; i < t->path_list_size; i++) {
     754                path = t->path_list[i];
     755                base = NULL;
     756                status = path_base_name(ctx, path, &base);
     757                if (!NT_STATUS_IS_OK(status)) {
     758                        err = 1;
     759                        goto out;
     760                }
     761                mask = talloc_asprintf(ctx, "%s\\%s",
     762                                       client_get_cur_dir(), path);
     763                if (mask == NULL) {
     764                        err = 1;
     765                        goto out;
     766                }
     767
     768                DBG(5, ("incl. path='%s', base='%s', mask='%s'\n",
     769                                        path, base ? base : "NULL", mask));
     770
     771                if (base != NULL) {
     772                        base = talloc_asprintf(ctx, "%s%s\\",
     773                                               client_get_cur_dir(), base);
     774                        if (base == NULL) {
     775                                err = 1;
     776                                goto out;
     777                        }
     778                        DBG(5, ("cd '%s' before do_list\n", base));
     779                        client_set_cur_dir(base);
     780                }
     781                status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
     782                if (base != NULL) {
     783                        client_set_cur_dir(start_dir);
     784                }
     785                if (!NT_STATUS_IS_OK(status)) {
     786                        DBG(0, ("do_list failed on %s (%s)\n", path, nt_errstr(status)));
     787                        err = 1;
     788                        goto out;
     789                }
     790        }
     791
     792out:
     793        talloc_free(ctx);
     794        return err;
     795}
     796
     797/**
     798 * get_file_callback - do_list callback
     799 *
     800 * Callback for client.c do_list(). Called for each file found on the
     801 * share matching do_list mask. Recursively call do_list() with itself
     802 * as callback when the current file is a directory.
     803 */
     804static NTSTATUS get_file_callback(struct cli_state *cli,
     805                                  struct file_info *finfo,
     806                                  const char *dir)
     807{
     808        NTSTATUS status = NT_STATUS_OK;
     809        char *remote_name;
     810        const char *initial_dir = client_get_cur_dir();
     811        bool skip = false;
     812        int rc;
     813        TALLOC_CTX *ctx = talloc_new(NULL);
     814        if (ctx == NULL) {
     815                return NT_STATUS_NO_MEMORY;
     816        }
     817
     818        remote_name = talloc_asprintf(ctx, "%s%s", initial_dir, finfo->name);
     819        if (remote_name == NULL) {
     820                status = NT_STATUS_NO_MEMORY;
     821                goto out;
     822        }
     823
     824        if (strequal(finfo->name, "..") || strequal(finfo->name, ".")) {
     825                goto out;
     826        }
     827
     828        status = tar_create_skip_path(&tar_ctx, remote_name, finfo, &skip);
     829        if (!NT_STATUS_IS_OK(status)) {
     830                goto out;
     831        }
     832
     833        if (skip) {
     834                DBG(5, ("--- %s\n", remote_name));
     835                status = NT_STATUS_OK;
     836                goto out;
     837        }
     838
     839        if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
     840                char *old_dir;
     841                char *new_dir;
     842                char *mask;
     843
     844                old_dir = talloc_strdup(ctx, initial_dir);
     845                new_dir = talloc_asprintf(ctx, "%s%s\\",
     846                                          initial_dir, finfo->name);
     847                if ((old_dir == NULL) || (new_dir == NULL)) {
     848                        status = NT_STATUS_NO_MEMORY;
     849                        goto out;
     850                }
     851                mask = talloc_asprintf(ctx, "%s*", new_dir);
     852                if (mask == NULL) {
     853                        status = NT_STATUS_NO_MEMORY;
     854                        goto out;
     855                }
     856
     857                rc = tar_get_file(&tar_ctx, remote_name, finfo);
     858                if (rc != 0) {
    787859                        status = NT_STATUS_UNSUCCESSFUL;
    788                 }
    789         }
    790 
    791         cli_close(cli, fnum);
    792         fnum = -1;
    793 
    794         if (shallitime) {
    795                 struct timespec tp_end;
    796                 int this_time;
    797 
    798                 /* if shallitime is true then we didn't skip */
    799                 if (tar_reset && !dry_run)
    800                         (void) do_setrattr(finfo.name, FILE_ATTRIBUTE_ARCHIVE, ATTRRESET);
    801 
    802                 clock_gettime_mono(&tp_end);
    803                 this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000000;
    804                 get_total_time_ms += this_time;
    805                 get_total_size += finfo.size;
    806 
    807                 if (tar_noisy) {
    808                         DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
    809                                 (double)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
    810                                 finfo.name));
    811                 }
    812 
    813                 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
    814                 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
    815                                 finfo.size / MAX(0.001, (1.024*this_time)),
    816                                 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
    817         }
    818 
    819   cleanup:
    820 
    821         if (fnum != (uint16_t)-1) {
    822                 cli_close(cli, fnum);
    823                 fnum = -1;
    824         }
    825         TALLOC_FREE(ctx);
    826         SAFE_FREE(data);
     860                        goto out;
     861                }
     862
     863                client_set_cur_dir(new_dir);
     864                do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
     865                client_set_cur_dir(old_dir);
     866        } else {
     867                rc = tar_get_file(&tar_ctx, remote_name, finfo);
     868                if (rc != 0) {
     869                        status = NT_STATUS_UNSUCCESSFUL;
     870                        goto out;
     871                }
     872        }
     873
     874out:
     875        talloc_free(ctx);
    827876        return status;
    828877}
    829878
    830 /****************************************************************************
    831 Append single file to tar file (or not)
    832 ***************************************************************************/
    833 
    834 static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo,
    835                    const char *dir)
    836 {
    837         TALLOC_CTX *ctx = talloc_stackframe();
     879/**
     880 * tar_get_file - fetch a remote file to the local archive
     881 * @full_dos_path: path to the file to fetch
     882 * @finfo: attributes of the file to fetch
     883 */
     884static int tar_get_file(struct tar *t,
     885                        const char *full_dos_path,
     886                        struct file_info *finfo)
     887{
     888        extern struct cli_state *cli;
     889        NTSTATUS status;
     890        struct archive_entry *entry;
     891        char *full_unix_path;
     892        char buf[TAR_CLI_READ_SIZE];
     893        size_t len;
     894        uint64_t off = 0;
     895        uint16_t remote_fd = (uint16_t)-1;
     896        int err = 0, r;
     897        const bool isdir = finfo->mode & FILE_ATTRIBUTE_DIRECTORY;
     898        TALLOC_CTX *ctx = talloc_new(NULL);
     899        if (ctx == NULL) {
     900                return 1;
     901        }
     902
     903        DBG(5, ("+++ %s\n", full_dos_path));
     904
     905        t->total_size += finfo->size;
     906
     907        if (t->mode.dry) {
     908                goto out;
     909        }
     910
     911        if (t->mode.reset) {
     912                /* ignore return value: server might not store DOS attributes */
     913                set_remote_attr(full_dos_path, FILE_ATTRIBUTE_ARCHIVE, ATTR_UNSET);
     914        }
     915
     916        full_unix_path = talloc_asprintf(ctx, ".%s", full_dos_path);
     917        if (full_unix_path == NULL) {
     918                err = 1;
     919                goto out;
     920        }
     921        string_replace(full_unix_path, '\\', '/');
     922        entry = archive_entry_new();
     923        archive_entry_copy_pathname(entry, full_unix_path);
     924        archive_entry_set_filetype(entry, isdir ? AE_IFDIR : AE_IFREG);
     925        archive_entry_set_atime(entry,
     926                        finfo->atime_ts.tv_sec,
     927                        finfo->atime_ts.tv_nsec);
     928        archive_entry_set_mtime(entry,
     929                        finfo->mtime_ts.tv_sec,
     930                        finfo->mtime_ts.tv_nsec);
     931        archive_entry_set_ctime(entry,
     932                        finfo->ctime_ts.tv_sec,
     933                        finfo->ctime_ts.tv_nsec);
     934        archive_entry_set_perm(entry, isdir ? 0755 : 0644);
     935        /*
     936         * check if we can safely cast unsigned file size to libarchive
     937         * signed size. Very unlikely problem (>9 exabyte file)
     938         */
     939        if (finfo->size > INT64_MAX) {
     940                DBG(0, ("Remote file %s too big\n", full_dos_path));
     941                goto out_entry;
     942        }
     943
     944        archive_entry_set_size(entry, (int64_t)finfo->size);
     945
     946        r = archive_write_header(t->archive, entry);
     947        if (r != ARCHIVE_OK) {
     948                DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
     949                err = 1;
     950                goto out_entry;
     951        }
     952
     953        if (isdir) {
     954                DBG(5, ("get_file skip dir %s\n", full_dos_path));
     955                goto out_entry;
     956        }
     957
     958        status = cli_open(cli, full_dos_path, O_RDONLY, DENY_NONE, &remote_fd);
     959        if (!NT_STATUS_IS_OK(status)) {
     960                DBG(0,("%s opening remote file %s\n",
     961                                        nt_errstr(status), full_dos_path));
     962                goto out_entry;
     963        }
     964
     965        do {
     966                status = cli_read(cli, remote_fd, buf, off, sizeof(buf), &len);
     967                if (!NT_STATUS_IS_OK(status)) {
     968                        DBG(0,("Error reading file %s : %s\n",
     969                                                full_dos_path, nt_errstr(status)));
     970                        err = 1;
     971                        goto out_close;
     972                }
     973
     974                off += len;
     975
     976                r = archive_write_data(t->archive, buf, len);
     977                if (r < 0) {
     978                        DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
     979                        err = 1;
     980                        goto out_close;
     981                }
     982
     983        } while (off < finfo->size);
     984
     985out_close:
     986        cli_close(cli, remote_fd);
     987
     988out_entry:
     989        archive_entry_free(entry);
     990
     991out:
     992        talloc_free(ctx);
     993        return err;
     994}
     995
     996/**
     997 * tar_extract - open archive and send files.
     998 */
     999static int tar_extract(struct tar *t)
     1000{
     1001        int err = 0;
     1002        int r;
     1003        struct archive_entry *entry;
     1004        const size_t bsize = t->mode.blocksize * TAR_BLOCK_UNIT;
     1005        int rc;
     1006
     1007        t->archive = archive_read_new();
     1008        archive_read_support_format_all(t->archive);
     1009#ifdef HAVE_ARCHIVE_READ_SUPPORT_FILTER_ALL
     1010        archive_read_support_filter_all(t->archive);
     1011#endif
     1012
     1013        if (strequal(t->tar_path, "-")) {
     1014                r = archive_read_open_fd(t->archive, STDIN_FILENO, bsize);
     1015        } else {
     1016                r = archive_read_open_filename(t->archive, t->tar_path, bsize);
     1017        }
     1018
     1019        if (r != ARCHIVE_OK) {
     1020                DBG(0, ("Can't open %s : %s\n", t->tar_path,
     1021                                        archive_error_string(t->archive)));
     1022                err = 1;
     1023                goto out;
     1024        }
     1025
     1026        for (;;) {
     1027                NTSTATUS status;
     1028                bool skip;
     1029                r = archive_read_next_header(t->archive, &entry);
     1030                if (r == ARCHIVE_EOF) {
     1031                        break;
     1032                }
     1033                if (r == ARCHIVE_WARN) {
     1034                        DBG(0, ("Warning: %s\n", archive_error_string(t->archive)));
     1035                }
     1036                if (r == ARCHIVE_FATAL) {
     1037                        DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
     1038                        err = 1;
     1039                        goto out;
     1040                }
     1041
     1042                status = tar_extract_skip_path(t, entry, &skip);
     1043                if (!NT_STATUS_IS_OK(status)) {
     1044                        err = 1;
     1045                        goto out;
     1046                }
     1047                if (skip) {
     1048                        DBG(5, ("--- %s\n", archive_entry_pathname(entry)));
     1049                        continue;
     1050                }
     1051
     1052                DBG(5, ("+++ %s\n", archive_entry_pathname(entry)));
     1053
     1054                rc = tar_send_file(t, entry);
     1055                if (rc != 0) {
     1056                        err = 1;
     1057                        goto out;
     1058                }
     1059        }
     1060
     1061out:
     1062#ifdef HAVE_ARCHIVE_READ_FREE
     1063        r = archive_read_free(t->archive);
     1064#else
     1065        r = archive_read_finish(t->archive);
     1066#endif
     1067        if (r != ARCHIVE_OK) {
     1068                DBG(0, ("Can't close %s : %s\n", t->tar_path,
     1069                                        archive_error_string(t->archive)));
     1070                err = 1;
     1071        }
     1072        return err;
     1073}
     1074
     1075/**
     1076 * tar_send_file - send @entry to the remote server
     1077 * @entry: current archive entry
     1078 *
     1079 * Handle the creation of the parent directories and transfer the
     1080 * entry to a new remote file.
     1081 */
     1082static int tar_send_file(struct tar *t, struct archive_entry *entry)
     1083{
     1084        extern struct cli_state *cli;
     1085        char *dos_path;
     1086        char *full_path;
     1087        NTSTATUS status;
     1088        uint16_t remote_fd = (uint16_t) -1;
     1089        int err = 0;
     1090        int flags = O_RDWR | O_CREAT | O_TRUNC;
     1091        mode_t mode = archive_entry_filetype(entry);
     1092        int rc;
     1093        TALLOC_CTX *ctx = talloc_new(NULL);
     1094        if (ctx == NULL) {
     1095                return 1;
     1096        }
     1097
     1098        dos_path = talloc_strdup(ctx, archive_entry_pathname(entry));
     1099        if (dos_path == NULL) {
     1100                err = 1;
     1101                goto out;
     1102        }
     1103        fix_unix_path(dos_path, true);
     1104
     1105        full_path = talloc_strdup(ctx, client_get_cur_dir());
     1106        if (full_path == NULL) {
     1107                err = 1;
     1108                goto out;
     1109        }
     1110        full_path = talloc_strdup_append(full_path, dos_path);
     1111        if (full_path == NULL) {
     1112                err = 1;
     1113                goto out;
     1114        }
     1115
     1116        if (mode != AE_IFREG && mode != AE_IFDIR) {
     1117                DBG(0, ("Skipping non-dir & non-regular file %s\n", full_path));
     1118                goto out;
     1119        }
     1120
     1121        rc = make_remote_path(full_path);
     1122        if (rc != 0) {
     1123                err = 1;
     1124                goto out;
     1125        }
     1126
     1127        if (mode == AE_IFDIR) {
     1128                goto out;
     1129        }
     1130
     1131        status = cli_open(cli, full_path, flags, DENY_NONE, &remote_fd);
     1132        if (!NT_STATUS_IS_OK(status)) {
     1133                DBG(0, ("Error opening remote file %s: %s\n",
     1134                                        full_path, nt_errstr(status)));
     1135                err = 1;
     1136                goto out;
     1137        }
     1138
     1139        for (;;) {
     1140                const void *buf;
     1141                size_t len;
     1142                off_t off;
     1143                int r;
     1144
     1145                r = archive_read_data_block(t->archive, &buf, &len, &off);
     1146                if (r == ARCHIVE_EOF) {
     1147                        break;
     1148                }
     1149                if (r == ARCHIVE_WARN) {
     1150                        DBG(0, ("Warning: %s\n", archive_error_string(t->archive)));
     1151                }
     1152                if (r == ARCHIVE_FATAL) {
     1153                        DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
     1154                        err = 1;
     1155                        goto close_out;
     1156                }
     1157
     1158                status = cli_writeall(cli, remote_fd, 0, buf, off, len, NULL);
     1159                if (!NT_STATUS_IS_OK(status)) {
     1160                        DBG(0, ("Error writing remote file %s: %s\n",
     1161                                                full_path, nt_errstr(status)));
     1162                        err = 1;
     1163                        goto close_out;
     1164                }
     1165        }
     1166
     1167close_out:
     1168        status = cli_close(cli, remote_fd);
     1169        if (!NT_STATUS_IS_OK(status)) {
     1170                DBG(0, ("Error losing remote file %s: %s\n",
     1171                                        full_path, nt_errstr(status)));
     1172                err = 1;
     1173        }
     1174
     1175out:
     1176        talloc_free(ctx);
     1177        return err;
     1178}
     1179
     1180/**
     1181 * tar_add_selection_path - add a path to the path list
     1182 * @path: path to add
     1183 */
     1184static NTSTATUS tar_add_selection_path(struct tar *t, const char *path)
     1185{
     1186        const char **list;
     1187        TALLOC_CTX *ctx = t->talloc_ctx;
     1188        if (!t->path_list) {
     1189                t->path_list = str_list_make_empty(ctx);
     1190                if (t->path_list == NULL) {
     1191                        return NT_STATUS_NO_MEMORY;
     1192                }
     1193                t->path_list_size = 0;
     1194        }
     1195
     1196        /* cast to silence gcc const-qual warning */
     1197        list = str_list_add((void *)t->path_list, path);
     1198        if (list == NULL) {
     1199                return NT_STATUS_NO_MEMORY;
     1200        }
     1201        t->path_list = discard_const_p(char *, list);
     1202        t->path_list_size++;
     1203        fix_unix_path(t->path_list[t->path_list_size - 1], true);
     1204
     1205        return NT_STATUS_OK;
     1206}
     1207
     1208/**
     1209 * tar_set_blocksize - set block size in TAR_BLOCK_UNIT
     1210 */
     1211static int tar_set_blocksize(struct tar *t, int size)
     1212{
     1213        if (size <= 0 || size > TAR_MAX_BLOCK_SIZE) {
     1214                return 1;
     1215        }
     1216
     1217        t->mode.blocksize = size;
     1218
     1219        return 0;
     1220}
     1221
     1222/**
     1223 * tar_set_newer_than - set date threshold of saved files
     1224 * @filename: local path to a file
     1225 *
     1226 * Only files newer than the modification time of @filename will be
     1227 * saved.
     1228 *
     1229 * Note: this function set the global variable newer_than from
     1230 * client.c. Thus the time is not a field of the tar structure. See
     1231 * cmd_newer() to change its value from an interactive session.
     1232 */
     1233static int tar_set_newer_than(struct tar *t, const char *filename)
     1234{
     1235        extern time_t newer_than;
     1236        SMB_STRUCT_STAT stbuf;
     1237        int rc;
     1238
     1239        rc = sys_stat(filename, &stbuf, false);
     1240        if (rc != 0) {
     1241                DBG(0, ("Error setting newer-than time\n"));
     1242                return 1;
     1243        }
     1244
     1245        newer_than = convert_timespec_to_time_t(stbuf.st_ex_mtime);
     1246        DBG(1, ("Getting files newer than %s\n", time_to_asc(newer_than)));
     1247        return 0;
     1248}
     1249
     1250/**
     1251 * tar_read_inclusion_file - set path list from file
     1252 * @filename: path to the list file
     1253 *
     1254 * Read and add each line of @filename to the path list.
     1255 */
     1256static int tar_read_inclusion_file(struct tar *t, const char* filename)
     1257{
     1258        char *line;
     1259        int err = 0;
     1260        int fd;
     1261        TALLOC_CTX *ctx = talloc_new(NULL);
     1262        if (ctx == NULL) {
     1263                return 1;
     1264        }
     1265
     1266        fd = open(filename, O_RDONLY);
     1267        if (fd < 0) {
     1268                DBG(0, ("Can't open inclusion file '%s': %s\n", filename, strerror(errno)));
     1269                err = 1;
     1270                goto out;
     1271        }
     1272
     1273        for (line = afdgets(fd, ctx, 0);
     1274                        line != NULL;
     1275                        line = afdgets(fd, ctx, 0)) {
     1276                NTSTATUS status;
     1277                status = tar_add_selection_path(t, line);
     1278                if (!NT_STATUS_IS_OK(status)) {
     1279                        err = 1;
     1280                        goto out;
     1281                }
     1282        }
     1283
     1284        close(fd);
     1285
     1286out:
     1287        talloc_free(ctx);
     1288        return err;
     1289}
     1290
     1291/**
     1292 * tar_path_in_list - check whether @path is in the path list
     1293 * @path: path to find
     1294 * @reverse: when true also try to find path list element in @path
     1295 * @_is_in_list: set if @path is in the path list
     1296 *
     1297 * Look at each path of the path list and set @_is_in_list if @path is a
     1298 * subpath of one of them.
     1299 *
     1300 * If you want /path to be in the path list (path/a/, path/b/) set
     1301 * @reverse to true to try to match the other way around.
     1302 */
     1303static NTSTATUS tar_path_in_list(struct tar *t, const char *path,
     1304                                 bool reverse, bool *_is_in_list)
     1305{
     1306        int i;
     1307        const char *p;
     1308        const char *pattern;
     1309
     1310        if (path == NULL || path[0] == '\0') {
     1311                *_is_in_list = false;
     1312                return NT_STATUS_OK;
     1313        }
     1314
     1315        p = skip_useless_char_in_path(path);
     1316
     1317        for (i = 0; i < t->path_list_size; i++) {
     1318                bool is_in_list;
     1319                NTSTATUS status;
     1320
     1321                pattern = skip_useless_char_in_path(t->path_list[i]);
     1322                status = is_subpath(p, pattern, &is_in_list);
     1323                if (!NT_STATUS_IS_OK(status)) {
     1324                        return status;
     1325                }
     1326                if (reverse && !is_in_list) {
     1327                        status = is_subpath(pattern, p, &is_in_list);
     1328                        if (!NT_STATUS_IS_OK(status)) {
     1329                                return status;
     1330                        }
     1331                }
     1332                if (is_in_list) {
     1333                        *_is_in_list = true;
     1334                        return NT_STATUS_OK;
     1335                }
     1336        }
     1337
     1338        *_is_in_list = false;
     1339        return NT_STATUS_OK;
     1340}
     1341
     1342/**
     1343 * tar_extract_skip_path - check if @entry should be skipped
     1344 * @entry: current tar entry
     1345 * @_skip: set true if path should be skipped, otherwise false
     1346 *
     1347 * Skip predicate for tar extraction (archive to server) only.
     1348 */
     1349static NTSTATUS tar_extract_skip_path(struct tar *t,
     1350                                      struct archive_entry *entry,
     1351                                      bool *_skip)
     1352{
     1353        const char *fullpath = archive_entry_pathname(entry);
     1354        bool in = true;
     1355
     1356        if (t->path_list_size <= 0) {
     1357                *_skip = false;
     1358                return NT_STATUS_OK;
     1359        }
     1360
     1361        if (t->mode.regex) {
     1362                in = mask_match_list(fullpath, t->path_list, t->path_list_size, true);
     1363        } else {
     1364                NTSTATUS status = tar_path_in_list(t, fullpath, false, &in);
     1365                if (!NT_STATUS_IS_OK(status)) {
     1366                        return status;
     1367                }
     1368        }
     1369
     1370        if (t->mode.selection == TAR_EXCLUDE) {
     1371                *_skip = in;
     1372        } else {
     1373                *_skip = !in;
     1374        }
     1375
     1376        return NT_STATUS_OK;
     1377}
     1378
     1379/**
     1380 * tar_create_skip_path - check if @fullpath shoud be skipped
     1381 * @fullpath: full remote path of the current file
     1382 * @finfo: remote file attributes
     1383 * @_skip: returned skip not
     1384 *
     1385 * Skip predicate for tar creation (server to archive) only.
     1386 */
     1387static NTSTATUS tar_create_skip_path(struct tar *t,
     1388                                     const char *fullpath,
     1389                                     const struct file_info *finfo,
     1390                                     bool *_skip)
     1391{
     1392        /* syntaxic sugar */
     1393        const mode_t mode = finfo->mode;
     1394        const bool isdir = mode & FILE_ATTRIBUTE_DIRECTORY;
     1395        const bool exclude = t->mode.selection == TAR_EXCLUDE;
     1396        bool in = true;
     1397
     1398        if (!isdir) {
     1399
     1400                /* 1. if we don't want X and we have X, skip */
     1401                if (!t->mode.system && (mode & FILE_ATTRIBUTE_SYSTEM)) {
     1402                        *_skip = true;
     1403                        return NT_STATUS_OK;
     1404                }
     1405
     1406                if (!t->mode.hidden && (mode & FILE_ATTRIBUTE_HIDDEN)) {
     1407                        *_skip = true;
     1408                        return NT_STATUS_OK;
     1409                }
     1410
     1411                /* 2. if we only want archive and it's not, skip */
     1412
     1413                if (t->mode.incremental && !(mode & FILE_ATTRIBUTE_ARCHIVE)) {
     1414                        *_skip = true;
     1415                        return NT_STATUS_OK;
     1416                }
     1417        }
     1418
     1419        /* 3. is it in the selection list? */
     1420
     1421        /*
     1422         * tar_create_from_list() use the include list as a starting
     1423         * point, no need to check
     1424         */
     1425        if (!exclude) {
     1426                *_skip = false;
     1427                return NT_STATUS_OK;
     1428        }
     1429
     1430        /* we are now in exclude mode */
     1431
     1432        /* no matter the selection, no list => include everything */
     1433        if (t->path_list_size <= 0) {
     1434                *_skip = false;
     1435                return NT_STATUS_OK;
     1436        }
     1437
     1438        if (t->mode.regex) {
     1439                in = mask_match_list(fullpath, t->path_list, t->path_list_size, true);
     1440        } else {
     1441                bool reverse = isdir && !exclude;
     1442                NTSTATUS status = tar_path_in_list(t, fullpath, reverse, &in);
     1443                if (!NT_STATUS_IS_OK(status)) {
     1444                        return status;
     1445                }
     1446        }
     1447        *_skip = in;
     1448
     1449        return NT_STATUS_OK;
     1450}
     1451
     1452/**
     1453 * tar_to_process - return true if @t is ready to be processed
     1454 *
     1455 * @t is ready if it properly parsed command line arguments.
     1456 */
     1457bool tar_to_process(struct tar *t)
     1458{
     1459        if (t == NULL) {
     1460                DBG(0, ("Invalid tar context\n"));
     1461                return false;
     1462        }
     1463        return t->to_process;
     1464}
     1465
     1466/**
     1467 * skip_useless_char_in_path - skip leading slashes/dots
     1468 *
     1469 * Skip leading slashes, backslashes and dot-slashes.
     1470 */
     1471static const char* skip_useless_char_in_path(const char *p)
     1472{
     1473        while (p) {
     1474                if (*p == '/' || *p == '\\') {
     1475                        p++;
     1476                }
     1477                else if (p[0] == '.' && (p[1] == '/' || p[1] == '\\')) {
     1478                        p += 2;
     1479                }
     1480                else
     1481                        return p;
     1482        }
     1483        return p;
     1484}
     1485
     1486/**
     1487 * is_subpath - check if the path @sub is a subpath of @full.
     1488 * @sub: path to test
     1489 * @full: container path
     1490 * @_subpath_match: set true if @sub is a subpath of @full, otherwise false
     1491 *
     1492 * String comparaison is case-insensitive.
     1493 */
     1494static NTSTATUS is_subpath(const char *sub, const char *full,
     1495                           bool *_subpath_match)
     1496{
    8381497        NTSTATUS status = NT_STATUS_OK;
    839 
    840         if (strequal(finfo->name,"..") || strequal(finfo->name,".")) {
    841                 status = NT_STATUS_OK;
    842                 goto cleanup;
    843         }
    844 
    845         /* Is it on the exclude list ? */
    846         if (!tar_excl && clipn) {
    847                 char *exclaim;
    848 
    849                 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir())));
    850 
    851                 exclaim = talloc_asprintf(ctx,
    852                                 "%s\\%s",
    853                                 client_get_cur_dir(),
    854                                 finfo->name);
    855                 if (!exclaim) {
    856                         status = NT_STATUS_NO_MEMORY;
    857                         goto cleanup;
    858                 }
    859 
    860                 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
    861 
    862                 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
    863                                 (tar_re_search && mask_match_list(exclaim, cliplist, clipn, True))) {
    864                         DEBUG(3,("Skipping file %s\n", exclaim));
    865                         TALLOC_FREE(exclaim);
    866                         status = NT_STATUS_OK;
    867                         goto cleanup;
    868                 }
    869                 TALLOC_FREE(exclaim);
    870         }
    871 
    872         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
    873                 char *saved_curdir = NULL;
    874                 char *new_cd = NULL;
    875                 char *mtar_mask = NULL;
    876 
    877                 saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
    878                 if (!saved_curdir) {
    879                         status = NT_STATUS_NO_MEMORY;
    880                         goto cleanup;
    881                 }
    882 
    883                 DEBUG(5, ("strlen(cur_dir)=%d, \
    884 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
    885                         (int)strlen(saved_curdir),
    886                         (int)strlen(finfo->name), finfo->name, saved_curdir));
    887 
    888                 new_cd = talloc_asprintf(ctx,
    889                                 "%s%s\\",
    890                                 client_get_cur_dir(),
    891                                 finfo->name);
    892                 if (!new_cd) {
    893                         status = NT_STATUS_NO_MEMORY;
    894                         goto cleanup;
    895                 }
    896                 client_set_cur_dir(new_cd);
    897 
    898                 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir()));
    899 
    900                 /* write a tar directory, don't bother with mode - just
    901                  * set it to 40755 */
    902                 writetarheader(tarhandle, client_get_cur_dir(), 0,
    903                                 finfo->mtime_ts.tv_sec, "040755 \0", '5');
    904                 if (tar_noisy) {
    905                         DEBUG(0,("                directory %s\n",
    906                                 client_get_cur_dir()));
    907                 }
    908                 ntarf++;  /* Make sure we have a file on there */
    909                 mtar_mask = talloc_asprintf(ctx,
    910                                 "%s*",
    911                                 client_get_cur_dir());
    912                 if (!mtar_mask) {
    913                         status = NT_STATUS_NO_MEMORY;
    914                         goto cleanup;
    915                 }
    916                 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask));
    917                 do_list(mtar_mask, attribute, do_tar, False, True);
    918                 client_set_cur_dir(saved_curdir);
    919                 TALLOC_FREE(saved_curdir);
    920                 TALLOC_FREE(new_cd);
    921                 TALLOC_FREE(mtar_mask);
    922         } else {
    923                 char *rname = talloc_asprintf(ctx,
    924                                         "%s%s",
    925                                         client_get_cur_dir(),
    926                                         finfo->name);
    927                 if (!rname) {
    928                         status = NT_STATUS_NO_MEMORY;
    929                         goto cleanup;
    930                 }
    931                 status = do_atar(rname,finfo->name,finfo);
    932                 TALLOC_FREE(rname);
    933         }
    934 
    935   cleanup:
    936         TALLOC_FREE(ctx);
     1498        int len = 0;
     1499        char *f, *s;
     1500        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     1501        if (tmp_ctx == NULL) {
     1502                status = NT_STATUS_NO_MEMORY;
     1503                goto out;
     1504        }
     1505
     1506        f = strlower_talloc(tmp_ctx, full);
     1507        if (f == NULL) {
     1508                status = NT_STATUS_NO_MEMORY;
     1509                goto out_ctx_free;
     1510        }
     1511        string_replace(f, '\\', '/');
     1512        s = strlower_talloc(tmp_ctx, sub);
     1513        if (f == NULL) {
     1514                status = NT_STATUS_NO_MEMORY;
     1515                goto out_ctx_free;
     1516        }
     1517        string_replace(s, '\\', '/');
     1518
     1519        /* find the point where sub and full diverge */
     1520        while ((*f != '\0') && (*s != '\0') && (*f == *s)) {
     1521                f++;
     1522                s++;
     1523                len++;
     1524        }
     1525
     1526        if ((*f == '\0') && (*s == '\0')) {
     1527                *_subpath_match = true; /* sub and full match */
     1528                goto out_ctx_free;
     1529        }
     1530
     1531        if ((*f == '\0') && (len > 0) && (*(f - 1) == '/')) {
     1532                /* sub diverges from full at path separator */
     1533                *_subpath_match = true;
     1534                goto out_ctx_free;
     1535        }
     1536
     1537        if ((*s == '\0') && (strcmp(f, "/") == 0)) {
     1538                /* full diverges from sub with trailing slash only */
     1539                *_subpath_match = true;
     1540                goto out_ctx_free;
     1541        }
     1542
     1543        if ((*s == '/') && (*f == '\0')) {
     1544                /* sub diverges from full with extra path component */
     1545                *_subpath_match = true;
     1546                goto out_ctx_free;
     1547        }
     1548        *_subpath_match = false;
     1549
     1550out_ctx_free:
     1551        talloc_free(tmp_ctx);
     1552out:
    9371553        return status;
    9381554}
    9391555
    940 /****************************************************************************
    941 Convert from UNIX to DOS file names
    942 ***************************************************************************/
    943 
    944 static void unfixtarname(char *tptr, char *fp, int l, bool first)
    945 {
    946         /* remove '.' from start of file name, convert from unix /'s to
    947          * dos \'s in path. Kill any absolute path names. But only if first!
     1556
     1557/**
     1558 * make_remote_path - recursively make remote dirs
     1559 * @full_path: full hierarchy to create
     1560 *
     1561 * Create @full_path and each parent directories as needed.
     1562 */
     1563static int make_remote_path(const char *full_path)
     1564{
     1565        extern struct cli_state *cli;
     1566        char *path;
     1567        char *subpath;
     1568        char *state;
     1569        char *last_backslash;
     1570        char *p;
     1571        int len;
     1572        NTSTATUS status;
     1573        int err = 0;
     1574        TALLOC_CTX *ctx = talloc_new(NULL);
     1575        if (ctx == NULL) {
     1576                return 1;
     1577        }
     1578
     1579        subpath = talloc_strdup(ctx, full_path);
     1580        if (subpath == NULL) {
     1581                err = 1;
     1582                goto out;
     1583        }
     1584        path = talloc_strdup(ctx, full_path);
     1585        if (path == NULL) {
     1586                err = 1;
     1587                goto out;
     1588        }
     1589        len = talloc_get_size(path) - 1;
     1590
     1591        last_backslash = strrchr_m(path, '\\');
     1592        if (last_backslash == NULL) {
     1593                goto out;
     1594        }
     1595
     1596        *last_backslash = 0;
     1597
     1598        subpath[0] = 0;
     1599        p = strtok_r(path, "\\", &state);
     1600
     1601        while (p != NULL) {
     1602                strlcat(subpath, p, len);
     1603                status = cli_chkpath(cli, subpath);
     1604                if (!NT_STATUS_IS_OK(status)) {
     1605                        status = cli_mkdir(cli, subpath);
     1606                        if (!NT_STATUS_IS_OK(status)) {
     1607                                DBG(0, ("Can't mkdir %s: %s\n", subpath, nt_errstr(status)));
     1608                                err = 1;
     1609                                goto out;
     1610                        }
     1611                        DBG(3, ("mkdir %s\n", subpath));
     1612                }
     1613
     1614                strlcat(subpath, "\\", len);
     1615                p = strtok_r(NULL, "/\\", &state);
     1616
     1617        }
     1618
     1619out:
     1620        talloc_free(ctx);
     1621        return err;
     1622}
     1623
     1624/**
     1625 * tar_reset_mem_context - reset talloc context associated with @t
     1626 *
     1627 * At the start of the program the context is NULL so a new one is
     1628 * allocated. On the following runs (interactive session only), simply
     1629 * free the children.
     1630 */
     1631static TALLOC_CTX *tar_reset_mem_context(struct tar *t)
     1632{
     1633        tar_free_mem_context(t);
     1634        t->talloc_ctx = talloc_new(NULL);
     1635        return t->talloc_ctx;
     1636}
     1637
     1638/**
     1639 * tar_free_mem_context - free talloc context associated with @t
     1640 */
     1641static void tar_free_mem_context(struct tar *t)
     1642{
     1643        if (t->talloc_ctx) {
     1644                talloc_free(t->talloc_ctx);
     1645                t->talloc_ctx = NULL;
     1646                t->path_list_size = 0;
     1647                t->path_list = NULL;
     1648                t->tar_path = NULL;
     1649        }
     1650}
     1651
     1652#define XSET(v)      [v] = #v
     1653#define XTABLE(v, t) DBG(2, ("DUMP:%-20.20s = %s\n", #v, t[v]))
     1654#define XBOOL(v)     DBG(2, ("DUMP:%-20.20s = %d\n", #v, v ? 1 : 0))
     1655#define XSTR(v)      DBG(2, ("DUMP:%-20.20s = %s\n", #v, v ? v : "NULL"))
     1656#define XINT(v)      DBG(2, ("DUMP:%-20.20s = %d\n", #v, v))
     1657#define XUINT64(v)   DBG(2, ("DUMP:%-20.20s = %" PRIu64  "\n", #v, v))
     1658
     1659/**
     1660 * tar_dump - dump tar structure on stdout
     1661 */
     1662static void tar_dump(struct tar *t)
     1663{
     1664        int i;
     1665        const char* op[] = {
     1666                XSET(TAR_NO_OPERATION),
     1667                XSET(TAR_CREATE),
     1668                XSET(TAR_EXTRACT),
     1669        };
     1670
     1671        const char* sel[] = {
     1672                XSET(TAR_NO_SELECTION),
     1673                XSET(TAR_INCLUDE),
     1674                XSET(TAR_EXCLUDE),
     1675        };
     1676
     1677        XBOOL(t->to_process);
     1678        XTABLE(t->mode.operation, op);
     1679        XTABLE(t->mode.selection, sel);
     1680        XINT(t->mode.blocksize);
     1681        XBOOL(t->mode.hidden);
     1682        XBOOL(t->mode.system);
     1683        XBOOL(t->mode.incremental);
     1684        XBOOL(t->mode.reset);
     1685        XBOOL(t->mode.dry);
     1686        XBOOL(t->mode.verbose);
     1687        XUINT64(t->total_size);
     1688        XSTR(t->tar_path);
     1689        XINT(t->path_list_size);
     1690
     1691        for (i = 0; t->path_list && t->path_list[i]; i++) {
     1692                DBG(2, ("DUMP: t->path_list[%2d] = %s\n", i, t->path_list[i]));
     1693        }
     1694
     1695        DBG(2, ("DUMP:t->path_list @ %p (%d elem)\n", t->path_list, i));
     1696}
     1697#undef XSET
     1698#undef XTABLE
     1699#undef XBOOL
     1700#undef XSTR
     1701#undef XINT
     1702
     1703/**
     1704 * max_token - return upper limit for the number of token in @str
     1705 *
     1706 * The result is not exact, the actual number of token might be less
     1707 * than what is returned.
     1708 */
     1709static int max_token(const char *str)
     1710{
     1711        const char *s;
     1712        int nb = 0;
     1713
     1714        if (str == NULL) {
     1715                return 0;
     1716        }
     1717
     1718        s = str;
     1719        while (s[0] != '\0') {
     1720                if (isspace((int)s[0])) {
     1721                        nb++;
     1722                }
     1723                s++;
     1724        }
     1725
     1726        nb++;
     1727
     1728        return nb;
     1729}
     1730
     1731/**
     1732 * fix_unix_path - convert @path to a DOS path
     1733 * @path: path to convert
     1734 * @removeprefix: if true, remove leading ./ or /.
     1735 */
     1736static char *fix_unix_path(char *path, bool do_remove_prefix)
     1737{
     1738        char *from = path, *to = path;
     1739
     1740        if (path == NULL || path[0] == '\0') {
     1741                return path;
     1742        }
     1743
     1744        /* remove prefix:
     1745         * ./path => path
     1746         *  /path => path
    9481747         */
    949 
    950         DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
    951 
    952         if (first) {
    953                 if (*fp == '.') {
    954                         fp++;
    955                         l--;
    956                 }
    957                 if (*fp == '\\' || *fp == '/') {
    958                         fp++;
    959                         l--;
    960                 }
    961         }
    962 
    963         safe_strcpy(tptr, fp, l);
    964         string_replace(tptr, '/', '\\');
    965 }
    966 
    967 /****************************************************************************
    968 Move to the next block in the buffer, which may mean read in another set of
    969 blocks. FIXME, we should allow more than one block to be skipped.
    970 ****************************************************************************/
    971 
    972 static int next_block(char *ltarbuf, char **bufferp, int bufsiz)
    973 {
    974         int bufread, total = 0;
    975 
    976         DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp));
    977         *bufferp += TBLOCK;
    978         total = TBLOCK;
    979 
    980         if (*bufferp >= (ltarbuf + bufsiz)) {
    981 
    982                 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
    983 
    984                 /*
    985                  * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
    986                  * Fixes bug where read can return short if coming from
    987                  * a pipe.
    988                  */
    989 
    990                 bufread = read(tarhandle, ltarbuf, bufsiz);
    991                 total = bufread;
    992 
    993                 while (total < bufsiz) {
    994                         if (bufread < 0) { /* An error, return false */
    995                                 return (total > 0 ? -2 : bufread);
    996                         }
    997                         if (bufread == 0) {
    998                                 if (total <= 0) {
    999                                         return -2;
    1000                                 }
    1001                                 break;
    1002                         }
    1003                         bufread = read(tarhandle, &ltarbuf[total], bufsiz - total);
    1004                         total += bufread;
    1005                 }
    1006 
    1007                 DEBUG(5, ("Total bytes read ... %i\n", total));
    1008 
    1009                 *bufferp = ltarbuf;
    1010         }
    1011 
    1012         return(total);
    1013 }
    1014 
    1015 /* Skip a file, even if it includes a long file name? */
    1016 static int skip_file(int skipsize)
    1017 {
    1018         int dsize = skipsize;
    1019 
    1020         DEBUG(5, ("Skiping file. Size = %i\n", skipsize));
    1021 
    1022         /* FIXME, we should skip more than one block at a time */
    1023 
    1024         while (dsize > 0) {
    1025                 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
    1026                         DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
    1027                         return(False);
    1028                 }
    1029                 dsize -= TBLOCK;
    1030         }
    1031 
    1032         return(True);
    1033 }
    1034 
    1035 /*************************************************************
    1036  Get a file from the tar file and store it.
    1037  When this is called, tarbuf already contains the first
    1038  file block. This is a bit broken & needs fixing.
    1039 **************************************************************/
    1040 
    1041 static int get_file(file_info2 finfo)
    1042 {
    1043         uint16_t fnum = (uint16_t) -1;
    1044         int dsize = 0, bpos = 0;
    1045         uint64_t rsize = 0, pos = 0;
    1046         NTSTATUS status;
    1047 
    1048         DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo.name, (double)finfo.size));
    1049 
    1050         if (!ensurepath(finfo.name)) {
    1051                 DEBUG(0, ("abandoning restore\n"));
    1052                 return False;
    1053         }
    1054 
    1055         status = cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
    1056         if (!NT_STATUS_IS_OK(status)) {
    1057                 DEBUG(0, ("abandoning restore\n"));
    1058                 return False;
    1059         }
    1060 
    1061         /* read the blocks from the tar file and write to the remote file */
    1062 
    1063         rsize = finfo.size;  /* This is how much to write */
    1064 
    1065         while (rsize > 0) {
    1066 
    1067                 /* We can only write up to the end of the buffer */
    1068                 dsize = MIN(tbufsiz - (buffer_p - tarbuf) - bpos, 65520); /* Calculate the size to write */
    1069                 dsize = MIN(dsize, rsize);  /* Should be only what is left */
    1070                 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize, bpos));
    1071 
    1072                 status = cli_writeall(cli, fnum, 0,
    1073                                       (uint8_t *)(buffer_p + bpos), pos,
    1074                                       dsize, NULL);
    1075                 if (!NT_STATUS_IS_OK(status)) {
    1076                         DEBUG(0, ("Error writing remote file: %s\n",
    1077                                   nt_errstr(status)));
    1078                         return 0;
    1079                 }
    1080 
    1081                 rsize -= dsize;
    1082                 pos += dsize;
    1083 
    1084                 /* Now figure out how much to move in the buffer */
    1085 
    1086                 /* FIXME, we should skip more than one block at a time */
    1087 
    1088                 /* First, skip any initial part of the part written that is left over */
    1089                 /* from the end of the first TBLOCK                                   */
    1090 
    1091                 if ((bpos) && ((bpos + dsize) >= TBLOCK)) {
    1092                         dsize -= (TBLOCK - bpos);  /* Get rid of the end of the first block */
    1093                         bpos = 0;
    1094 
    1095                         if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {  /* and skip the block */
    1096                                 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
    1097                                 return False;
    1098                         }
    1099                 }
    1100 
    1101                 /*
    1102                  * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
    1103                  * If the file being extracted is an exact multiple of
    1104                  * TBLOCK bytes then we don't want to extract the next
    1105                  * block from the tarfile here, as it will be done in
    1106                  * the caller of get_file().
    1107                  */
    1108 
    1109                 while (((rsize != 0) && (dsize >= TBLOCK)) ||
    1110                                 ((rsize == 0) && (dsize > TBLOCK))) {
    1111 
    1112                         if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
    1113                                 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
    1114                                 return False;
    1115                         }
    1116 
    1117                         dsize -= TBLOCK;
    1118                 }
    1119                 bpos = dsize;
    1120         }
    1121 
    1122         /* Now close the file ... */
    1123 
    1124         if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
    1125                 DEBUG(0, ("Error %s closing remote file\n",
    1126                         cli_errstr(cli)));
    1127                 return(False);
    1128         }
    1129 
    1130         /* Now we update the creation date ... */
    1131         DEBUG(5, ("Updating creation date on %s\n", finfo.name));
    1132 
    1133         if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime_ts.tv_sec))) {
    1134                 if (tar_real_noisy) {
    1135                         DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
    1136                         /*return(False); */ /* Ignore, as Win95 does not allow changes */
    1137                 }
    1138         }
    1139 
    1140         ntarf++;
    1141         DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo.name, (double)finfo.size));
    1142         return(True);
    1143 }
    1144 
    1145 /* Create a directory.  We just ensure that the path exists and return as there
    1146    is no file associated with a directory
    1147 */
    1148 static int get_dir(file_info2 finfo)
    1149 {
    1150         DEBUG(0, ("restore directory %s\n", finfo.name));
    1151 
    1152         if (!ensurepath(finfo.name)) {
    1153                 DEBUG(0, ("Problems creating directory\n"));
    1154                 return(False);
    1155         }
    1156         ntarf++;
    1157         return(True);
    1158 }
    1159 
    1160 /* Get a file with a long file name ... first file has file name, next file
    1161    has the data. We only want the long file name, as the loop in do_tarput
    1162    will deal with the rest.
    1163 */
    1164 static char *get_longfilename(file_info2 finfo)
    1165 {
    1166         /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
    1167          * header call. */
    1168         int namesize = finfo.size + strlen(client_get_cur_dir()) + 2;
    1169         char *longname = (char *)SMB_MALLOC(namesize);
    1170         int offset = 0, left = finfo.size;
    1171         bool first = True;
    1172 
    1173         DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
    1174         DEBUG(5, ("Len = %.0f\n", (double)finfo.size));
    1175 
    1176         if (longname == NULL) {
    1177                 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize));
    1178                 return(NULL);
    1179         }
    1180 
    1181         /* First, add cur_dir to the long file name */
    1182 
    1183         if (strlen(client_get_cur_dir()) > 0) {
    1184                 strncpy(longname, client_get_cur_dir(), namesize);
    1185                 offset = strlen(client_get_cur_dir());
    1186         }
    1187 
    1188         /* Loop through the blocks picking up the name */
    1189 
    1190         while (left > 0) {
    1191                 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
    1192                         DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
    1193                         SAFE_FREE(longname);
    1194                         return(NULL);
    1195                 }
    1196 
    1197                 unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
    1198                 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
    1199 
    1200                 offset += TBLOCK;
    1201                 left -= TBLOCK;
    1202         }
    1203 
    1204         return(longname);
    1205 }
    1206 
    1207 static void do_tarput(void)
    1208 {
    1209         file_info2 finfo;
    1210         struct timespec tp_start;
    1211         char *longfilename = NULL, linkflag;
    1212         int skip = False;
    1213 
    1214         ZERO_STRUCT(finfo);
    1215 
    1216         clock_gettime_mono(&tp_start);
    1217         DEBUG(5, ("RJS do_tarput called ...\n"));
    1218 
    1219         buffer_p = tarbuf + tbufsiz;  /* init this to force first read */
    1220 
    1221         /* Now read through those files ... */
    1222         while (True) {
    1223                 /* Get us to the next block, or the first block first time around */
    1224                 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
    1225                         DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
    1226                         SAFE_FREE(longfilename);
    1227                         return;
    1228                 }
    1229 
    1230                 DEBUG(5, ("Reading the next header ...\n"));
    1231 
    1232                 switch (readtarheader((union hblock *) buffer_p,
    1233                                         &finfo, client_get_cur_dir())) {
    1234                         case -2:    /* Hmm, not good, but not fatal */
    1235                                 DEBUG(0, ("Skipping %s...\n", finfo.name));
    1236                                 if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) && !skip_file(finfo.size)) {
    1237                                         DEBUG(0, ("Short file, bailing out...\n"));
    1238                                         SAFE_FREE(longfilename);
    1239                                         return;
    1240                                 }
    1241                                 break;
    1242 
    1243                         case -1:
    1244                                 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
    1245                                 SAFE_FREE(longfilename);
    1246                                 return;
    1247 
    1248                         case 0: /* chksum is zero - looks like an EOF */
    1249                                 DEBUG(0, ("tar: restored %d files and directories\n", ntarf));
    1250                                 SAFE_FREE(longfilename);
    1251                                 return;        /* Hmmm, bad here ... */
    1252 
    1253                         default:
    1254                                 /* No action */
    1255                                 break;
    1256                 }
    1257 
    1258                 /* Now, do we have a long file name? */
    1259                 if (longfilename != NULL) {
    1260                         SAFE_FREE(finfo.name);   /* Free the space already allocated */
    1261                         finfo.name = longfilename;
    1262                         longfilename = NULL;
    1263                 }
    1264 
    1265                 /* Well, now we have a header, process the file ...            */
    1266                 /* Should we skip the file? We have the long name as well here */
    1267                 skip = clipn && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl) ||
    1268                                         (tar_re_search && mask_match_list(finfo.name, cliplist, clipn, True)));
    1269 
    1270                 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
    1271                 if (skip) {
    1272                         skip_file(finfo.size);
    1273                         continue;
    1274                 }
    1275 
    1276                 /* We only get this far if we should process the file */
    1277                 linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag;
    1278                 switch (linkflag) {
    1279                         case '0':  /* Should use symbolic names--FIXME */
    1280                                 /*
    1281                                  * Skip to the next block first, so we can get the file, FIXME, should
    1282                                  * be in get_file ...
    1283                                  * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
    1284                                  * Fixes bug where file size in tarfile is zero.
    1285                                  */
    1286                                 if ((finfo.size != 0) && next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
    1287                                         DEBUG(0, ("Short file, bailing out...\n"));
    1288                                         return;
    1289                                 }
    1290                                 if (!get_file(finfo)) {
    1291                                         DEBUG(0, ("Abandoning restore\n"));
    1292                                         return;
    1293                                 }
    1294                                 break;
    1295                         case '5':
    1296                                 if (!get_dir(finfo)) {
    1297                                         DEBUG(0, ("Abandoning restore \n"));
    1298                                         return;
    1299                                 }
    1300                                 break;
    1301                         case 'L':
    1302                                 SAFE_FREE(longfilename);
    1303                                 longfilename = get_longfilename(finfo);
    1304                                 if (!longfilename) {
    1305                                         DEBUG(0, ("abandoning restore\n"));
    1306                                         return;
    1307                                 }
    1308                                 DEBUG(5, ("Long file name: %s\n", longfilename));
    1309                                 break;
    1310 
    1311                         default:
    1312                                 skip_file(finfo.size);  /* Don't handle these yet */
    1313                                 break;
    1314                 }
    1315         }
    1316 }
    1317 
    1318 /*
    1319  * samba interactive commands
    1320  */
    1321 
    1322 /****************************************************************************
    1323 Blocksize command
    1324 ***************************************************************************/
     1748        if (do_remove_prefix) {
     1749                /* /path */
     1750                if (path[0] == '/' || path[0] == '\\') {
     1751                        from += 1;
     1752                }
     1753
     1754                /* ./path */
     1755                if (path[1] != '\0' && path[0] == '.' && (path[1] == '/' || path[1] == '\\')) {
     1756                        from += 2;
     1757                }
     1758        }
     1759
     1760        /* replace / with \ */
     1761        while (from[0] != '\0') {
     1762                if (from[0] == '/') {
     1763                        to[0] = '\\';
     1764                } else {
     1765                        to[0] = from[0];
     1766                }
     1767
     1768                from++;
     1769                to++;
     1770        }
     1771        to[0] = '\0';
     1772
     1773        return path;
     1774}
     1775
     1776/**
     1777 * path_base_name - return @path basename
     1778 *
     1779 * If @path doesn't contain any directory separator return NULL.
     1780 */
     1781static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base)
     1782{
     1783        char *base = NULL;
     1784        int last = -1;
     1785        int i;
     1786
     1787        for (i = 0; path[i]; i++) {
     1788                if (path[i] == '\\' || path[i] == '/') {
     1789                        last = i;
     1790                }
     1791        }
     1792
     1793        if (last >= 0) {
     1794                base = talloc_strdup(ctx, path);
     1795                if (base == NULL) {
     1796                        return NT_STATUS_NO_MEMORY;
     1797                }
     1798
     1799                base[last] = 0;
     1800        }
     1801
     1802        *_base = base;
     1803        return NT_STATUS_OK;
     1804}
     1805
     1806#else
     1807
     1808#define NOT_IMPLEMENTED DEBUG(0, ("tar mode not compiled. build with --with-libarchive\n"))
    13251809
    13261810int cmd_block(void)
    13271811{
    1328         TALLOC_CTX *ctx = talloc_tos();
    1329         char *buf;
    1330         int block;
    1331 
    1332         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    1333                 DEBUG(0, ("blocksize <n>\n"));
    1334                 return 1;
    1335         }
    1336 
    1337         block=atoi(buf);
    1338         if (block < 0 || block > 65535) {
    1339                 DEBUG(0, ("blocksize out of range"));
    1340                 return 1;
    1341         }
    1342 
    1343         blocksize=block;
    1344         DEBUG(2,("blocksize is now %d\n", blocksize));
    1345         return 0;
    1346 }
    1347 
    1348 /****************************************************************************
    1349 command to set incremental / reset mode
    1350 ***************************************************************************/
     1812        NOT_IMPLEMENTED;
     1813        return 1;
     1814}
    13511815
    13521816int cmd_tarmode(void)
    13531817{
    1354         TALLOC_CTX *ctx = talloc_tos();
    1355         char *buf;
    1356 
    1357         while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    1358                 if (strequal(buf, "full"))
    1359                         tar_inc=False;
    1360                 else if (strequal(buf, "inc"))
    1361                         tar_inc=True;
    1362                 else if (strequal(buf, "reset"))
    1363                         tar_reset=True;
    1364                 else if (strequal(buf, "noreset"))
    1365                         tar_reset=False;
    1366                 else if (strequal(buf, "system"))
    1367                         tar_system=True;
    1368                 else if (strequal(buf, "nosystem"))
    1369                         tar_system=False;
    1370                 else if (strequal(buf, "hidden"))
    1371                         tar_hidden=True;
    1372                 else if (strequal(buf, "nohidden"))
    1373                         tar_hidden=False;
    1374                 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
    1375                         tar_noisy=True;
    1376                 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
    1377                         tar_noisy=False;
    1378                 else
    1379                         DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
    1380                 TALLOC_FREE(buf);
    1381         }
    1382 
    1383         DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
    1384                         tar_inc ? "incremental" : "full",
    1385                         tar_system ? "system" : "nosystem",
    1386                         tar_hidden ? "hidden" : "nohidden",
    1387                         tar_reset ? "reset" : "noreset",
    1388                         tar_noisy ? "verbose" : "quiet"));
    1389         return 0;
    1390 }
    1391 
    1392 /****************************************************************************
    1393 Feeble attrib command
    1394 ***************************************************************************/
    1395 
    1396 int cmd_setmode(void)
    1397 {
    1398         TALLOC_CTX *ctx = talloc_tos();
    1399         char *q;
    1400         char *buf;
    1401         char *fname = NULL;
    1402         uint16 attra[2];
    1403         int direct=1;
    1404 
    1405         attra[0] = attra[1] = 0;
    1406 
    1407         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    1408                 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
    1409                 return 1;
    1410         }
    1411 
    1412         fname = talloc_asprintf(ctx,
    1413                                 "%s%s",
    1414                                 client_get_cur_dir(),
    1415                                 buf);
    1416         if (!fname) {
    1417                 return 1;
    1418         }
    1419 
    1420         while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    1421                 q=buf;
    1422 
    1423                 while(*q) {
    1424                         switch (*q++) {
    1425                                 case '+':
    1426                                         direct=1;
    1427                                         break;
    1428                                 case '-':
    1429                                         direct=0;
    1430                                         break;
    1431                                 case 'r':
    1432                                         attra[direct]|=FILE_ATTRIBUTE_READONLY;
    1433                                         break;
    1434                                 case 'h':
    1435                                         attra[direct]|=FILE_ATTRIBUTE_HIDDEN;
    1436                                         break;
    1437                                 case 's':
    1438                                         attra[direct]|=FILE_ATTRIBUTE_SYSTEM;
    1439                                         break;
    1440                                 case 'a':
    1441                                         attra[direct]|=FILE_ATTRIBUTE_ARCHIVE;
    1442                                         break;
    1443                                 default:
    1444                                         DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
    1445                                         return 1;
    1446                         }
    1447                 }
    1448         }
    1449 
    1450         if (attra[ATTRSET]==0 && attra[ATTRRESET]==0) {
    1451                 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
    1452                 return 1;
    1453         }
    1454 
    1455         DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
    1456         do_setrattr(fname, attra[ATTRSET], ATTRSET);
    1457         do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
    1458         return 0;
    1459 }
    1460 
    1461 /**
    1462  Convert list of tokens to array; dependent on above routine.
    1463  Uses the global cmd_ptr from above - bit of a hack.
    1464 **/
    1465 
    1466 static char **toktocliplist(int *ctok, const char *sep)
    1467 {
    1468         char *s=(char *)cmd_ptr;
    1469         int ictok=0;
    1470         char **ret, **iret;
    1471 
    1472         if (!sep)
    1473                 sep = " \t\n\r";
    1474 
    1475         while(*s && strchr_m(sep,*s))
    1476                 s++;
    1477 
    1478         /* nothing left? */
    1479         if (!*s)
    1480                 return(NULL);
    1481 
    1482         do {
    1483                 ictok++;
    1484                 while(*s && (!strchr_m(sep,*s)))
    1485                         s++;
    1486                 while(*s && strchr_m(sep,*s))
    1487                         *s++=0;
    1488         } while(*s);
    1489 
    1490         *ctok=ictok;
    1491         s=(char *)cmd_ptr;
    1492 
    1493         if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
    1494                 return NULL;
    1495 
    1496         while(ictok--) {
    1497                 *iret++=s;
    1498                 if (ictok > 0) {
    1499                         while(*s++)
    1500                                 ;
    1501                         while(!*s)
    1502                                 s++;
    1503                 }
    1504         }
    1505 
    1506         ret[*ctok] = NULL;
    1507         return ret;
    1508 }
    1509 
    1510 /****************************************************************************
    1511 Principal command for creating / extracting
    1512 ***************************************************************************/
     1818        NOT_IMPLEMENTED;
     1819        return 1;
     1820}
    15131821
    15141822int cmd_tar(void)
    15151823{
    1516         TALLOC_CTX *ctx = talloc_tos();
    1517         char *buf;
    1518         char **argl = NULL;
    1519         int argcl = 0;
    1520         int ret;
    1521 
    1522         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
    1523                 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
    1524                 return 1;
    1525         }
    1526 
    1527         argl=toktocliplist(&argcl, NULL);
    1528         if (!tar_parseargs(argcl, argl, buf, 0)) {
    1529                 SAFE_FREE(argl);
    1530                 return 1;
    1531         }
    1532 
    1533         ret = process_tar();
    1534         SAFE_FREE(argl);
    1535         return ret;
    1536 }
    1537 
    1538 /****************************************************************************
    1539 Command line (option) version
    1540 ***************************************************************************/
    1541 
    1542 int process_tar(void)
    1543 {
    1544         TALLOC_CTX *ctx = talloc_tos();
    1545         int rc = 0;
    1546         initarbuf();
    1547         switch(tar_type) {
    1548                 case 'x':
    1549 
    1550 #if 0
    1551                         do_tarput2();
    1552 #else
    1553                         do_tarput();
     1824        NOT_IMPLEMENTED;
     1825        return 1;
     1826}
     1827
     1828int tar_process(struct tar* tar)
     1829{
     1830        NOT_IMPLEMENTED;
     1831        return 1;
     1832}
     1833
     1834int tar_parse_args(struct tar *tar, const char *flag, const char **val, int valsize)
     1835{
     1836        NOT_IMPLEMENTED;
     1837        return 1;
     1838}
     1839
     1840bool tar_to_process(struct tar *tar)
     1841{
     1842        return false;
     1843}
     1844
     1845struct tar *tar_get_ctx()
     1846{
     1847        return NULL;
     1848}
     1849
    15541850#endif
    1555                         SAFE_FREE(tarbuf);
    1556                         close(tarhandle);
    1557                         break;
    1558                 case 'r':
    1559                 case 'c':
    1560                         if (clipn && tar_excl) {
    1561                                 int i;
    1562                                 char *tarmac = NULL;
    1563 
    1564                                 for (i=0; i<clipn; i++) {
    1565                                         DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
    1566 
    1567                                         if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
    1568                                                 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
    1569                                         }
    1570 
    1571                                         if (strrchr_m(cliplist[i], '\\')) {
    1572                                                 char *p;
    1573                                                 char saved_char;
    1574                                                 char *saved_dir = talloc_strdup(ctx,
    1575                                                                         client_get_cur_dir());
    1576                                                 if (!saved_dir) {
    1577                                                         return 1;
    1578                                                 }
    1579 
    1580                                                 if (*cliplist[i]=='\\') {
    1581                                                         tarmac = talloc_strdup(ctx,
    1582                                                                         cliplist[i]);
    1583                                                 } else {
    1584                                                         tarmac = talloc_asprintf(ctx,
    1585                                                                         "%s%s",
    1586                                                                         client_get_cur_dir(),
    1587                                                                         cliplist[i]);
    1588                                                 }
    1589                                                 if (!tarmac) {
    1590                                                         return 1;
    1591                                                 }
    1592                                                 /*
    1593                                                  * Strip off the last \\xxx
    1594                                                  * xxx element of tarmac to set
    1595                                                  * it as current directory.
    1596                                                  */
    1597                                                 p = strrchr_m(tarmac, '\\');
    1598                                                 if (!p) {
    1599                                                         return 1;
    1600                                                 }
    1601                                                 saved_char = p[1];
    1602                                                 p[1] = '\0';
    1603 
    1604                                                 client_set_cur_dir(tarmac);
    1605 
    1606                                                 /*
    1607                                                  * Restore the character we
    1608                                                  * just replaced to
    1609                                                  * put the pathname
    1610                                                  * back as it was.
    1611                                                  */
    1612                                                 p[1] = saved_char;
    1613 
    1614                                                 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
    1615                                                 do_list(tarmac,attribute,do_tar, False, True);
    1616 
    1617                                                 client_set_cur_dir(saved_dir);
    1618 
    1619                                                 TALLOC_FREE(saved_dir);
    1620                                                 TALLOC_FREE(tarmac);
    1621                                         } else {
    1622                                                 tarmac = talloc_asprintf(ctx,
    1623                                                                 "%s%s",
    1624                                                                 client_get_cur_dir(),
    1625                                                                 cliplist[i]);
    1626                                                 if (!tarmac) {
    1627                                                         return 1;
    1628                                                 }
    1629                                                 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
    1630                                                 do_list(tarmac,attribute,do_tar, False, True);
    1631                                                 TALLOC_FREE(tarmac);
    1632                                         }
    1633                                 }
    1634                         } else {
    1635                                 char *mask = talloc_asprintf(ctx,
    1636                                                         "%s\\*",
    1637                                                         client_get_cur_dir());
    1638                                 if (!mask) {
    1639                                         return 1;
    1640                                 }
    1641                                 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask));
    1642                                 do_list(mask,attribute,do_tar,False, True);
    1643                                 TALLOC_FREE(mask);
    1644                         }
    1645 
    1646                         if (ntarf) {
    1647                                 dotareof(tarhandle);
    1648                         }
    1649                         close(tarhandle);
    1650                         SAFE_FREE(tarbuf);
    1651 
    1652                         DEBUG(0, ("tar: dumped %d files and directories\n", ntarf));
    1653                         DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf));
    1654                         break;
    1655         }
    1656 
    1657         if (must_free_cliplist) {
    1658                 int i;
    1659                 for (i = 0; i < clipn; ++i) {
    1660                         SAFE_FREE(cliplist[i]);
    1661                 }
    1662                 SAFE_FREE(cliplist);
    1663                 cliplist = NULL;
    1664                 clipn = 0;
    1665                 must_free_cliplist = False;
    1666         }
    1667         return rc;
    1668 }
    1669 
    1670 /****************************************************************************
    1671 Find a token (filename) in a clip list
    1672 ***************************************************************************/
    1673 
    1674 static int clipfind(char **aret, int ret, char *tok)
    1675 {
    1676         if (aret==NULL)
    1677                 return 0;
    1678 
    1679         /* ignore leading slashes or dots in token */
    1680         while(strchr_m("/\\.", *tok))
    1681                 tok++;
    1682 
    1683         while(ret--) {
    1684                 char *pkey=*aret++;
    1685 
    1686                 /* ignore leading slashes or dots in list */
    1687                 while(strchr_m("/\\.", *pkey))
    1688                         pkey++;
    1689 
    1690                 if (!strslashcmp(pkey, tok))
    1691                         return 1;
    1692         }
    1693         return 0;
    1694 }
    1695 
    1696 /****************************************************************************
    1697 Read list of files to include from the file and initialize cliplist
    1698 accordingly.
    1699 ***************************************************************************/
    1700 
    1701 static int read_inclusion_file(char *filename)
    1702 {
    1703         XFILE *inclusion = NULL;
    1704         char buf[PATH_MAX + 1];
    1705         char *inclusion_buffer = NULL;
    1706         int inclusion_buffer_size = 0;
    1707         int inclusion_buffer_sofar = 0;
    1708         char *p;
    1709         char *tmpstr;
    1710         int i;
    1711         int error = 0;
    1712 
    1713         clipn = 0;
    1714         buf[PATH_MAX] = '\0'; /* guarantee null-termination */
    1715         if ((inclusion = x_fopen(filename, O_RDONLY, 0)) == NULL) {
    1716                 /* XXX It would be better to include a reason for failure, but without
    1717                  * autoconf, it's hard to use strerror, sys_errlist, etc.
    1718                  */
    1719                 DEBUG(0,("Unable to open inclusion file %s\n", filename));
    1720                 return 0;
    1721         }
    1722 
    1723         while ((! error) && (x_fgets(buf, sizeof(buf)-1, inclusion))) {
    1724                 if (inclusion_buffer == NULL) {
    1725                         inclusion_buffer_size = 1024;
    1726                         if ((inclusion_buffer = (char *)SMB_MALLOC(inclusion_buffer_size)) == NULL) {
    1727                                 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
    1728                                 error = 1;
    1729                                 break;
    1730                         }
    1731                 }
    1732 
    1733                 if (buf[strlen(buf)-1] == '\n') {
    1734                         buf[strlen(buf)-1] = '\0';
    1735                 }
    1736 
    1737                 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
    1738                         inclusion_buffer_size *= 2;
    1739                         inclusion_buffer = (char *)SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);
    1740                         if (!inclusion_buffer) {
    1741                                 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
    1742                                                 inclusion_buffer_size));
    1743                                 error = 1;
    1744                                 break;
    1745                         }
    1746                 }
    1747 
    1748                 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
    1749                 inclusion_buffer_sofar += strlen(buf) + 1;
    1750                 clipn++;
    1751         }
    1752         x_fclose(inclusion);
    1753 
    1754         if (! error) {
    1755                 /* Allocate an array of clipn + 1 char*'s for cliplist */
    1756                 cliplist = SMB_MALLOC_ARRAY(char *, clipn + 1);
    1757                 if (cliplist == NULL) {
    1758                         DEBUG(0,("failure allocating memory for cliplist\n"));
    1759                         error = 1;
    1760                 } else {
    1761                         cliplist[clipn] = NULL;
    1762                         p = inclusion_buffer;
    1763                         for (i = 0; (! error) && (i < clipn); i++) {
    1764                                 /* set current item to NULL so array will be null-terminated even if
    1765                                                 * malloc fails below. */
    1766                                 cliplist[i] = NULL;
    1767                                 if ((tmpstr = (char *)SMB_MALLOC(strlen(p)+1)) == NULL) {
    1768                                         DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));
    1769                                         error = 1;
    1770                                 } else {
    1771                                         unfixtarname(tmpstr, p, strlen(p) + 1, True);
    1772                                         cliplist[i] = tmpstr;
    1773                                         if ((p = strchr_m(p, '\000')) == NULL) {
    1774                                                 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
    1775                                                 abort();
    1776                                         }
    1777                                 }
    1778                                 ++p;
    1779                         }
    1780                         must_free_cliplist = True;
    1781                 }
    1782         }
    1783 
    1784         SAFE_FREE(inclusion_buffer);
    1785         if (error) {
    1786                 if (cliplist) {
    1787                         char **pp;
    1788                         /* We know cliplist is always null-terminated */
    1789                         for (pp = cliplist; *pp; ++pp) {
    1790                                 SAFE_FREE(*pp);
    1791                         }
    1792                         SAFE_FREE(cliplist);
    1793                         cliplist = NULL;
    1794                         must_free_cliplist = False;
    1795                 }
    1796                 return 0;
    1797         }
    1798 
    1799         /* cliplist and its elements are freed at the end of process_tar. */
    1800         return 1;
    1801 }
    1802 
    1803 /****************************************************************************
    1804 Parse tar arguments. Sets tar_type, tar_excl, etc.
    1805 ***************************************************************************/
    1806 
    1807 int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
    1808 {
    1809         int newOptind = Optind;
    1810         char tar_clipfl='\0';
    1811 
    1812         /* Reset back to defaults - could be from interactive version
    1813          * reset mode and archive mode left as they are though
    1814          */
    1815         tar_type='\0';
    1816         tar_excl=True;
    1817         dry_run=False;
    1818 
    1819         while (*Optarg) {
    1820                 switch(*Optarg++) {
    1821                         case 'c':
    1822                                 tar_type='c';
    1823                                 break;
    1824                         case 'x':
    1825                                 if (tar_type=='c') {
    1826                                         printf("Tar must be followed by only one of c or x.\n");
    1827                                         return 0;
    1828                                 }
    1829                                 tar_type='x';
    1830                                 break;
    1831                         case 'b':
    1832                                 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
    1833                                         DEBUG(0,("Option b must be followed by valid blocksize\n"));
    1834                                         return 0;
    1835                                 } else {
    1836                                         Optind++;
    1837                                         newOptind++;
    1838                                 }
    1839                                 break;
    1840                         case 'g':
    1841                                 tar_inc=True;
    1842                                 break;
    1843                         case 'N':
    1844                                 if (Optind>=argc) {
    1845                                         DEBUG(0,("Option N must be followed by valid file name\n"));
    1846                                         return 0;
    1847                                 } else {
    1848                                         SMB_STRUCT_STAT stbuf;
    1849 
    1850                                         if (sys_stat(argv[Optind], &stbuf,
    1851                                                      false) == 0) {
    1852                                                 newer_than = convert_timespec_to_time_t(
    1853                                                         stbuf.st_ex_mtime);
    1854                                                 DEBUG(1,("Getting files newer than %s",
    1855                                                         time_to_asc(newer_than)));
    1856                                                 newOptind++;
    1857                                                 Optind++;
    1858                                         } else {
    1859                                                 DEBUG(0,("Error setting newer-than time\n"));
    1860                                                 return 0;
    1861                                         }
    1862                                 }
    1863                                 break;
    1864                         case 'a':
    1865                                 tar_reset=True;
    1866                                 break;
    1867                         case 'q':
    1868                                 tar_noisy=False;
    1869                                 break;
    1870                         case 'I':
    1871                                 if (tar_clipfl) {
    1872                                         DEBUG(0,("Only one of I,X,F must be specified\n"));
    1873                                         return 0;
    1874                                 }
    1875                                 tar_clipfl='I';
    1876                                 break;
    1877                         case 'X':
    1878                                 if (tar_clipfl) {
    1879                                         DEBUG(0,("Only one of I,X,F must be specified\n"));
    1880                                         return 0;
    1881                                 }
    1882                                 tar_clipfl='X';
    1883                                 break;
    1884                         case 'F':
    1885                                 if (tar_clipfl) {
    1886                                         DEBUG(0,("Only one of I,X,F must be specified\n"));
    1887                                         return 0;
    1888                                 }
    1889                                 tar_clipfl='F';
    1890                                 break;
    1891                         case 'r':
    1892                                 DEBUG(0, ("tar_re_search set\n"));
    1893                                 tar_re_search = True;
    1894                                 break;
    1895                         case 'n':
    1896                                 if (tar_type == 'c') {
    1897                                         DEBUG(0, ("dry_run set\n"));
    1898                                         dry_run = True;
    1899                                 } else {
    1900                                         DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
    1901                                         return 0;
    1902                                 }
    1903                                 break;
    1904                         default:
    1905                                 DEBUG(0,("Unknown tar option\n"));
    1906                                 return 0;
    1907                 }
    1908         }
    1909 
    1910         if (!tar_type) {
    1911                 printf("Option T must be followed by one of c or x.\n");
    1912                 return 0;
    1913         }
    1914 
    1915         /* tar_excl is true if cliplist lists files to be included.
    1916          * Both 'I' and 'F' mean include. */
    1917         tar_excl=tar_clipfl!='X';
    1918 
    1919         if (tar_clipfl=='F') {
    1920                 if (argc-Optind-1 != 1) {
    1921                         DEBUG(0,("Option F must be followed by exactly one filename.\n"));
    1922                         return 0;
    1923                 }
    1924                 newOptind++;
    1925                 /* Optind points at the tar output file, Optind+1 at the inclusion file. */
    1926                 if (! read_inclusion_file(argv[Optind+1])) {
    1927                         return 0;
    1928                 }
    1929         } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
    1930                 char *tmpstr;
    1931                 char **tmplist;
    1932                 int clipcount;
    1933 
    1934                 cliplist=argv+Optind+1;
    1935                 clipn=argc-Optind-1;
    1936                 clipcount = clipn;
    1937 
    1938                 if ((tmplist=SMB_MALLOC_ARRAY(char *,clipn)) == NULL) {
    1939                         DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn));
    1940                         return 0;
    1941                 }
    1942 
    1943                 for (clipcount = 0; clipcount < clipn; clipcount++) {
    1944 
    1945                         DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
    1946 
    1947                         if ((tmpstr = (char *)SMB_MALLOC(strlen(cliplist[clipcount])+1)) == NULL) {
    1948                                 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount));
    1949                                 SAFE_FREE(tmplist);
    1950                                 return 0;
    1951                         }
    1952 
    1953                         unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);
    1954                         tmplist[clipcount] = tmpstr;
    1955                         DEBUG(5, ("Processed an item, %s\n", tmpstr));
    1956 
    1957                         DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
    1958                 }
    1959 
    1960                 cliplist = tmplist;
    1961                 must_free_cliplist = True;
    1962 
    1963                 newOptind += clipn;
    1964         }
    1965 
    1966         if (Optind+1<argc && tar_re_search && tar_clipfl != 'F') {
    1967                 /* Doing regular expression seaches not from an inclusion file. */
    1968                 clipn=argc-Optind-1;
    1969                 cliplist=argv+Optind+1;
    1970                 newOptind += clipn;
    1971         }
    1972 
    1973         if (Optind>=argc || !strcmp(argv[Optind], "-")) {
    1974                 /* Sets tar handle to either 0 or 1, as appropriate */
    1975                 tarhandle=(tar_type=='c');
    1976                 /*
    1977                  * Make sure that dbf points to stderr if we are using stdout for
    1978                  * tar output
    1979                  */
    1980                 if (tarhandle == 1)  {
    1981                         setup_logging("smbclient", DEBUG_STDERR);
    1982                 }
    1983                 if (!argv[Optind]) {
    1984                         DEBUG(0,("Must specify tar filename\n"));
    1985                         return 0;
    1986                 }
    1987                 if (!strcmp(argv[Optind], "-")) {
    1988                         newOptind++;
    1989                 }
    1990 
    1991         } else {
    1992                 if (tar_type=='c' && dry_run) {
    1993                         tarhandle=-1;
    1994                 } else if ((tar_type=='x' && (tarhandle = sys_open(argv[Optind], O_RDONLY, 0)) == -1)
    1995                                         || (tar_type=='c' && (tarhandle=sys_creat(argv[Optind], 0644)) < 0)) {
    1996                         DEBUG(0,("Error opening local file %s - %s\n", argv[Optind], strerror(errno)));
    1997                         return(0);
    1998                 }
    1999                 newOptind++;
    2000         }
    2001 
    2002         return newOptind;
    2003 }
  • vendor/current/source3/client/dnsbrowse.c

    r740 r988  
    125125        }
    126126
    127         bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
     127        bresult = talloc_array(talloc_tos(), struct mdns_smbsrv_result, 1);
    128128        if (bresult == NULL) {
    129129                return;
     
    169169                int revents;
    170170
    171                 ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, &revents, 1000);
     171                ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, 1000, &revents);
    172172                if (ret <= 0 && errno != EINTR) {
    173173                        break;
  • vendor/current/source3/client/smbspool.c

    r740 r988  
    152152                goto done;
    153153        } else {
    154                 copies = atoi(argv[4]);
     154                char *p = argv[4];
     155                char *endp;
     156
     157                copies = strtol(p, &endp, 10);
     158                if (p == endp) {
     159                        perror("ERROR: Unable to determine number of copies");
     160                        goto done;
     161                }
    155162        }
    156163
     
    246253        setup_logging("smbspool", DEBUG_STDOUT);
    247254
    248         lp_set_in_client(True); /* Make sure that we tell lp_load we are */
    249 
    250         load_case_tables();
    251 
    252         if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, True)) {
     255        smb_init_locale();
     256
     257        if (!lp_load_client(get_dyn_CONFIGFILE())) {
    253258                fprintf(stderr, "ERROR: Can't load %s - run testparm to debug it\n", get_dyn_CONFIGFILE());
    254259                goto done;
     
    342347
    343348
    344         fprintf(stderr, "DEBUG: get_exit_code(cli=%p, nt_status=%x)\n",
    345                 cli, NT_STATUS_V(nt_status));
     349        fprintf(stderr, "DEBUG: get_exit_code(cli=%p, nt_status=%s [%x])\n",
     350                cli, nt_errstr(nt_status), NT_STATUS_V(nt_status));
    346351
    347352        for (i = 0; i < ARRAY_SIZE(auth_errors); i++) {
     
    405410        *need_auth = false;
    406411        nt_status = cli_start_connection(&cli, myname, server, NULL, port,
    407                                          Undefined, flags);
     412                                         SMB_SIGNING_DEFAULT, flags);
    408413        if (!NT_STATUS_IS_OK(nt_status)) {
    409414                fprintf(stderr, "ERROR: Connection failed: %s\n", nt_errstr(nt_status));
     
    436441        }
    437442
    438         nt_status = cli_tcon_andx(cli, share, "?????", password,
    439                                   strlen(password) + 1);
     443        nt_status = cli_tree_connect(cli, share, "?????", password,
     444                                     strlen(password) + 1);
    440445        if (!NT_STATUS_IS_OK(nt_status)) {
    441446                fprintf(stderr, "ERROR: Tree connect failed (%s)\n",
  • vendor/current/source3/client/tree.c

    r414 r988  
    3131struct tree_data {
    3232
    33   guint32 type;    /* Type of tree item, an SMBC_TYPE */
     33  guint32_t type;    /* Type of tree item, an SMBC_TYPE */
    3434  char name[256];  /* May need to change this later   */
    3535
     
    129129}
    130130
    131 struct tree_data *make_tree_data(guint32 type, const char *name)
     131struct tree_data *make_tree_data(guint32_t type, const char *name)
    132132{
    133133  struct tree_data *p = SMB_MALLOC_P(struct tree_data);
Note: See TracChangeset for help on using the changeset viewer.