build: Make --with-libarchive the default
[metze/samba/wip.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 struct 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  */
163 struct 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 */
176 static int tar_create(struct tar* t);
177 static int tar_create_from_list(struct tar *t);
178 static int tar_extract(struct tar *t);
179 static int tar_read_inclusion_file(struct tar *t, const char* filename);
180 static int tar_send_file(struct tar *t, struct archive_entry *entry);
181 static int tar_set_blocksize(struct tar *t, int size);
182 static int tar_set_newer_than(struct tar *t, const char *filename);
183 static NTSTATUS tar_add_selection_path(struct tar *t, const char *path);
184 static void tar_dump(struct tar *t);
185 static NTSTATUS tar_extract_skip_path(struct tar *t,
186                                       struct archive_entry *entry,
187                                       bool *_skip);
188 static TALLOC_CTX *tar_reset_mem_context(struct tar *t);
189 static void tar_free_mem_context(struct tar *t);
190 static NTSTATUS tar_create_skip_path(struct tar *t,
191                                      const char *fullpath,
192                                      const struct file_info *finfo,
193                                      bool *_skip);
194
195 static NTSTATUS tar_path_in_list(struct tar *t, const char *path,
196                                  bool reverse, bool *_is_in_list);
197
198 static int tar_get_file(struct tar *t,
199                         const char *full_dos_path,
200                         struct file_info *finfo);
201
202 static NTSTATUS get_file_callback(struct cli_state *cli,
203                                   struct file_info *finfo,
204                                   const char *dir);
205
206 /* utilities */
207 static char *fix_unix_path(char *path, bool removeprefix);
208 static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base);
209 static const char* skip_useless_char_in_path(const char *p);
210 static int make_remote_path(const char *full_path);
211 static int max_token (const char *str);
212 static 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  */
218 struct 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  */
229 int 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
257 out:
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  */
268 int cmd_tarmode(void)
269 {
270         const extern char *cmd_ptr;
271         char *buf;
272         int i;
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;
303                                 break;
304                         }
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  */
327 int 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
375 out:
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  */
407 int 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;
444                         }
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;
451                         }
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;
460                         }
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;
467                         }
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;
474                         }
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  */
609 int 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  */
639 static 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);
676                 } else {
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                 mask = client_clean_name(ctx, mask);
703                 if (mask == NULL) {
704                         err = 1;
705                         goto out_close;
706                 }
707                 DBG(5, ("tar_process do_list with mask: %s\n", mask));
708                 status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
709                 if (!NT_STATUS_IS_OK(status)) {
710                         DBG(0, ("do_list fail %s\n", nt_errstr(status)));
711                         err = 1;
712                         goto out_close;
713                 }
714         }
715
716 out_close:
717         DBG(0, ("Total bytes received: %" PRIu64 "\n", t->total_size));
718
719         if (!t->mode.dry) {
720                 r = archive_write_close(t->archive);
721                 if (r != ARCHIVE_OK) {
722                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
723                         err = 1;
724                         goto out;
725                 }
726         }
727 out:
728 #ifdef HAVE_ARCHIVE_READ_FREE
729         archive_write_free(t->archive);
730 #else
731         archive_write_finish(t->archive);
732 #endif
733         talloc_free(ctx);
734         return err;
735 }
736
737 /**
738  * tar_create_from_list - fetch from path list in include mode
739  */
740 static int tar_create_from_list(struct tar *t)
741 {
742         int err = 0;
743         NTSTATUS status;
744         char *base;
745         const char *path, *mask, *start_dir;
746         int i;
747         TALLOC_CTX *ctx = talloc_new(NULL);
748         if (ctx == NULL) {
749                 return 1;
750         }
751
752         start_dir = talloc_strdup(ctx, client_get_cur_dir());
753         if (start_dir == NULL) {
754                 err = 1;
755                 goto out;
756         }
757
758         for (i = 0; i < t->path_list_size; i++) {
759                 path = t->path_list[i];
760                 base = NULL;
761                 status = path_base_name(ctx, path, &base);
762                 if (!NT_STATUS_IS_OK(status)) {
763                         err = 1;
764                         goto out;
765                 }
766                 mask = talloc_asprintf(ctx, "%s\\%s",
767                                        client_get_cur_dir(), path);
768                 if (mask == NULL) {
769                         err = 1;
770                         goto out;
771                 }
772                 mask = client_clean_name(ctx, mask);
773                 if (mask == NULL) {
774                         err = 1;
775                         goto out;
776                 }
777
778                 DBG(5, ("incl. path='%s', base='%s', mask='%s'\n",
779                                         path, base ? base : "NULL", mask));
780
781                 if (base != NULL) {
782                         base = talloc_asprintf(ctx, "%s%s\\",
783                                                client_get_cur_dir(), base);
784                         if (base == NULL) {
785                                 err = 1;
786                                 goto out;
787                         }
788                         base = client_clean_name(ctx, base);
789                         if (base == NULL) {
790                                 err = 1;
791                                 goto out;
792                         }
793
794                         DBG(5, ("cd '%s' before do_list\n", base));
795                         client_set_cur_dir(base);
796                 }
797                 status = do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
798                 if (base != NULL) {
799                         client_set_cur_dir(start_dir);
800                 }
801                 if (!NT_STATUS_IS_OK(status)) {
802                         DBG(0, ("do_list failed on %s (%s)\n", path, nt_errstr(status)));
803                         err = 1;
804                         goto out;
805                 }
806         }
807
808 out:
809         talloc_free(ctx);
810         return err;
811 }
812
813 /**
814  * get_file_callback - do_list callback
815  *
816  * Callback for client.c do_list(). Called for each file found on the
817  * share matching do_list mask. Recursively call do_list() with itself
818  * as callback when the current file is a directory.
819  */
820 static NTSTATUS get_file_callback(struct cli_state *cli,
821                                   struct file_info *finfo,
822                                   const char *dir)
823 {
824         NTSTATUS status = NT_STATUS_OK;
825         char *remote_name;
826         const char *initial_dir = client_get_cur_dir();
827         bool skip = false;
828         int rc;
829         TALLOC_CTX *ctx = talloc_new(NULL);
830         if (ctx == NULL) {
831                 return NT_STATUS_NO_MEMORY;
832         }
833
834         remote_name = talloc_asprintf(ctx, "%s%s", initial_dir, finfo->name);
835         if (remote_name == NULL) {
836                 status = NT_STATUS_NO_MEMORY;
837                 goto out;
838         }
839         remote_name = client_clean_name(ctx, remote_name);
840         if (remote_name == NULL) {
841                 status = NT_STATUS_NO_MEMORY;
842                 goto out;
843         }
844
845         if (strequal(finfo->name, "..") || strequal(finfo->name, ".")) {
846                 goto out;
847         }
848
849         status = tar_create_skip_path(&tar_ctx, remote_name, finfo, &skip);
850         if (!NT_STATUS_IS_OK(status)) {
851                 goto out;
852         }
853
854         if (skip) {
855                 DBG(5, ("--- %s\n", remote_name));
856                 status = NT_STATUS_OK;
857                 goto out;
858         }
859
860         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
861                 char *old_dir;
862                 char *new_dir;
863                 char *mask;
864
865                 old_dir = talloc_strdup(ctx, initial_dir);
866                 new_dir = talloc_asprintf(ctx, "%s%s\\",
867                                           initial_dir, finfo->name);
868                 if ((old_dir == NULL) || (new_dir == NULL)) {
869                         status = NT_STATUS_NO_MEMORY;
870                         goto out;
871                 }
872                 mask = talloc_asprintf(ctx, "%s*", new_dir);
873                 if (mask == NULL) {
874                         status = NT_STATUS_NO_MEMORY;
875                         goto out;
876                 }
877                 mask = client_clean_name(ctx, mask);
878                 if (mask == NULL) {
879                         status = NT_STATUS_NO_MEMORY;
880                         goto out;
881                 }
882
883                 rc = tar_get_file(&tar_ctx, remote_name, finfo);
884                 if (rc != 0) {
885                         status = NT_STATUS_UNSUCCESSFUL;
886                         goto out;
887                 }
888
889                 client_set_cur_dir(new_dir);
890                 do_list(mask, TAR_DO_LIST_ATTR, get_file_callback, false, true);
891                 client_set_cur_dir(old_dir);
892         } else {
893                 rc = tar_get_file(&tar_ctx, remote_name, finfo);
894                 if (rc != 0) {
895                         status = NT_STATUS_UNSUCCESSFUL;
896                         goto out;
897                 }
898         }
899
900 out:
901         talloc_free(ctx);
902         return status;
903 }
904
905 /**
906  * tar_get_file - fetch a remote file to the local archive
907  * @full_dos_path: path to the file to fetch
908  * @finfo: attributes of the file to fetch
909  */
910 static int tar_get_file(struct tar *t,
911                         const char *full_dos_path,
912                         struct file_info *finfo)
913 {
914         extern struct cli_state *cli;
915         NTSTATUS status;
916         struct archive_entry *entry;
917         char *full_unix_path;
918         char buf[TAR_CLI_READ_SIZE];
919         size_t len;
920         uint64_t off = 0;
921         uint16_t remote_fd = (uint16_t)-1;
922         int err = 0, r;
923         const bool isdir = finfo->mode & FILE_ATTRIBUTE_DIRECTORY;
924         TALLOC_CTX *ctx = talloc_new(NULL);
925         if (ctx == NULL) {
926                 return 1;
927         }
928
929         DBG(5, ("+++ %s\n", full_dos_path));
930
931         t->total_size += finfo->size;
932
933         if (t->mode.dry) {
934                 goto out;
935         }
936
937         if (t->mode.reset) {
938                 /* ignore return value: server might not store DOS attributes */
939                 set_remote_attr(full_dos_path, FILE_ATTRIBUTE_ARCHIVE, ATTR_UNSET);
940         }
941
942         full_unix_path = talloc_asprintf(ctx, ".%s", full_dos_path);
943         if (full_unix_path == NULL) {
944                 err = 1;
945                 goto out;
946         }
947         string_replace(full_unix_path, '\\', '/');
948         entry = archive_entry_new();
949         archive_entry_copy_pathname(entry, full_unix_path);
950         archive_entry_set_filetype(entry, isdir ? AE_IFDIR : AE_IFREG);
951         archive_entry_set_atime(entry,
952                         finfo->atime_ts.tv_sec,
953                         finfo->atime_ts.tv_nsec);
954         archive_entry_set_mtime(entry,
955                         finfo->mtime_ts.tv_sec,
956                         finfo->mtime_ts.tv_nsec);
957         archive_entry_set_ctime(entry,
958                         finfo->ctime_ts.tv_sec,
959                         finfo->ctime_ts.tv_nsec);
960         archive_entry_set_perm(entry, isdir ? 0755 : 0644);
961         /*
962          * check if we can safely cast unsigned file size to libarchive
963          * signed size. Very unlikely problem (>9 exabyte file)
964          */
965         if (finfo->size > INT64_MAX) {
966                 DBG(0, ("Remote file %s too big\n", full_dos_path));
967                 goto out_entry;
968         }
969
970         archive_entry_set_size(entry, (int64_t)finfo->size);
971
972         r = archive_write_header(t->archive, entry);
973         if (r != ARCHIVE_OK) {
974                 DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
975                 err = 1;
976                 goto out_entry;
977         }
978
979         if (isdir) {
980                 DBG(5, ("get_file skip dir %s\n", full_dos_path));
981                 goto out_entry;
982         }
983
984         status = cli_open(cli, full_dos_path, O_RDONLY, DENY_NONE, &remote_fd);
985         if (!NT_STATUS_IS_OK(status)) {
986                 DBG(0,("%s opening remote file %s\n",
987                                         nt_errstr(status), full_dos_path));
988                 goto out_entry;
989         }
990
991         do {
992                 status = cli_read(cli, remote_fd, buf, off, sizeof(buf), &len);
993                 if (!NT_STATUS_IS_OK(status)) {
994                         DBG(0,("Error reading file %s : %s\n",
995                                                 full_dos_path, nt_errstr(status)));
996                         err = 1;
997                         goto out_close;
998                 }
999
1000                 off += len;
1001
1002                 r = archive_write_data(t->archive, buf, len);
1003                 if (r < 0) {
1004                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1005                         err = 1;
1006                         goto out_close;
1007                 }
1008
1009         } while (off < finfo->size);
1010
1011 out_close:
1012         cli_close(cli, remote_fd);
1013
1014 out_entry:
1015         archive_entry_free(entry);
1016
1017 out:
1018         talloc_free(ctx);
1019         return err;
1020 }
1021
1022 /**
1023  * tar_extract - open archive and send files.
1024  */
1025 static int tar_extract(struct tar *t)
1026 {
1027         int err = 0;
1028         int r;
1029         struct archive_entry *entry;
1030         const size_t bsize = t->mode.blocksize * TAR_BLOCK_UNIT;
1031         int rc;
1032
1033         t->archive = archive_read_new();
1034         archive_read_support_format_all(t->archive);
1035 #ifdef HAVE_ARCHIVE_READ_SUPPORT_FILTER_ALL
1036         archive_read_support_filter_all(t->archive);
1037 #endif
1038
1039         if (strequal(t->tar_path, "-")) {
1040                 r = archive_read_open_fd(t->archive, STDIN_FILENO, bsize);
1041         } else {
1042                 r = archive_read_open_filename(t->archive, t->tar_path, bsize);
1043         }
1044
1045         if (r != ARCHIVE_OK) {
1046                 DBG(0, ("Can't open %s : %s\n", t->tar_path,
1047                                         archive_error_string(t->archive)));
1048                 err = 1;
1049                 goto out;
1050         }
1051
1052         for (;;) {
1053                 NTSTATUS status;
1054                 bool skip = false;
1055                 r = archive_read_next_header(t->archive, &entry);
1056                 if (r == ARCHIVE_EOF) {
1057                         break;
1058                 }
1059                 if (r == ARCHIVE_WARN) {
1060                         DBG(0, ("Warning: %s\n", archive_error_string(t->archive)));
1061                 }
1062                 if (r == ARCHIVE_FATAL) {
1063                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1064                         err = 1;
1065                         goto out;
1066                 }
1067
1068                 status = tar_extract_skip_path(t, entry, &skip);
1069                 if (!NT_STATUS_IS_OK(status)) {
1070                         err = 1;
1071                         goto out;
1072                 }
1073                 if (skip) {
1074                         DBG(5, ("--- %s\n", archive_entry_pathname(entry)));
1075                         continue;
1076                 }
1077
1078                 DBG(5, ("+++ %s\n", archive_entry_pathname(entry)));
1079
1080                 rc = tar_send_file(t, entry);
1081                 if (rc != 0) {
1082                         err = 1;
1083                         goto out;
1084                 }
1085         }
1086
1087 out:
1088 #ifdef HAVE_ARCHIVE_READ_FREE
1089         r = archive_read_free(t->archive);
1090 #else
1091         r = archive_read_finish(t->archive);
1092 #endif
1093         if (r != ARCHIVE_OK) {
1094                 DBG(0, ("Can't close %s : %s\n", t->tar_path,
1095                                         archive_error_string(t->archive)));
1096                 err = 1;
1097         }
1098         return err;
1099 }
1100
1101 /**
1102  * tar_send_file - send @entry to the remote server
1103  * @entry: current archive entry
1104  *
1105  * Handle the creation of the parent directories and transfer the
1106  * entry to a new remote file.
1107  */
1108 static int tar_send_file(struct tar *t, struct archive_entry *entry)
1109 {
1110         extern struct cli_state *cli;
1111         char *dos_path;
1112         char *full_path;
1113         NTSTATUS status;
1114         uint16_t remote_fd = (uint16_t) -1;
1115         int err = 0;
1116         int flags = O_RDWR | O_CREAT | O_TRUNC;
1117         mode_t mode = archive_entry_filetype(entry);
1118         int rc;
1119         TALLOC_CTX *ctx = talloc_new(NULL);
1120         if (ctx == NULL) {
1121                 return 1;
1122         }
1123
1124         dos_path = talloc_strdup(ctx, archive_entry_pathname(entry));
1125         if (dos_path == NULL) {
1126                 err = 1;
1127                 goto out;
1128         }
1129         fix_unix_path(dos_path, true);
1130
1131         full_path = talloc_strdup(ctx, client_get_cur_dir());
1132         if (full_path == NULL) {
1133                 err = 1;
1134                 goto out;
1135         }
1136         full_path = talloc_strdup_append(full_path, dos_path);
1137         if (full_path == NULL) {
1138                 err = 1;
1139                 goto out;
1140         }
1141         full_path = client_clean_name(ctx, full_path);
1142         if (full_path == NULL) {
1143                 err = 1;
1144                 goto out;
1145         }
1146
1147         if (mode != AE_IFREG && mode != AE_IFDIR) {
1148                 DBG(0, ("Skipping non-dir & non-regular file %s\n", full_path));
1149                 goto out;
1150         }
1151
1152         rc = make_remote_path(full_path);
1153         if (rc != 0) {
1154                 err = 1;
1155                 goto out;
1156         }
1157
1158         if (mode == AE_IFDIR) {
1159                 goto out;
1160         }
1161
1162         status = cli_open(cli, full_path, flags, DENY_NONE, &remote_fd);
1163         if (!NT_STATUS_IS_OK(status)) {
1164                 DBG(0, ("Error opening remote file %s: %s\n",
1165                                         full_path, nt_errstr(status)));
1166                 err = 1;
1167                 goto out;
1168         }
1169
1170         for (;;) {
1171                 const void *buf;
1172                 size_t len;
1173                 off_t off;
1174                 int r;
1175
1176                 r = archive_read_data_block(t->archive, &buf, &len, &off);
1177                 if (r == ARCHIVE_EOF) {
1178                         break;
1179                 }
1180                 if (r == ARCHIVE_WARN) {
1181                         DBG(0, ("Warning: %s\n", archive_error_string(t->archive)));
1182                 }
1183                 if (r == ARCHIVE_FATAL) {
1184                         DBG(0, ("Fatal: %s\n", archive_error_string(t->archive)));
1185                         err = 1;
1186                         goto close_out;
1187                 }
1188
1189                 status = cli_writeall(cli, remote_fd, 0, buf, off, len, NULL);
1190                 if (!NT_STATUS_IS_OK(status)) {
1191                         DBG(0, ("Error writing remote file %s: %s\n",
1192                                                 full_path, nt_errstr(status)));
1193                         err = 1;
1194                         goto close_out;
1195                 }
1196         }
1197
1198 close_out:
1199         status = cli_close(cli, remote_fd);
1200         if (!NT_STATUS_IS_OK(status)) {
1201                 DBG(0, ("Error losing remote file %s: %s\n",
1202                                         full_path, nt_errstr(status)));
1203                 err = 1;
1204         }
1205
1206 out:
1207         talloc_free(ctx);
1208         return err;
1209 }
1210
1211 /**
1212  * tar_add_selection_path - add a path to the path list
1213  * @path: path to add
1214  */
1215 static NTSTATUS tar_add_selection_path(struct tar *t, const char *path)
1216 {
1217         const char **list;
1218         TALLOC_CTX *ctx = t->talloc_ctx;
1219         if (!t->path_list) {
1220                 t->path_list = str_list_make_empty(ctx);
1221                 if (t->path_list == NULL) {
1222                         return NT_STATUS_NO_MEMORY;
1223                 }
1224                 t->path_list_size = 0;
1225         }
1226
1227         /* cast to silence gcc const-qual warning */
1228         list = str_list_add((void *)t->path_list, path);
1229         if (list == NULL) {
1230                 return NT_STATUS_NO_MEMORY;
1231         }
1232         t->path_list = discard_const_p(char *, list);
1233         t->path_list_size++;
1234         fix_unix_path(t->path_list[t->path_list_size - 1], true);
1235
1236         return NT_STATUS_OK;
1237 }
1238
1239 /**
1240  * tar_set_blocksize - set block size in TAR_BLOCK_UNIT
1241  */
1242 static int tar_set_blocksize(struct tar *t, int size)
1243 {
1244         if (size <= 0 || size > TAR_MAX_BLOCK_SIZE) {
1245                 return 1;
1246         }
1247
1248         t->mode.blocksize = size;
1249
1250         return 0;
1251 }
1252
1253 /**
1254  * tar_set_newer_than - set date threshold of saved files
1255  * @filename: local path to a file
1256  *
1257  * Only files newer than the modification time of @filename will be
1258  * saved.
1259  *
1260  * Note: this function set the global variable newer_than from
1261  * client.c. Thus the time is not a field of the tar structure. See
1262  * cmd_newer() to change its value from an interactive session.
1263  */
1264 static int tar_set_newer_than(struct tar *t, const char *filename)
1265 {
1266         extern time_t newer_than;
1267         SMB_STRUCT_STAT stbuf;
1268         int rc;
1269
1270         rc = sys_stat(filename, &stbuf, false);
1271         if (rc != 0) {
1272                 DBG(0, ("Error setting newer-than time\n"));
1273                 return 1;
1274         }
1275
1276         newer_than = convert_timespec_to_time_t(stbuf.st_ex_mtime);
1277         DBG(1, ("Getting files newer than %s\n", time_to_asc(newer_than)));
1278         return 0;
1279 }
1280
1281 /**
1282  * tar_read_inclusion_file - set path list from file
1283  * @filename: path to the list file
1284  *
1285  * Read and add each line of @filename to the path list.
1286  */
1287 static int tar_read_inclusion_file(struct tar *t, const char* filename)
1288 {
1289         char *line;
1290         int err = 0;
1291         int fd = -1;
1292         TALLOC_CTX *ctx = talloc_new(NULL);
1293         if (ctx == NULL) {
1294                 return 1;
1295         }
1296
1297         fd = open(filename, O_RDONLY);
1298         if (fd < 0) {
1299                 DBG(0, ("Can't open inclusion file '%s': %s\n", filename, strerror(errno)));
1300                 err = 1;
1301                 goto out;
1302         }
1303
1304         for (line = afdgets(fd, ctx, 0);
1305                         line != NULL;
1306                         line = afdgets(fd, ctx, 0)) {
1307                 NTSTATUS status;
1308                 status = tar_add_selection_path(t, line);
1309                 if (!NT_STATUS_IS_OK(status)) {
1310                         err = 1;
1311                         goto out;
1312                 }
1313         }
1314
1315 out:
1316         if (fd != -1) {
1317                 close(fd);
1318         }
1319         talloc_free(ctx);
1320         return err;
1321 }
1322
1323 /**
1324  * tar_path_in_list - check whether @path is in the path list
1325  * @path: path to find
1326  * @reverse: when true also try to find path list element in @path
1327  * @_is_in_list: set if @path is in the path list
1328  *
1329  * Look at each path of the path list and set @_is_in_list if @path is a
1330  * subpath of one of them.
1331  *
1332  * If you want /path to be in the path list (path/a/, path/b/) set
1333  * @reverse to true to try to match the other way around.
1334  */
1335 static NTSTATUS tar_path_in_list(struct tar *t, const char *path,
1336                                  bool reverse, bool *_is_in_list)
1337 {
1338         int i;
1339         const char *p;
1340         const char *pattern;
1341
1342         if (path == NULL || path[0] == '\0') {
1343                 *_is_in_list = false;
1344                 return NT_STATUS_OK;
1345         }
1346
1347         p = skip_useless_char_in_path(path);
1348
1349         for (i = 0; i < t->path_list_size; i++) {
1350                 bool is_in_list;
1351                 NTSTATUS status;
1352
1353                 pattern = skip_useless_char_in_path(t->path_list[i]);
1354                 status = is_subpath(p, pattern, &is_in_list);
1355                 if (!NT_STATUS_IS_OK(status)) {
1356                         return status;
1357                 }
1358                 if (reverse && !is_in_list) {
1359                         status = is_subpath(pattern, p, &is_in_list);
1360                         if (!NT_STATUS_IS_OK(status)) {
1361                                 return status;
1362                         }
1363                 }
1364                 if (is_in_list) {
1365                         *_is_in_list = true;
1366                         return NT_STATUS_OK;
1367                 }
1368         }
1369
1370         *_is_in_list = false;
1371         return NT_STATUS_OK;
1372 }
1373
1374 /**
1375  * tar_extract_skip_path - check if @entry should be skipped
1376  * @entry: current tar entry
1377  * @_skip: set true if path should be skipped, otherwise false
1378  *
1379  * Skip predicate for tar extraction (archive to server) only.
1380  */
1381 static NTSTATUS tar_extract_skip_path(struct tar *t,
1382                                       struct archive_entry *entry,
1383                                       bool *_skip)
1384 {
1385         const char *fullpath = archive_entry_pathname(entry);
1386         bool in = true;
1387
1388         if (t->path_list_size <= 0) {
1389                 *_skip = false;
1390                 return NT_STATUS_OK;
1391         }
1392
1393         if (t->mode.regex) {
1394                 in = mask_match_list(fullpath, t->path_list, t->path_list_size, true);
1395         } else {
1396                 NTSTATUS status = tar_path_in_list(t, fullpath, false, &in);
1397                 if (!NT_STATUS_IS_OK(status)) {
1398                         return status;
1399                 }
1400         }
1401
1402         if (t->mode.selection == TAR_EXCLUDE) {
1403                 *_skip = in;
1404         } else {
1405                 *_skip = !in;
1406         }
1407
1408         return NT_STATUS_OK;
1409 }
1410
1411 /**
1412  * tar_create_skip_path - check if @fullpath shoud be skipped
1413  * @fullpath: full remote path of the current file
1414  * @finfo: remote file attributes
1415  * @_skip: returned skip not
1416  *
1417  * Skip predicate for tar creation (server to archive) only.
1418  */
1419 static NTSTATUS tar_create_skip_path(struct tar *t,
1420                                      const char *fullpath,
1421                                      const struct file_info *finfo,
1422                                      bool *_skip)
1423 {
1424         /* syntaxic sugar */
1425         const mode_t mode = finfo->mode;
1426         const bool isdir = mode & FILE_ATTRIBUTE_DIRECTORY;
1427         const bool exclude = t->mode.selection == TAR_EXCLUDE;
1428         bool in = true;
1429
1430         if (!isdir) {
1431
1432                 /* 1. if we don't want X and we have X, skip */
1433                 if (!t->mode.system && (mode & FILE_ATTRIBUTE_SYSTEM)) {
1434                         *_skip = true;
1435                         return NT_STATUS_OK;
1436                 }
1437
1438                 if (!t->mode.hidden && (mode & FILE_ATTRIBUTE_HIDDEN)) {
1439                         *_skip = true;
1440                         return NT_STATUS_OK;
1441                 }
1442
1443                 /* 2. if we only want archive and it's not, skip */
1444
1445                 if (t->mode.incremental && !(mode & FILE_ATTRIBUTE_ARCHIVE)) {
1446                         *_skip = true;
1447                         return NT_STATUS_OK;
1448                 }
1449         }
1450
1451         /* 3. is it in the selection list? */
1452
1453         /*
1454          * tar_create_from_list() use the include list as a starting
1455          * point, no need to check
1456          */
1457         if (!exclude) {
1458                 *_skip = false;
1459                 return NT_STATUS_OK;
1460         }
1461
1462         /* we are now in exclude mode */
1463
1464         /* no matter the selection, no list => include everything */
1465         if (t->path_list_size <= 0) {
1466                 *_skip = false;
1467                 return NT_STATUS_OK;
1468         }
1469
1470         if (t->mode.regex) {
1471                 in = mask_match_list(fullpath, t->path_list, t->path_list_size, true);
1472         } else {
1473                 bool reverse = isdir && !exclude;
1474                 NTSTATUS status = tar_path_in_list(t, fullpath, reverse, &in);
1475                 if (!NT_STATUS_IS_OK(status)) {
1476                         return status;
1477                 }
1478         }
1479         *_skip = in;
1480
1481         return NT_STATUS_OK;
1482 }
1483
1484 /**
1485  * tar_to_process - return true if @t is ready to be processed
1486  *
1487  * @t is ready if it properly parsed command line arguments.
1488  */
1489 bool tar_to_process(struct tar *t)
1490 {
1491         if (t == NULL) {
1492                 DBG(0, ("Invalid tar context\n"));
1493                 return false;
1494         }
1495         return t->to_process;
1496 }
1497
1498 /**
1499  * skip_useless_char_in_path - skip leading slashes/dots
1500  *
1501  * Skip leading slashes, backslashes and dot-slashes.
1502  */
1503 static const char* skip_useless_char_in_path(const char *p)
1504 {
1505         while (p) {
1506                 if (*p == '/' || *p == '\\') {
1507                         p++;
1508                 }
1509                 else if (p[0] == '.' && (p[1] == '/' || p[1] == '\\')) {
1510                         p += 2;
1511                 }
1512                 else
1513                         return p;
1514         }
1515         return p;
1516 }
1517
1518 /**
1519  * is_subpath - check if the path @sub is a subpath of @full.
1520  * @sub: path to test
1521  * @full: container path
1522  * @_subpath_match: set true if @sub is a subpath of @full, otherwise false
1523  *
1524  * String comparaison is case-insensitive.
1525  */
1526 static NTSTATUS is_subpath(const char *sub, const char *full,
1527                            bool *_subpath_match)
1528 {
1529         NTSTATUS status = NT_STATUS_OK;
1530         int len = 0;
1531         char *f, *s;
1532         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1533         if (tmp_ctx == NULL) {
1534                 status = NT_STATUS_NO_MEMORY;
1535                 goto out;
1536         }
1537
1538         f = strlower_talloc(tmp_ctx, full);
1539         if (f == NULL) {
1540                 status = NT_STATUS_NO_MEMORY;
1541                 goto out_ctx_free;
1542         }
1543         string_replace(f, '\\', '/');
1544         s = strlower_talloc(tmp_ctx, sub);
1545         if (s == NULL) {
1546                 status = NT_STATUS_NO_MEMORY;
1547                 goto out_ctx_free;
1548         }
1549         string_replace(s, '\\', '/');
1550
1551         /* find the point where sub and full diverge */
1552         while ((*f != '\0') && (*s != '\0') && (*f == *s)) {
1553                 f++;
1554                 s++;
1555                 len++;
1556         }
1557
1558         if ((*f == '\0') && (*s == '\0')) {
1559                 *_subpath_match = true; /* sub and full match */
1560                 goto out_ctx_free;
1561         }
1562
1563         if ((*f == '\0') && (len > 0) && (*(f - 1) == '/')) {
1564                 /* sub diverges from full at path separator */
1565                 *_subpath_match = true;
1566                 goto out_ctx_free;
1567         }
1568
1569         if ((*s == '\0') && (strcmp(f, "/") == 0)) {
1570                 /* full diverges from sub with trailing slash only */
1571                 *_subpath_match = true;
1572                 goto out_ctx_free;
1573         }
1574
1575         if ((*s == '/') && (*f == '\0')) {
1576                 /* sub diverges from full with extra path component */
1577                 *_subpath_match = true;
1578                 goto out_ctx_free;
1579         }
1580         *_subpath_match = false;
1581
1582 out_ctx_free:
1583         talloc_free(tmp_ctx);
1584 out:
1585         return status;
1586 }
1587
1588
1589 /**
1590  * make_remote_path - recursively make remote dirs
1591  * @full_path: full hierarchy to create
1592  *
1593  * Create @full_path and each parent directories as needed.
1594  */
1595 static int make_remote_path(const char *full_path)
1596 {
1597         extern struct cli_state *cli;
1598         char *path;
1599         char *subpath;
1600         char *state;
1601         char *last_backslash;
1602         char *p;
1603         int len;
1604         NTSTATUS status;
1605         int err = 0;
1606         TALLOC_CTX *ctx = talloc_new(NULL);
1607         if (ctx == NULL) {
1608                 return 1;
1609         }
1610
1611         subpath = talloc_strdup(ctx, full_path);
1612         if (subpath == NULL) {
1613                 err = 1;
1614                 goto out;
1615         }
1616         path = talloc_strdup(ctx, full_path);
1617         if (path == NULL) {
1618                 err = 1;
1619                 goto out;
1620         }
1621         len = talloc_get_size(path) - 1;
1622
1623         last_backslash = strrchr_m(path, '\\');
1624         if (last_backslash == NULL) {
1625                 goto out;
1626         }
1627
1628         *last_backslash = 0;
1629
1630         subpath[0] = 0;
1631         p = strtok_r(path, "\\", &state);
1632
1633         while (p != NULL) {
1634                 strlcat(subpath, p, len);
1635                 status = cli_chkpath(cli, subpath);
1636                 if (!NT_STATUS_IS_OK(status)) {
1637                         status = cli_mkdir(cli, subpath);
1638                         if (!NT_STATUS_IS_OK(status)) {
1639                                 DBG(0, ("Can't mkdir %s: %s\n", subpath, nt_errstr(status)));
1640                                 err = 1;
1641                                 goto out;
1642                         }
1643                         DBG(3, ("mkdir %s\n", subpath));
1644                 }
1645
1646                 strlcat(subpath, "\\", len);
1647                 p = strtok_r(NULL, "/\\", &state);
1648
1649         }
1650
1651 out:
1652         talloc_free(ctx);
1653         return err;
1654 }
1655
1656 /**
1657  * tar_reset_mem_context - reset talloc context associated with @t
1658  *
1659  * At the start of the program the context is NULL so a new one is
1660  * allocated. On the following runs (interactive session only), simply
1661  * free the children.
1662  */
1663 static TALLOC_CTX *tar_reset_mem_context(struct tar *t)
1664 {
1665         tar_free_mem_context(t);
1666         t->talloc_ctx = talloc_new(NULL);
1667         return t->talloc_ctx;
1668 }
1669
1670 /**
1671  * tar_free_mem_context - free talloc context associated with @t
1672  */
1673 static void tar_free_mem_context(struct tar *t)
1674 {
1675         if (t->talloc_ctx) {
1676                 talloc_free(t->talloc_ctx);
1677                 t->talloc_ctx = NULL;
1678                 t->path_list_size = 0;
1679                 t->path_list = NULL;
1680                 t->tar_path = NULL;
1681         }
1682 }
1683
1684 #define XSET(v)      [v] = #v
1685 #define XTABLE(v, t) DBG(2, ("DUMP:%-20.20s = %s\n", #v, t[v]))
1686 #define XBOOL(v)     DBG(2, ("DUMP:%-20.20s = %d\n", #v, v ? 1 : 0))
1687 #define XSTR(v)      DBG(2, ("DUMP:%-20.20s = %s\n", #v, v ? v : "NULL"))
1688 #define XINT(v)      DBG(2, ("DUMP:%-20.20s = %d\n", #v, v))
1689 #define XUINT64(v)   DBG(2, ("DUMP:%-20.20s = %" PRIu64  "\n", #v, v))
1690
1691 /**
1692  * tar_dump - dump tar structure on stdout
1693  */
1694 static void tar_dump(struct tar *t)
1695 {
1696         int i;
1697         const char* op[] = {
1698                 XSET(TAR_NO_OPERATION),
1699                 XSET(TAR_CREATE),
1700                 XSET(TAR_EXTRACT),
1701         };
1702
1703         const char* sel[] = {
1704                 XSET(TAR_NO_SELECTION),
1705                 XSET(TAR_INCLUDE),
1706                 XSET(TAR_EXCLUDE),
1707         };
1708
1709         XBOOL(t->to_process);
1710         XTABLE(t->mode.operation, op);
1711         XTABLE(t->mode.selection, sel);
1712         XINT(t->mode.blocksize);
1713         XBOOL(t->mode.hidden);
1714         XBOOL(t->mode.system);
1715         XBOOL(t->mode.incremental);
1716         XBOOL(t->mode.reset);
1717         XBOOL(t->mode.dry);
1718         XBOOL(t->mode.verbose);
1719         XUINT64(t->total_size);
1720         XSTR(t->tar_path);
1721         XINT(t->path_list_size);
1722
1723         for (i = 0; t->path_list && t->path_list[i]; i++) {
1724                 DBG(2, ("DUMP: t->path_list[%2d] = %s\n", i, t->path_list[i]));
1725         }
1726
1727         DBG(2, ("DUMP:t->path_list @ %p (%d elem)\n", t->path_list, i));
1728 }
1729 #undef XSET
1730 #undef XTABLE
1731 #undef XBOOL
1732 #undef XSTR
1733 #undef XINT
1734
1735 /**
1736  * max_token - return upper limit for the number of token in @str
1737  *
1738  * The result is not exact, the actual number of token might be less
1739  * than what is returned.
1740  */
1741 static int max_token(const char *str)
1742 {
1743         const char *s;
1744         int nb = 0;
1745
1746         if (str == NULL) {
1747                 return 0;
1748         }
1749
1750         s = str;
1751         while (s[0] != '\0') {
1752                 if (isspace((int)s[0])) {
1753                         nb++;
1754                 }
1755                 s++;
1756         }
1757
1758         nb++;
1759
1760         return nb;
1761 }
1762
1763 /**
1764  * fix_unix_path - convert @path to a DOS path
1765  * @path: path to convert
1766  * @removeprefix: if true, remove leading ./ or /.
1767  */
1768 static char *fix_unix_path(char *path, bool do_remove_prefix)
1769 {
1770         char *from = path, *to = path;
1771
1772         if (path == NULL || path[0] == '\0') {
1773                 return path;
1774         }
1775
1776         /* remove prefix:
1777          * ./path => path
1778          *  /path => path
1779          */
1780         if (do_remove_prefix) {
1781                 /* /path */
1782                 if (path[0] == '/' || path[0] == '\\') {
1783                         from += 1;
1784                 }
1785
1786                 /* ./path */
1787                 if (path[1] != '\0' && path[0] == '.' && (path[1] == '/' || path[1] == '\\')) {
1788                         from += 2;
1789                 }
1790         }
1791
1792         /* replace / with \ */
1793         while (from[0] != '\0') {
1794                 if (from[0] == '/') {
1795                         to[0] = '\\';
1796                 } else {
1797                         to[0] = from[0];
1798                 }
1799
1800                 from++;
1801                 to++;
1802         }
1803         to[0] = '\0';
1804
1805         return path;
1806 }
1807
1808 /**
1809  * path_base_name - return @path basename
1810  *
1811  * If @path doesn't contain any directory separator return NULL.
1812  */
1813 static NTSTATUS path_base_name(TALLOC_CTX *ctx, const char *path, char **_base)
1814 {
1815         char *base = NULL;
1816         int last = -1;
1817         int i;
1818
1819         for (i = 0; path[i]; i++) {
1820                 if (path[i] == '\\' || path[i] == '/') {
1821                         last = i;
1822                 }
1823         }
1824
1825         if (last >= 0) {
1826                 base = talloc_strdup(ctx, path);
1827                 if (base == NULL) {
1828                         return NT_STATUS_NO_MEMORY;
1829                 }
1830
1831                 base[last] = 0;
1832         }
1833
1834         *_base = base;
1835         return NT_STATUS_OK;
1836 }
1837
1838 #else
1839
1840 #define NOT_IMPLEMENTED DEBUG(0, ("tar mode not compiled. build used --without-libarchive\n"))
1841
1842 int cmd_block(void)
1843 {
1844         NOT_IMPLEMENTED;
1845         return 1;
1846 }
1847
1848 int cmd_tarmode(void)
1849 {
1850         NOT_IMPLEMENTED;
1851         return 1;
1852 }
1853
1854 int cmd_tar(void)
1855 {
1856         NOT_IMPLEMENTED;
1857         return 1;
1858 }
1859
1860 int tar_process(struct tar* tar)
1861 {
1862         NOT_IMPLEMENTED;
1863         return 1;
1864 }
1865
1866 int tar_parse_args(struct tar *tar, const char *flag, const char **val, int valsize)
1867 {
1868         NOT_IMPLEMENTED;
1869         return 1;
1870 }
1871
1872 bool tar_to_process(struct tar *tar)
1873 {
1874         return false;
1875 }
1876
1877 struct tar *tar_get_ctx()
1878 {
1879         return NULL;
1880 }
1881
1882 #endif