Convert all uint32/16/8 to _t in source3/client.
[vlendec/samba-autobuild/.git] / source3 / client / clitar.c
1 /*
2    Unix SMB/CIFS implementation.
3    Tar backup command extension
4    Copyright (C) AurĂ©lien Aptel 2013
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
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  */
68
69 #include "includes.h"
70 #include "system/filesys.h"
71 #include "client/client_proto.h"
72 #include "client/clitar_proto.h"
73 #include "libsmb/libsmb.h"
74
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
112 enum tar_operation {
113         TAR_NO_OPERATION,
114         TAR_CREATE,    /* c flag */
115         TAR_EXTRACT,   /* x flag */
116 };
117
118 enum tar_selection {
119         TAR_NO_SELECTION,
120         TAR_INCLUDE,       /* I and F flag, default */
121         TAR_EXCLUDE,       /* X flag */
122 };
123
124 enum {
125         ATTR_UNSET,
126         ATTR_SET,
127 };
128
129 struct tar {
130         TALLOC_CTX *talloc_ctx;
131
132         /* in state that needs/can be processed? */
133         bool to_process;
134
135         /* flags */
136         struct tar_mode {
137                 enum tar_operation operation; /* create, extract */
138                 enum tar_selection selection; /* include, exclude */
139                 int blocksize;    /* size in TAR_BLOCK_UNIT of a tar file block */
140                 bool hidden;      /* backup hidden file? */
141                 bool system;      /* backup system file? */
142                 bool incremental; /* backup _only_ archived file? */
143                 bool reset;       /* unset archive bit? */
144                 bool dry;         /* don't write tar file? */
145                 bool regex;       /* XXX: never actually using regex... */
146                 bool verbose;     /* XXX: ignored */
147         } mode;
148
149         /* nb of bytes received */
150         uint64_t total_size;
151
152         /* path to tar archive name */
153         char *tar_path;
154
155         /* list of path to include or exclude */
156         char **path_list;
157         int path_list_size;
158
159         /* archive handle */
160         struct archive *archive;
161 };
162
163 /**
164  * Global context imported in client.c when needed.
165  *
166  * Default options.
167  */
168 struct tar tar_ctx = {
169         .mode.selection   = TAR_INCLUDE,
170         .mode.blocksize   = TAR_DEFAULT_BLOCK_SIZE,
171         .mode.hidden      = true,
172         .mode.system      = true,
173         .mode.incremental = false,
174         .mode.reset       = false,
175         .mode.dry         = false,
176         .mode.regex       = false,
177         .mode.verbose     = false,
178 };
179
180 /* tar, local function */
181 static int tar_create(struct tar* t);
182 static int tar_create_from_list(struct tar *t);
183 static int tar_extract(struct tar *t);
184 static int tar_read_inclusion_file(struct tar *t, const char* filename);
185 static int tar_send_file(struct tar *t, struct archive_entry *entry);
186 static int tar_set_blocksize(struct tar *t, int size);
187 static int tar_set_newer_than(struct tar *t, const char *filename);
188 static NTSTATUS tar_add_selection_path(struct tar *t, const char *path);
189 static void tar_dump(struct tar *t);
190 static NTSTATUS tar_extract_skip_path(struct tar *t,
191                                       struct archive_entry *entry,
192                                       bool *_skip);
193 static TALLOC_CTX *tar_reset_mem_context(struct tar *t);
194 static void tar_free_mem_context(struct tar *t);
195 static NTSTATUS tar_create_skip_path(struct tar *t,
196                                      const char *fullpath,
197                                      const struct file_info *finfo,
198                                      bool *_skip);
199
200 static NTSTATUS tar_path_in_list(struct tar *t, const char *path,
201                                  bool reverse, bool *_is_in_list);
202
203 static int tar_get_file(struct tar *t,
204                         const char *full_dos_path,
205                         struct file_info *finfo);
206
207 static NTSTATUS get_file_callback(struct cli_state *cli,
208                                   struct file_info *finfo,
209                                   const char *dir);
210
211 /* utilities */
212 static char *fix_unix_path(char *path, bool removeprefix);
213 static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base);
214 static const char* skip_useless_char_in_path(const char *p);
215 static int make_remote_path(const char *full_path);
216 static int max_token (const char *str);
217 static NTSTATUS is_subpath(const char *sub, const char *full,
218                            bool *_subpath_match);
219 static int set_remote_attr(const char *filename, uint16_t new_attr, int mode);
220
221 /**
222  * tar_get_ctx - retrieve global tar context handle
223  */
224 struct tar *tar_get_ctx()
225 {
226         return &tar_ctx;
227 }
228
229 /**
230  * cmd_block - interactive command to change tar blocksize
231  *
232  * Read a size from the client command line and update the current
233  * blocksize.
234  */
235 int cmd_block(void)
236 {
237         /* XXX: from client.c */
238         const extern char *cmd_ptr;
239         char *buf;
240         int err = 0;
241         bool ok;
242         TALLOC_CTX *ctx = talloc_new(NULL);
243         if (ctx == NULL) {
244                 return 1;
245         }
246
247         ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
248         if (!ok) {
249                 DBG(0, ("blocksize <n>\n"));
250                 err = 1;
251                 goto out;
252         }
253
254         ok = tar_set_blocksize(&tar_ctx, atoi(buf));
255         if (ok) {
256                 DBG(0, ("invalid blocksize\n"));
257                 err = 1;
258                 goto out;
259         }
260
261         DBG(2, ("blocksize is now %d\n", tar_ctx.mode.blocksize));
262
263 out:
264         talloc_free(ctx);
265         return err;
266 }
267
268 /**
269  * cmd_tarmode - interactive command to change tar behaviour
270  *
271  * Read one or more modes from the client command line and update the
272  * current tar mode.
273  */
274 int cmd_tarmode(void)
275 {
276         const extern char *cmd_ptr;
277         char *buf;
278         int i;
279         TALLOC_CTX *ctx;
280
281         struct {
282                 const char *cmd;
283                 bool *p;
284                 bool value;
285         } table[] = {
286                 {"full",      &tar_ctx.mode.incremental, false},
287                 {"inc",       &tar_ctx.mode.incremental, true },
288                 {"reset",     &tar_ctx.mode.reset,       true },
289                 {"noreset",   &tar_ctx.mode.reset,       false},
290                 {"system",    &tar_ctx.mode.system,      true },
291                 {"nosystem",  &tar_ctx.mode.system,      false},
292                 {"hidden",    &tar_ctx.mode.hidden,      true },
293                 {"nohidden",  &tar_ctx.mode.hidden,      false},
294                 {"verbose",   &tar_ctx.mode.verbose,     true },
295                 {"noquiet",   &tar_ctx.mode.verbose,     true },
296                 {"quiet",     &tar_ctx.mode.verbose,     false},
297                 {"noverbose", &tar_ctx.mode.verbose,     false},
298         };
299
300         ctx = talloc_new(NULL);
301         if (ctx == NULL) {
302                 return 1;
303         }
304
305         while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
306                 for (i = 0; i < ARRAY_SIZE(table); i++) {
307                         if (strequal(table[i].cmd, buf)) {
308                                 *table[i].p = table[i].value;
309                                 break;
310                         }
311                 }
312
313                 if (i == ARRAY_SIZE(table))
314                         DBG(0, ("tarmode: unrecognised option %s\n", buf));
315         }
316
317         DBG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
318                                 tar_ctx.mode.incremental ? "incremental" : "full",
319                                 tar_ctx.mode.system      ? "system"      : "nosystem",
320                                 tar_ctx.mode.hidden      ? "hidden"      : "nohidden",
321                                 tar_ctx.mode.reset       ? "reset"       : "noreset",
322                                 tar_ctx.mode.verbose     ? "verbose"     : "quiet"));
323
324         talloc_free(ctx);
325         return 0;
326 }
327
328 /**
329  * cmd_tar - interactive command to start a tar backup/restoration
330  *
331  * Check presence of argument, parse them and handle the request.
332  */
333 int cmd_tar(void)
334 {
335         const extern char *cmd_ptr;
336         const char *flag;
337         const char **val;
338         char *buf;
339         int maxtok = max_token(cmd_ptr);
340         int i = 0;
341         int err = 0;
342         bool ok;
343         int rc;
344         TALLOC_CTX *ctx = talloc_new(NULL);
345         if (ctx == NULL) {
346                 return 1;
347         }
348
349         ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
350         if (!ok) {
351                 DBG(0, ("tar <c|x>[IXFbganN] [options] <tar file> [path list]\n"));
352                 err = 1;
353                 goto out;
354         }
355
356         flag = buf;
357         val = talloc_array(ctx, const char *, maxtok);
358         if (val == NULL) {
359                 err = 1;
360                 goto out;
361         }
362
363         while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
364                 val[i++] = buf;
365         }
366
367         rc = tar_parse_args(&tar_ctx, flag, val, i);
368         if (rc != 0) {
369                 DBG(0, ("parse_args failed\n"));
370                 err = 1;
371                 goto out;
372         }
373
374         rc = tar_process(&tar_ctx);
375         if (rc != 0) {
376                 DBG(0, ("tar_process failed\n"));
377                 err = 1;
378                 goto out;
379         }
380
381 out:
382         talloc_free(ctx);
383         return err;
384 }
385
386 /**
387  * cmd_setmode - interactive command to set DOS attributes
388  *
389  * Read a filename and mode from the client command line and update
390  * the file DOS attributes.
391  */
392 int cmd_setmode(void)
393 {
394         const extern char *cmd_ptr;
395         char *buf;
396         char *fname = NULL;
397         uint16_t attr[2] = {0};
398         int mode = ATTR_SET;
399         int err = 0;
400         bool ok;
401         TALLOC_CTX *ctx = talloc_new(NULL);
402         if (ctx == NULL) {
403                 return 1;
404         }
405
406         ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
407         if (!ok) {
408                 DBG(0, ("setmode <filename> <[+|-]rsha>\n"));
409                 err = 1;
410                 goto out;
411         }
412
413         fname = talloc_asprintf(ctx,
414                                 "%s%s",
415                                 client_get_cur_dir(),
416                                 buf);
417         if (fname == NULL) {
418                 err = 1;
419                 goto out;
420         }
421
422         while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
423                 const char *s = buf;
424
425                 while (*s) {
426                         switch (*s++) {
427                         case '+':
428                                 mode = ATTR_SET;
429                                 break;
430                         case '-':
431                                 mode = ATTR_UNSET;
432                                 break;
433                         case 'r':
434                                 attr[mode] |= FILE_ATTRIBUTE_READONLY;
435                                 break;
436                         case 'h':
437                                 attr[mode] |= FILE_ATTRIBUTE_HIDDEN;
438                                 break;
439                         case 's':
440                                 attr[mode] |= FILE_ATTRIBUTE_SYSTEM;
441                                 break;
442                         case 'a':
443                                 attr[mode] |= FILE_ATTRIBUTE_ARCHIVE;
444                                 break;
445                         default:
446                                 DBG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
447                                 err = 1;
448                                 goto out;
449                         }
450                 }
451         }
452
453         if (attr[ATTR_SET] == 0 && attr[ATTR_UNSET] == 0) {
454                 DBG(0, ("setmode <filename> <[+|-]rsha>\n"));
455                 err = 1;
456                 goto out;
457         }
458
459         DBG(2, ("perm set %d %d\n", attr[ATTR_SET], attr[ATTR_UNSET]));
460
461         /* ignore return value: server might not store DOS attributes */
462         set_remote_attr(fname, attr[ATTR_SET], ATTR_SET);
463         set_remote_attr(fname, attr[ATTR_UNSET], ATTR_UNSET);
464 out:
465         talloc_free(ctx);
466         return err;
467 }
468
469 /**
470  * tar_parse_args - parse and set tar command line arguments
471  * @flag: string pointing to tar options
472  * @val: number of tar arguments
473  * @valsize: table of arguments after the flags (number of element in val)
474  *
475  * tar arguments work in a weird way. For each flag f that takes a
476  * value v, the user is supposed to type:
477  *
478  * on the CLI:
479  *   -Tf1f2f3 v1 v2 v3 TARFILE PATHS...
480  *
481  * in the interactive session:
482  *   tar f1f2f3 v1 v2 v3 TARFILE PATHS...
483  *
484  * @flag has only flags (eg. "f1f2f3") and @val has the arguments
485  * (values) following them (eg. ["v1", "v2", "v3", "TARFILE", "PATH1",
486  * "PATH2"]).
487  *
488  * There are only 2 flags that take an arg: b and N. The other flags
489  * just change the semantic of PATH or TARFILE.
490  *
491  * PATH can be a list of included/excluded paths, the path to a file
492  * containing a list of included/excluded paths to use (F flag). If no
493  * PATH is provided, the whole share is used (/).
494  */
495 int tar_parse_args(struct tar* t,
496                    const char *flag,
497                    const char **val,
498                    int valsize)
499 {
500         TALLOC_CTX *ctx;
501         bool do_read_list = false;
502         /* index of next value to use */
503         int ival = 0;
504         int rc;
505
506         if (t == NULL) {
507                 DBG(0, ("Invalid tar context\n"));
508                 return 1;
509         }
510
511         ctx = tar_reset_mem_context(t);
512         if (ctx == NULL) {
513                 return 1;
514         }
515         /*
516          * Reset back some options - could be from interactive version
517          * all other modes are left as they are
518          */
519         t->mode.operation = TAR_NO_OPERATION;
520         t->mode.selection = TAR_NO_SELECTION;
521         t->mode.dry = false;
522         t->to_process = false;
523         t->total_size = 0;
524
525         while (flag[0] != '\0') {
526                 switch(flag[0]) {
527                 /* operation */
528                 case 'c':
529                         if (t->mode.operation != TAR_NO_OPERATION) {
530                                 printf("Tar must be followed by only one of c or x.\n");
531                                 return 1;
532                         }
533                         t->mode.operation = TAR_CREATE;
534                         break;
535                 case 'x':
536                         if (t->mode.operation != TAR_NO_OPERATION) {
537                                 printf("Tar must be followed by only one of c or x.\n");
538                                 return 1;
539                         }
540                         t->mode.operation = TAR_EXTRACT;
541                         break;
542
543                         /* selection  */
544                 case 'I':
545                         if (t->mode.selection != TAR_NO_SELECTION) {
546                                 DBG(0,("Only one of I,X,F must be specified\n"));
547                                 return 1;
548                         }
549                         t->mode.selection = TAR_INCLUDE;
550                         break;
551                 case 'X':
552                         if (t->mode.selection != TAR_NO_SELECTION) {
553                                 DBG(0,("Only one of I,X,F must be specified\n"));
554                                 return 1;
555                         }
556                         t->mode.selection = TAR_EXCLUDE;
557                         break;
558                 case 'F':
559                         if (t->mode.selection != TAR_NO_SELECTION) {
560                                 DBG(0,("Only one of I,X,F must be specified\n"));
561                                 return 1;
562                         }
563                         t->mode.selection = TAR_INCLUDE;
564                         do_read_list = true;
565                         break;
566
567                         /* blocksize */
568                 case 'b':
569                         if (ival >= valsize) {
570                                 DBG(0, ("Option b must be followed by a blocksize\n"));
571                                 return 1;
572                         }
573
574                         if (tar_set_blocksize(t, atoi(val[ival]))) {
575                                 DBG(0, ("Option b must be followed by a valid blocksize\n"));
576                                 return 1;
577                         }
578
579                         ival++;
580                         break;
581
582                         /* incremental mode */
583                 case 'g':
584                         t->mode.incremental = true;
585                         break;
586
587                         /* newer than */
588                 case 'N':
589                         if (ival >= valsize) {
590                                 DBG(0, ("Option N must be followed by valid file name\n"));
591                                 return 1;
592                         }
593
594                         if (tar_set_newer_than(t, val[ival])) {
595                                 DBG(0,("Error setting newer-than time\n"));
596                                 return 1;
597                         }
598
599                         ival++;
600                         break;
601
602                         /* reset mode */
603                 case 'a':
604                         t->mode.reset = true;
605                         break;
606
607                         /* verbose */
608                 case 'q':
609                         t->mode.verbose = true;
610                         break;
611
612                         /* regex match  */
613                 case 'r':
614                         t->mode.regex = true;
615                         break;
616
617                         /* dry run mode */
618                 case 'n':
619                         if (t->mode.operation != TAR_CREATE) {
620                                 DBG(0, ("n is only meaningful when creating a tar-file\n"));
621                                 return 1;
622                         }
623
624                         t->mode.dry = true;
625                         DBG(0, ("dry_run set\n"));
626                         break;
627
628                 default:
629                         DBG(0,("Unknown tar option\n"));
630                         return 1;
631                 }
632
633                 flag++;
634         }
635
636         /* no selection given? default selection is include */
637         if (t->mode.selection == TAR_NO_SELECTION) {
638                 t->mode.selection = TAR_INCLUDE;
639         }
640
641         if (valsize - ival < 1) {
642                 DBG(0, ("No tar file given.\n"));
643                 return 1;
644         }
645
646         /* handle TARFILE */
647         t->tar_path = talloc_strdup(ctx, val[ival]);
648         if (t->tar_path == NULL) {
649                 return 1;
650         }
651         ival++;
652
653         /*
654          * Make sure that dbf points to stderr if we are using stdout for
655          * tar output
656          */
657         if (t->mode.operation == TAR_CREATE && strequal(t->tar_path, "-")) {
658                 setup_logging("smbclient", DEBUG_STDERR);
659         }
660
661         /* handle PATHs... */
662
663         /* flag F -> read file list */
664         if (do_read_list) {
665                 if (valsize - ival != 1) {
666                         DBG(0,("Option F must be followed by exactly one filename.\n"));
667                         return 1;
668                 }
669
670                 rc = tar_read_inclusion_file(t, val[ival]);
671                 if (rc != 0) {
672                         return 1;
673                 }
674                 ival++;
675         /* otherwise store all the PATHs on the command line */
676         } else {
677                 int i;
678                 for (i = ival; i < valsize; i++) {
679                         NTSTATUS status;
680                         status = tar_add_selection_path(t, val[i]);
681                         if (!NT_STATUS_IS_OK(status)) {
682                                 return 1;
683                         }
684                 }
685         }
686
687         t->to_process = true;
688         tar_dump(t);
689         return 0;
690 }
691
692 /**
693  * tar_process - start processing archive
694  *
695  * The talloc context of the fields is freed at the end of the call.
696  */
697 int tar_process(struct tar *t)
698 {
699         int rc = 0;
700
701         if (t == NULL) {
702                 DBG(0, ("Invalid tar context\n"));
703                 return 1;
704         }
705
706         switch(t->mode.operation) {
707         case TAR_EXTRACT:
708                 rc = tar_extract(t);
709                 break;
710         case TAR_CREATE:
711                 rc = tar_create(t);
712                 break;
713         default:
714                 DBG(0, ("Invalid tar state\n"));
715                 rc = 1;
716         }
717
718         t->to_process = false;
719         tar_free_mem_context(t);
720         DBG(5, ("tar_process done, err = %d\n", rc));
721         return rc;
722 }
723
724 /**
725  * tar_create - create archive and fetch files
726  */
727 static int tar_create(struct tar* t)
728 {
729         int r;
730         int err = 0;
731         NTSTATUS status;
732         const char *mask;
733         TALLOC_CTX *ctx = talloc_new(NULL);
734         if (ctx == NULL) {
735                 return 1;
736         }
737
738         t->archive = archive_write_new();
739
740         if (!t->mode.dry) {
741                 const int bsize = t->mode.blocksize * TAR_BLOCK_UNIT;
742                 r = archive_write_set_bytes_per_block(t->archive, bsize);
743                 if (r != ARCHIVE_OK) {
744                         DBG(0, ("Can't use a block size of %d bytes", bsize));
745                         err = 1;
746                         goto out;
747                 }
748
749                 /*
750                  * Use PAX restricted format which is not the most
751                  * conservative choice but has useful extensions and is widely
752                  * supported
753                  */
754                 r = archive_write_set_format_pax_restricted(t->archive);
755                 if (r != ARCHIVE_OK) {
756                         DBG(0, ("Can't use pax restricted format: %s\n",
757                                                 archive_error_string(t->archive)));
758                         err = 1;
759                         goto out;
760                 }
761
762                 if (strequal(t->tar_path, "-")) {
763                         r = archive_write_open_fd(t->archive, STDOUT_FILENO);
764                 } else {
765                         r = archive_write_open_filename(t->archive, t->tar_path);
766                 }
767
768                 if (r != ARCHIVE_OK) {
769                         DBG(0, ("Can't open %s: %s\n", t->tar_path,
770                                                 archive_error_string(t->archive)));
771                         err = 1;
772                         goto out_close;
773                 }
774         }
775
776         /*
777          * In inclusion mode, iterate on the inclusion list
778          */
779         if (t->mode.selection == TAR_INCLUDE && t->path_list_size > 0) {
780                 if (tar_create_from_list(t)) {
781                         err = 1;
782                         goto out_close;
783                 }
784         } else {
785                 mask = talloc_asprintf(ctx, "%s\\*", client_get_cur_dir());
786                 if (mask == NULL) {
787                         err = 1;
788                         goto out_close;
789                 }
790                 DBG(5, ("tar_process do_list with mask: %s\n", mask));
791                 status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
792                 if (!NT_STATUS_IS_OK(status)) {
793                         DBG(0, ("do_list fail %s\n", nt_errstr(status)));
794                         err = 1;
795                         goto out_close;
796                 }
797         }
798
799 out_close:
800         DBG(0, ("Total bytes received: %" PRIu64 "\n", t->total_size));
801
802         if (!t->mode.dry) {
803                 r = archive_write_close(t->archive);
804                 if (r != ARCHIVE_OK) {
805                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
806                         err = 1;
807                         goto out;
808                 }
809         }
810 out:
811         archive_write_free(t->archive);
812         talloc_free(ctx);
813         return err;
814 }
815
816 /**
817  * tar_create_from_list - fetch from path list in include mode
818  */
819 static int tar_create_from_list(struct tar *t)
820 {
821         int err = 0;
822         NTSTATUS status;
823         char *base;
824         const char *path, *mask, *start_dir;
825         int i;
826         TALLOC_CTX *ctx = talloc_new(NULL);
827         if (ctx == NULL) {
828                 return 1;
829         }
830
831         start_dir = talloc_strdup(ctx, client_get_cur_dir());
832         if (start_dir == NULL) {
833                 err = 1;
834                 goto out;
835         }
836
837         for (i = 0; i < t->path_list_size; i++) {
838                 path = t->path_list[i];
839                 base = NULL;
840                 status = path_base_name(ctx, path, &base);
841                 if (!NT_STATUS_IS_OK(status)) {
842                         err = 1;
843                         goto out;
844                 }
845                 mask = talloc_asprintf(ctx, "%s\\%s",
846                                        client_get_cur_dir(), path);
847                 if (mask == NULL) {
848                         err = 1;
849                         goto out;
850                 }
851
852                 DBG(5, ("incl. path='%s', base='%s', mask='%s'\n",
853                                         path, base ? base : "NULL", mask));
854
855                 if (base != NULL) {
856                         base = talloc_asprintf(ctx, "%s%s\\",
857                                                client_get_cur_dir(), base);
858                         if (base == NULL) {
859                                 err = 1;
860                                 goto out;
861                         }
862                         DBG(5, ("cd '%s' before do_list\n", base));
863                         client_set_cur_dir(base);
864                 }
865                 status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
866                 if (base != NULL) {
867                         client_set_cur_dir(start_dir);
868                 }
869                 if (!NT_STATUS_IS_OK(status)) {
870                         DBG(0, ("do_list failed on %s (%s)\n", path, nt_errstr(status)));
871                         err = 1;
872                         goto out;
873                 }
874         }
875
876 out:
877         talloc_free(ctx);
878         return err;
879 }
880
881 /**
882  * get_file_callback - do_list callback
883  *
884  * Callback for client.c do_list(). Called for each file found on the
885  * share matching do_list mask. Recursively call do_list() with itself
886  * as callback when the current file is a directory.
887  */
888 static NTSTATUS get_file_callback(struct cli_state *cli,
889                                   struct file_info *finfo,
890                                   const char *dir)
891 {
892         NTSTATUS status = NT_STATUS_OK;
893         char *remote_name;
894         const char *initial_dir = client_get_cur_dir();
895         bool skip = false;
896         int rc;
897         TALLOC_CTX *ctx = talloc_new(NULL);
898         if (ctx == NULL) {
899                 return NT_STATUS_NO_MEMORY;
900         }
901
902         remote_name = talloc_asprintf(ctx, "%s%s", initial_dir, finfo->name);
903         if (remote_name == NULL) {
904                 status = NT_STATUS_NO_MEMORY;
905                 goto out;
906         }
907
908         if (strequal(finfo->name, "..") || strequal(finfo->name, ".")) {
909                 goto out;
910         }
911
912         status = tar_create_skip_path(&tar_ctx, remote_name, finfo, &skip);
913         if (!NT_STATUS_IS_OK(status)) {
914                 goto out;
915         }
916
917         if (skip) {
918                 DBG(5, ("--- %s\n", remote_name));
919                 status = NT_STATUS_OK;
920                 goto out;
921         }
922
923         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
924                 char *old_dir;
925                 char *new_dir;
926                 char *mask;
927
928                 old_dir = talloc_strdup(ctx, initial_dir);
929                 new_dir = talloc_asprintf(ctx, "%s%s\\",
930                                           initial_dir, finfo->name);
931                 if ((old_dir == NULL) || (new_dir == NULL)) {
932                         status = NT_STATUS_NO_MEMORY;
933                         goto out;
934                 }
935                 mask = talloc_asprintf(ctx, "%s*", new_dir);
936                 if (mask == NULL) {
937                         status = NT_STATUS_NO_MEMORY;
938                         goto out;
939                 }
940
941                 rc = tar_get_file(&tar_ctx, remote_name, finfo);
942                 if (rc != 0) {
943                         status = NT_STATUS_UNSUCCESSFUL;
944                         goto out;
945                 }
946
947                 client_set_cur_dir(new_dir);
948                 do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
949                 client_set_cur_dir(old_dir);
950         } else {
951                 rc = tar_get_file(&tar_ctx, remote_name, finfo);
952                 if (rc != 0) {
953                         status = NT_STATUS_UNSUCCESSFUL;
954                         goto out;
955                 }
956         }
957
958 out:
959         talloc_free(ctx);
960         return status;
961 }
962
963 /**
964  * tar_get_file - fetch a remote file to the local archive
965  * @full_dos_path: path to the file to fetch
966  * @finfo: attributes of the file to fetch
967  */
968 static int tar_get_file(struct tar *t,
969                         const char *full_dos_path,
970                         struct file_info *finfo)
971 {
972         extern struct cli_state *cli;
973         NTSTATUS status;
974         struct archive_entry *entry;
975         char *full_unix_path;
976         char buf[TAR_CLI_READ_SIZE];
977         size_t len;
978         uint64_t off = 0;
979         uint16_t remote_fd = (uint16_t)-1;
980         int err = 0, r;
981         const bool isdir = finfo->mode & FILE_ATTRIBUTE_DIRECTORY;
982         TALLOC_CTX *ctx = talloc_new(NULL);
983         if (ctx == NULL) {
984                 return 1;
985         }
986
987         DBG(5, ("+++ %s\n", full_dos_path));
988
989         t->total_size += finfo->size;
990
991         if (t->mode.dry) {
992                 goto out;
993         }
994
995         if (t->mode.reset) {
996                 /* ignore return value: server might not store DOS attributes */
997                 set_remote_attr(full_dos_path, FILE_ATTRIBUTE_ARCHIVE, ATTR_UNSET);
998         }
999
1000         full_unix_path = talloc_asprintf(ctx, ".%s", full_dos_path);
1001         if (full_unix_path == NULL) {
1002                 err = 1;
1003                 goto out;
1004         }
1005         string_replace(full_unix_path, '\\', '/');
1006         entry = archive_entry_new();
1007         archive_entry_copy_pathname(entry, full_unix_path);
1008         archive_entry_set_filetype(entry, isdir ? AE_IFDIR : AE_IFREG);
1009         archive_entry_set_atime(entry,
1010                         finfo->atime_ts.tv_sec,
1011                         finfo->atime_ts.tv_nsec);
1012         archive_entry_set_mtime(entry,
1013                         finfo->mtime_ts.tv_sec,
1014                         finfo->mtime_ts.tv_nsec);
1015         archive_entry_set_ctime(entry,
1016                         finfo->ctime_ts.tv_sec,
1017                         finfo->ctime_ts.tv_nsec);
1018         archive_entry_set_perm(entry, isdir ? 0755 : 0644);
1019         /*
1020          * check if we can safely cast unsigned file size to libarchive
1021          * signed size. Very unlikely problem (>9 exabyte file)
1022          */
1023         if (finfo->size > INT64_MAX) {
1024                 DBG(0, ("Remote file %s too big\n", full_dos_path));
1025                 goto out_entry;
1026         }
1027
1028         archive_entry_set_size(entry, (int64_t)finfo->size);
1029
1030         r = archive_write_header(t->archive, entry);
1031         if (r != ARCHIVE_OK) {
1032                 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1033                 err = 1;
1034                 goto out_entry;
1035         }
1036
1037         if (isdir) {
1038                 DBG(5, ("get_file skip dir %s\n", full_dos_path));
1039                 goto out_entry;
1040         }
1041
1042         status = cli_open(cli, full_dos_path, O_RDONLY, DENY_NONE, &remote_fd);
1043         if (!NT_STATUS_IS_OK(status)) {
1044                 DBG(0,("%s opening remote file %s\n",
1045                                         nt_errstr(status), full_dos_path));
1046                 goto out_entry;
1047         }
1048
1049         do {
1050                 status = cli_read(cli, remote_fd, buf, off, sizeof(buf), &len);
1051                 if (!NT_STATUS_IS_OK(status)) {
1052                         DBG(0,("Error reading file %s : %s\n",
1053                                                 full_dos_path, nt_errstr(status)));
1054                         err = 1;
1055                         goto out_close;
1056                 }
1057
1058                 off += len;
1059
1060                 r = archive_write_data(t->archive, buf, len);
1061                 if (r < 0) {
1062                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1063                         err = 1;
1064                         goto out_close;
1065                 }
1066
1067         } while (off < finfo->size);
1068
1069 out_close:
1070         cli_close(cli, remote_fd);
1071
1072 out_entry:
1073         archive_entry_free(entry);
1074
1075 out:
1076         talloc_free(ctx);
1077         return err;
1078 }
1079
1080 /**
1081  * tar_extract - open archive and send files.
1082  */
1083 static int tar_extract(struct tar *t)
1084 {
1085         int err = 0;
1086         int r;
1087         struct archive_entry *entry;
1088         const size_t bsize = t->mode.blocksize * TAR_BLOCK_UNIT;
1089         int rc;
1090
1091         t->archive = archive_read_new();
1092         archive_read_support_format_all(t->archive);
1093         archive_read_support_filter_all(t->archive);
1094
1095         if (strequal(t->tar_path, "-")) {
1096                 r = archive_read_open_fd(t->archive, STDIN_FILENO, bsize);
1097         } else {
1098                 r = archive_read_open_filename(t->archive, t->tar_path, bsize);
1099         }
1100
1101         if (r != ARCHIVE_OK) {
1102                 DBG(0, ("Can't open %s : %s\n", t->tar_path,
1103                                         archive_error_string(t->archive)));
1104                 err = 1;
1105                 goto out;
1106         }
1107
1108         for (;;) {
1109                 NTSTATUS status;
1110                 bool skip;
1111                 r = archive_read_next_header(t->archive, &entry);
1112                 if (r == ARCHIVE_EOF) {
1113                         break;
1114                 }
1115                 if (r == ARCHIVE_WARN) {
1116                         DBG(0, ("Warning: %s\n", archive_error_string(t->archive)));
1117                 }
1118                 if (r == ARCHIVE_FATAL) {
1119                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1120                         err = 1;
1121                         goto out;
1122                 }
1123
1124                 status = tar_extract_skip_path(t, entry, &skip);
1125                 if (!NT_STATUS_IS_OK(status)) {
1126                         err = 1;
1127                         goto out;
1128                 }
1129                 if (skip) {
1130                         DBG(5, ("--- %s\n", archive_entry_pathname(entry)));
1131                         continue;
1132                 }
1133
1134                 DBG(5, ("+++ %s\n", archive_entry_pathname(entry)));
1135
1136                 rc = tar_send_file(t, entry);
1137                 if (rc != 0) {
1138                         err = 1;
1139                         goto out;
1140                 }
1141         }
1142
1143 out:
1144         r = archive_read_free(t->archive);
1145         if (r != ARCHIVE_OK) {
1146                 DBG(0, ("Can't close %s : %s\n", t->tar_path,
1147                                         archive_error_string(t->archive)));
1148                 err = 1;
1149         }
1150         return err;
1151 }
1152
1153 /**
1154  * tar_send_file - send @entry to the remote server
1155  * @entry: current archive entry
1156  *
1157  * Handle the creation of the parent directories and transfer the
1158  * entry to a new remote file.
1159  */
1160 static int tar_send_file(struct tar *t, struct archive_entry *entry)
1161 {
1162         extern struct cli_state *cli;
1163         char *dos_path;
1164         char *full_path;
1165         NTSTATUS status;
1166         uint16_t remote_fd = (uint16_t) -1;
1167         int err = 0;
1168         int flags = O_RDWR | O_CREAT | O_TRUNC;
1169         mode_t mode = archive_entry_filetype(entry);
1170         int rc;
1171         TALLOC_CTX *ctx = talloc_new(NULL);
1172         if (ctx == NULL) {
1173                 return 1;
1174         }
1175
1176         dos_path = talloc_strdup(ctx, archive_entry_pathname(entry));
1177         if (dos_path == NULL) {
1178                 err = 1;
1179                 goto out;
1180         }
1181         fix_unix_path(dos_path, true);
1182
1183         full_path = talloc_strdup(ctx, client_get_cur_dir());
1184         if (full_path == NULL) {
1185                 err = 1;
1186                 goto out;
1187         }
1188         full_path = talloc_strdup_append(full_path, dos_path);
1189         if (full_path == NULL) {
1190                 err = 1;
1191                 goto out;
1192         }
1193
1194         if (mode != AE_IFREG && mode != AE_IFDIR) {
1195                 DBG(0, ("Skipping non-dir & non-regular file %s\n", full_path));
1196                 goto out;
1197         }
1198
1199         rc = make_remote_path(full_path);
1200         if (rc != 0) {
1201                 err = 1;
1202                 goto out;
1203         }
1204
1205         if (mode == AE_IFDIR) {
1206                 goto out;
1207         }
1208
1209         status = cli_open(cli, full_path, flags, DENY_NONE, &remote_fd);
1210         if (!NT_STATUS_IS_OK(status)) {
1211                 DBG(0, ("Error opening remote file %s: %s\n",
1212                                         full_path, nt_errstr(status)));
1213                 err = 1;
1214                 goto out;
1215         }
1216
1217         for (;;) {
1218                 const void *buf;
1219                 size_t len;
1220                 off_t off;
1221                 int r;
1222
1223                 r = archive_read_data_block(t->archive, &buf, &len, &off);
1224                 if (r == ARCHIVE_EOF) {
1225                         break;
1226                 }
1227                 if (r == ARCHIVE_WARN) {
1228                         DBG(0, ("Warning: %s\n", archive_error_string(t->archive)));
1229                 }
1230                 if (r == ARCHIVE_FATAL) {
1231                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1232                         err = 1;
1233                         goto close_out;
1234                 }
1235
1236                 status = cli_writeall(cli, remote_fd, 0, buf, off, len, NULL);
1237                 if (!NT_STATUS_IS_OK(status)) {
1238                         DBG(0, ("Error writing remote file %s: %s\n",
1239                                                 full_path, nt_errstr(status)));
1240                         err = 1;
1241                         goto close_out;
1242                 }
1243         }
1244
1245 close_out:
1246         status = cli_close(cli, remote_fd);
1247         if (!NT_STATUS_IS_OK(status)) {
1248                 DBG(0, ("Error losing remote file %s: %s\n",
1249                                         full_path, nt_errstr(status)));
1250                 err = 1;
1251         }
1252
1253 out:
1254         talloc_free(ctx);
1255         return err;
1256 }
1257
1258 /**
1259  * tar_add_selection_path - add a path to the path list
1260  * @path: path to add
1261  */
1262 static NTSTATUS tar_add_selection_path(struct tar *t, const char *path)
1263 {
1264         const char **list;
1265         TALLOC_CTX *ctx = t->talloc_ctx;
1266         if (!t->path_list) {
1267                 t->path_list = str_list_make_empty(ctx);
1268                 if (t->path_list == NULL) {
1269                         return NT_STATUS_NO_MEMORY;
1270                 }
1271                 t->path_list_size = 0;
1272         }
1273
1274         /* cast to silence gcc const-qual warning */
1275         list = str_list_add((void *)t->path_list, path);
1276         if (list == NULL) {
1277                 return NT_STATUS_NO_MEMORY;
1278         }
1279         t->path_list = discard_const_p(char *, list);
1280         t->path_list_size++;
1281         fix_unix_path(t->path_list[t->path_list_size - 1], true);
1282
1283         return NT_STATUS_OK;
1284 }
1285
1286 /**
1287  * tar_set_blocksize - set block size in TAR_BLOCK_UNIT
1288  */
1289 static int tar_set_blocksize(struct tar *t, int size)
1290 {
1291         if (size <= 0 || size > TAR_MAX_BLOCK_SIZE) {
1292                 return 1;
1293         }
1294
1295         t->mode.blocksize = size;
1296
1297         return 0;
1298 }
1299
1300 /**
1301  * tar_set_newer_than - set date threshold of saved files
1302  * @filename: local path to a file
1303  *
1304  * Only files newer than the modification time of @filename will be
1305  * saved.
1306  *
1307  * Note: this function set the global variable newer_than from
1308  * client.c. Thus the time is not a field of the tar structure. See
1309  * cmd_newer() to change its value from an interactive session.
1310  */
1311 static int tar_set_newer_than(struct tar *t, const char *filename)
1312 {
1313         extern time_t newer_than;
1314         SMB_STRUCT_STAT stbuf;
1315         int rc;
1316
1317         rc = sys_stat(filename, &stbuf, false);
1318         if (rc != 0) {
1319                 DBG(0, ("Error setting newer-than time\n"));
1320                 return 1;
1321         }
1322
1323         newer_than = convert_timespec_to_time_t(stbuf.st_ex_mtime);
1324         DBG(1, ("Getting files newer than %s\n", time_to_asc(newer_than)));
1325         return 0;
1326 }
1327
1328 /**
1329  * tar_read_inclusion_file - set path list from file
1330  * @filename: path to the list file
1331  *
1332  * Read and add each line of @filename to the path list.
1333  */
1334 static int tar_read_inclusion_file(struct tar *t, const char* filename)
1335 {
1336         char *line;
1337         int err = 0;
1338         int fd;
1339         TALLOC_CTX *ctx = talloc_new(NULL);
1340         if (ctx == NULL) {
1341                 return 1;
1342         }
1343
1344         fd = open(filename, O_RDONLY);
1345         if (fd < 0) {
1346                 DBG(0, ("Can't open inclusion file '%s': %s\n", filename, strerror(errno)));
1347                 err = 1;
1348                 goto out;
1349         }
1350
1351         for (line = afdgets(fd, ctx, 0);
1352                         line != NULL;
1353                         line = afdgets(fd, ctx, 0)) {
1354                 NTSTATUS status;
1355                 status = tar_add_selection_path(t, line);
1356                 if (!NT_STATUS_IS_OK(status)) {
1357                         err = 1;
1358                         goto out;
1359                 }
1360         }
1361
1362         close(fd);
1363
1364 out:
1365         talloc_free(ctx);
1366         return err;
1367 }
1368
1369 /**
1370  * tar_path_in_list - check whether @path is in the path list
1371  * @path: path to find
1372  * @reverse: when true also try to find path list element in @path
1373  * @_is_in_list: set if @path is in the path list
1374  *
1375  * Look at each path of the path list and set @_is_in_list if @path is a
1376  * subpath of one of them.
1377  *
1378  * If you want /path to be in the path list (path/a/, path/b/) set
1379  * @reverse to true to try to match the other way around.
1380  */
1381 static NTSTATUS tar_path_in_list(struct tar *t, const char *path,
1382                                  bool reverse, bool *_is_in_list)
1383 {
1384         int i;
1385         const char *p;
1386         const char *pattern;
1387
1388         if (path == NULL || path[0] == '\0') {
1389                 *_is_in_list = false;
1390                 return NT_STATUS_OK;
1391         }
1392
1393         p = skip_useless_char_in_path(path);
1394
1395         for (i = 0; i < t->path_list_size; i++) {
1396                 bool is_in_list;
1397                 NTSTATUS status;
1398
1399                 pattern = skip_useless_char_in_path(t->path_list[i]);
1400                 status = is_subpath(p, pattern, &is_in_list);
1401                 if (!NT_STATUS_IS_OK(status)) {
1402                         return status;
1403                 }
1404                 if (reverse && !is_in_list) {
1405                         status = is_subpath(pattern, p, &is_in_list);
1406                         if (!NT_STATUS_IS_OK(status)) {
1407                                 return status;
1408                         }
1409                 }
1410                 if (is_in_list) {
1411                         *_is_in_list = true;
1412                         return NT_STATUS_OK;
1413                 }
1414         }
1415
1416         *_is_in_list = false;
1417         return NT_STATUS_OK;
1418 }
1419
1420 /**
1421  * tar_extract_skip_path - check if @entry should be skipped
1422  * @entry: current tar entry
1423  * @_skip: set true if path should be skipped, otherwise false
1424  *
1425  * Skip predicate for tar extraction (archive to server) only.
1426  */
1427 static NTSTATUS tar_extract_skip_path(struct tar *t,
1428                                       struct archive_entry *entry,
1429                                       bool *_skip)
1430 {
1431         const char *fullpath = archive_entry_pathname(entry);
1432         bool in = true;
1433
1434         if (t->path_list_size <= 0) {
1435                 *_skip = false;
1436                 return NT_STATUS_OK;
1437         }
1438
1439         if (t->mode.regex) {
1440                 in = mask_match_list(fullpath, t->path_list, t->path_list_size, true);
1441         } else {
1442                 NTSTATUS status = tar_path_in_list(t, fullpath, false, &in);
1443                 if (!NT_STATUS_IS_OK(status)) {
1444                         return status;
1445                 }
1446         }
1447
1448         if (t->mode.selection == TAR_EXCLUDE) {
1449                 *_skip = in;
1450         } else {
1451                 *_skip = !in;
1452         }
1453
1454         return NT_STATUS_OK;
1455 }
1456
1457 /**
1458  * tar_create_skip_path - check if @fullpath shoud be skipped
1459  * @fullpath: full remote path of the current file
1460  * @finfo: remote file attributes
1461  * @_skip: returned skip not
1462  *
1463  * Skip predicate for tar creation (server to archive) only.
1464  */
1465 static NTSTATUS tar_create_skip_path(struct tar *t,
1466                                      const char *fullpath,
1467                                      const struct file_info *finfo,
1468                                      bool *_skip)
1469 {
1470         /* syntaxic sugar */
1471         const mode_t mode = finfo->mode;
1472         const bool isdir = mode & FILE_ATTRIBUTE_DIRECTORY;
1473         const bool exclude = t->mode.selection == TAR_EXCLUDE;
1474         bool in = true;
1475
1476         if (!isdir) {
1477
1478                 /* 1. if we dont want X and we have X, skip */
1479                 if (!t->mode.system && (mode & FILE_ATTRIBUTE_SYSTEM)) {
1480                         *_skip = true;
1481                         return NT_STATUS_OK;
1482                 }
1483
1484                 if (!t->mode.hidden && (mode & FILE_ATTRIBUTE_HIDDEN)) {
1485                         *_skip = true;
1486                         return NT_STATUS_OK;
1487                 }
1488
1489                 /* 2. if we only want archive and it's not, skip */
1490
1491                 if (t->mode.incremental && !(mode & FILE_ATTRIBUTE_ARCHIVE)) {
1492                         *_skip = true;
1493                         return NT_STATUS_OK;
1494                 }
1495         }
1496
1497         /* 3. is it in the selection list? */
1498
1499         /*
1500          * tar_create_from_list() use the include list as a starting
1501          * point, no need to check
1502          */
1503         if (!exclude) {
1504                 *_skip = false;
1505                 return NT_STATUS_OK;
1506         }
1507
1508         /* we are now in exclude mode */
1509
1510         /* no matter the selection, no list => include everything */
1511         if (t->path_list_size <= 0) {
1512                 *_skip = false;
1513                 return NT_STATUS_OK;
1514         }
1515
1516         if (t->mode.regex) {
1517                 in = mask_match_list(fullpath, t->path_list, t->path_list_size, true);
1518         } else {
1519                 bool reverse = isdir && !exclude;
1520                 NTSTATUS status = tar_path_in_list(t, fullpath, reverse, &in);
1521                 if (!NT_STATUS_IS_OK(status)) {
1522                         return status;
1523                 }
1524         }
1525         *_skip = in;
1526
1527         return NT_STATUS_OK;
1528 }
1529
1530 /**
1531  * tar_to_process - return true if @t is ready to be processed
1532  *
1533  * @t is ready if it properly parsed command line arguments.
1534  */
1535 bool tar_to_process(struct tar *t)
1536 {
1537         if (t == NULL) {
1538                 DBG(0, ("Invalid tar context\n"));
1539                 return false;
1540         }
1541         return t->to_process;
1542 }
1543
1544 /**
1545  * skip_useless_char_in_path - skip leading slashes/dots
1546  *
1547  * Skip leading slashes, backslashes and dot-slashes.
1548  */
1549 static const char* skip_useless_char_in_path(const char *p)
1550 {
1551         while (p) {
1552                 if (*p == '/' || *p == '\\') {
1553                         p++;
1554                 }
1555                 else if (p[0] == '.' && (p[1] == '/' || p[1] == '\\')) {
1556                         p += 2;
1557                 }
1558                 else
1559                         return p;
1560         }
1561         return p;
1562 }
1563
1564 /**
1565  * is_subpath - check if the path @sub is a subpath of @full.
1566  * @sub: path to test
1567  * @full: container path
1568  * @_subpath_match: set true if @sub is a subpath of @full, otherwise false
1569  *
1570  * String comparaison is case-insensitive.
1571  */
1572 static NTSTATUS is_subpath(const char *sub, const char *full,
1573                            bool *_subpath_match)
1574 {
1575         NTSTATUS status = NT_STATUS_OK;
1576         int len = 0;
1577         char *f, *s;
1578         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1579         if (tmp_ctx == NULL) {
1580                 status = NT_STATUS_NO_MEMORY;
1581                 goto out;
1582         }
1583
1584         f = strlower_talloc(tmp_ctx, full);
1585         if (f == NULL) {
1586                 status = NT_STATUS_NO_MEMORY;
1587                 goto out_ctx_free;
1588         }
1589         string_replace(f, '\\', '/');
1590         s = strlower_talloc(tmp_ctx, sub);
1591         if (f == NULL) {
1592                 status = NT_STATUS_NO_MEMORY;
1593                 goto out_ctx_free;
1594         }
1595         string_replace(s, '\\', '/');
1596
1597         /* find the point where sub and full diverge */
1598         while ((*f != '\0') && (*s != '\0') && (*f == *s)) {
1599                 f++;
1600                 s++;
1601                 len++;
1602         }
1603
1604         if ((*f == '\0') && (*s == '\0')) {
1605                 *_subpath_match = true; /* sub and full match */
1606                 goto out_ctx_free;
1607         }
1608
1609         if ((*f == '\0') && (len > 0) && (*(f - 1) == '/')) {
1610                 /* sub diverges from full at path separator */
1611                 *_subpath_match = true;
1612                 goto out_ctx_free;
1613         }
1614
1615         if ((*s == '\0') && (strcmp(f, "/") == 0)) {
1616                 /* full diverges from sub with trailing slash only */
1617                 *_subpath_match = true;
1618                 goto out_ctx_free;
1619         }
1620
1621         if ((*s == '/') && (*f == '\0')) {
1622                 /* sub diverges from full with extra path component */
1623                 *_subpath_match = true;
1624                 goto out_ctx_free;
1625         }
1626         *_subpath_match = false;
1627
1628 out_ctx_free:
1629         talloc_free(tmp_ctx);
1630 out:
1631         return status;
1632 }
1633
1634 /**
1635  * set_remote_attr - set DOS attributes of a remote file
1636  * @filename: path to the file name
1637  * @new_attr: attribute bit mask to use
1638  * @mode: one of ATTR_SET or ATTR_UNSET
1639  *
1640  * Update the file attributes with the one provided.
1641  */
1642 static int set_remote_attr(const char *filename, uint16_t new_attr, int mode)
1643 {
1644         extern struct cli_state *cli;
1645         uint16_t old_attr;
1646         NTSTATUS status;
1647
1648         status = cli_getatr(cli, filename, &old_attr, NULL, NULL);
1649         if (!NT_STATUS_IS_OK(status)) {
1650                 DBG(0, ("cli_getatr failed: %s\n", nt_errstr(status)));
1651                 return 1;
1652         }
1653
1654         if (mode == ATTR_SET) {
1655                 new_attr |= old_attr;
1656         } else {
1657                 new_attr = old_attr & ~new_attr;
1658         }
1659
1660         status = cli_setatr(cli, filename, new_attr, 0);
1661         if (!NT_STATUS_IS_OK(status)) {
1662                 DBG(1, ("cli_setatr failed: %s\n", nt_errstr(status)));
1663                 return 1;
1664         }
1665
1666         return 0;
1667 }
1668
1669
1670 /**
1671  * make_remote_path - recursively make remote dirs
1672  * @full_path: full hierarchy to create
1673  *
1674  * Create @full_path and each parent directories as needed.
1675  */
1676 static int make_remote_path(const char *full_path)
1677 {
1678         extern struct cli_state *cli;
1679         char *path;
1680         char *subpath;
1681         char *state;
1682         char *last_backslash;
1683         char *p;
1684         int len;
1685         NTSTATUS status;
1686         int err = 0;
1687         TALLOC_CTX *ctx = talloc_new(NULL);
1688         if (ctx == NULL) {
1689                 return 1;
1690         }
1691
1692         subpath = talloc_strdup(ctx, full_path);
1693         if (subpath == NULL) {
1694                 err = 1;
1695                 goto out;
1696         }
1697         path = talloc_strdup(ctx, full_path);
1698         if (path == NULL) {
1699                 err = 1;
1700                 goto out;
1701         }
1702         len = talloc_get_size(path) - 1;
1703
1704         last_backslash = strrchr_m(path, '\\');
1705         if (last_backslash == NULL) {
1706                 goto out;
1707         }
1708
1709         *last_backslash = 0;
1710
1711         subpath[0] = 0;
1712         p = strtok_r(path, "\\", &state);
1713
1714         while (p != NULL) {
1715                 strlcat(subpath, p, len);
1716                 status = cli_chkpath(cli, subpath);
1717                 if (!NT_STATUS_IS_OK(status)) {
1718                         status = cli_mkdir(cli, subpath);
1719                         if (!NT_STATUS_IS_OK(status)) {
1720                                 DBG(0, ("Can't mkdir %s: %s\n", subpath, nt_errstr(status)));
1721                                 err = 1;
1722                                 goto out;
1723                         }
1724                         DBG(3, ("mkdir %s\n", subpath));
1725                 }
1726
1727                 strlcat(subpath, "\\", len);
1728                 p = strtok_r(NULL, "/\\", &state);
1729
1730         }
1731
1732 out:
1733         talloc_free(ctx);
1734         return err;
1735 }
1736
1737 /**
1738  * tar_reset_mem_context - reset talloc context associated with @t
1739  *
1740  * At the start of the program the context is NULL so a new one is
1741  * allocated. On the following runs (interactive session only), simply
1742  * free the children.
1743  */
1744 static TALLOC_CTX *tar_reset_mem_context(struct tar *t)
1745 {
1746         tar_free_mem_context(t);
1747         t->talloc_ctx = talloc_new(NULL);
1748         return t->talloc_ctx;
1749 }
1750
1751 /**
1752  * tar_free_mem_context - free talloc context associated with @t
1753  */
1754 static void tar_free_mem_context(struct tar *t)
1755 {
1756         if (t->talloc_ctx) {
1757                 talloc_free(t->talloc_ctx);
1758                 t->talloc_ctx = NULL;
1759                 t->path_list_size = 0;
1760                 t->path_list = NULL;
1761                 t->tar_path = NULL;
1762         }
1763 }
1764
1765 #define XSET(v)      [v] = #v
1766 #define XTABLE(v, t) DBG(2, ("DUMP:%-20.20s = %s\n", #v, t[v]))
1767 #define XBOOL(v)     DBG(2, ("DUMP:%-20.20s = %d\n", #v, v ? 1 : 0))
1768 #define XSTR(v)      DBG(2, ("DUMP:%-20.20s = %s\n", #v, v ? v : "NULL"))
1769 #define XINT(v)      DBG(2, ("DUMP:%-20.20s = %d\n", #v, v))
1770 #define XUINT64(v)   DBG(2, ("DUMP:%-20.20s = %" PRIu64  "\n", #v, v))
1771
1772 /**
1773  * tar_dump - dump tar structure on stdout
1774  */
1775 static void tar_dump(struct tar *t)
1776 {
1777         int i;
1778         const char* op[] = {
1779                 XSET(TAR_NO_OPERATION),
1780                 XSET(TAR_CREATE),
1781                 XSET(TAR_EXTRACT),
1782         };
1783
1784         const char* sel[] = {
1785                 XSET(TAR_NO_SELECTION),
1786                 XSET(TAR_INCLUDE),
1787                 XSET(TAR_EXCLUDE),
1788         };
1789
1790         XBOOL(t->to_process);
1791         XTABLE(t->mode.operation, op);
1792         XTABLE(t->mode.selection, sel);
1793         XINT(t->mode.blocksize);
1794         XBOOL(t->mode.hidden);
1795         XBOOL(t->mode.system);
1796         XBOOL(t->mode.incremental);
1797         XBOOL(t->mode.reset);
1798         XBOOL(t->mode.dry);
1799         XBOOL(t->mode.verbose);
1800         XUINT64(t->total_size);
1801         XSTR(t->tar_path);
1802         XINT(t->path_list_size);
1803
1804         for (i = 0; t->path_list && t->path_list[i]; i++) {
1805                 DBG(2, ("DUMP: t->path_list[%2d] = %s\n", i, t->path_list[i]));
1806         }
1807
1808         DBG(2, ("DUMP:t->path_list @ %p (%d elem)\n", t->path_list, i));
1809 }
1810 #undef XSET
1811 #undef XTABLE
1812 #undef XBOOL
1813 #undef XSTR
1814 #undef XINT
1815
1816 /**
1817  * max_token - return upper limit for the number of token in @str
1818  *
1819  * The result is not exact, the actual number of token might be less
1820  * than what is returned.
1821  */
1822 static int max_token(const char *str)
1823 {
1824         const char *s;
1825         int nb = 0;
1826
1827         if (str == NULL) {
1828                 return 0;
1829         }
1830
1831         s = str;
1832         while (s[0] != '\0') {
1833                 if (isspace((int)s[0])) {
1834                         nb++;
1835                 }
1836                 s++;
1837         }
1838
1839         nb++;
1840
1841         return nb;
1842 }
1843
1844 /**
1845  * fix_unix_path - convert @path to a DOS path
1846  * @path: path to convert
1847  * @removeprefix: if true, remove leading ./ or /.
1848  */
1849 static char *fix_unix_path(char *path, bool do_remove_prefix)
1850 {
1851         char *from = path, *to = path;
1852
1853         if (path == NULL || path[0] == '\0') {
1854                 return path;
1855         }
1856
1857         /* remove prefix:
1858          * ./path => path
1859          *  /path => path
1860          */
1861         if (do_remove_prefix) {
1862                 /* /path */
1863                 if (path[0] == '/' || path[0] == '\\') {
1864                         from += 1;
1865                 }
1866
1867                 /* ./path */
1868                 if (path[1] != '\0' && path[0] == '.' && (path[1] == '/' || path[1] == '\\')) {
1869                         from += 2;
1870                 }
1871         }
1872
1873         /* replace / with \ */
1874         while (from[0] != '\0') {
1875                 if (from[0] == '/') {
1876                         to[0] = '\\';
1877                 } else {
1878                         to[0] = from[0];
1879                 }
1880
1881                 from++;
1882                 to++;
1883         }
1884         to[0] = '\0';
1885
1886         return path;
1887 }
1888
1889 /**
1890  * path_base_name - return @path basename
1891  *
1892  * If @path doesn't contain any directory separator return NULL.
1893  */
1894 static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base)
1895 {
1896         char *base = NULL;
1897         int last = -1;
1898         int i;
1899
1900         for (i = 0; path[i]; i++) {
1901                 if (path[i] == '\\' || path[i] == '/') {
1902                         last = i;
1903                 }
1904         }
1905
1906         if (last >= 0) {
1907                 base = talloc_strdup(ctx, path);
1908                 if (base == NULL) {
1909                         return NT_STATUS_NO_MEMORY;
1910                 }
1911
1912                 base[last] = 0;
1913         }
1914
1915         *_base = base;
1916         return NT_STATUS_OK;
1917 }
1918
1919 #else
1920
1921 #define NOT_IMPLEMENTED DEBUG(0, ("tar mode not compiled. build with --with-libarchive\n"))
1922
1923 int cmd_block(void)
1924 {
1925         NOT_IMPLEMENTED;
1926         return 1;
1927 }
1928
1929 int cmd_tarmode(void)
1930 {
1931         NOT_IMPLEMENTED;
1932         return 1;
1933 }
1934
1935 int cmd_setmode(void)
1936 {
1937         NOT_IMPLEMENTED;
1938         return 1;
1939 }
1940
1941 int cmd_tar(void)
1942 {
1943         NOT_IMPLEMENTED;
1944         return 1;
1945 }
1946
1947 int tar_process(struct tar* tar)
1948 {
1949         NOT_IMPLEMENTED;
1950         return 1;
1951 }
1952
1953 int tar_parse_args(struct tar *tar, const char *flag, const char **val, int valsize)
1954 {
1955         NOT_IMPLEMENTED;
1956         return 1;
1957 }
1958
1959 bool tar_to_process(struct tar *tar)
1960 {
1961         return false;
1962 }
1963
1964 struct tar *tar_get_ctx()
1965 {
1966         return NULL;
1967 }
1968
1969 #endif