2 Unix SMB/CIFS implementation.
4 Copyright (C) Ricky Poulten 1995-1998
5 Copyright (C) Richard Sharpe 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /* The following changes developed by Richard Sharpe for Canon Information
21 Systems Research Australia (CISRA)
23 1. Restore can now restore files with long file names
24 2. Save now saves directory information so that we can restore
25 directory creation times
26 3. tar now accepts both UNIX path names and DOS path names. I prefer
27 those lovely /'s to those UGLY \'s :-)
28 4. the files to exclude can be specified as a regular expression by adding
29 an r flag to the other tar flags. Eg:
31 -TcrX file.tar "*.(obj|exe)"
33 will skip all .obj and .exe files
38 #include "system/filesys.h"
40 #include "client/client_proto.h"
42 static int clipfind(char **aret, int ret, char *tok);
44 typedef struct file_info_struct file_info2;
46 struct file_info_struct {
51 /* These times are normally kept in GMT */
52 struct timespec mtime_ts;
53 struct timespec atime_ts;
54 struct timespec ctime_ts;
55 char *name; /* This is dynamically allocated */
56 file_info2 *next, *prev; /* Used in the stack ... */
64 #define SEPARATORS " \t\n\r"
65 extern time_t newer_than;
66 extern struct cli_state *cli;
68 /* These defines are for the do_setrattr routine, to indicate
69 * setting and reseting of file attributes in the function call */
73 static uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
75 #ifndef CLIENT_TIMEOUT
76 #define CLIENT_TIMEOUT (30*1000)
79 static char *tarbuf, *buffer_p;
80 static int tp, ntarf, tbufsiz;
82 /* Incremental mode */
83 static bool tar_inc=False;
84 /* Reset archive bit */
85 static bool tar_reset=False;
86 /* Include / exclude mode (true=include, false=exclude) */
87 static bool tar_excl=True;
88 /* use regular expressions for search on file names */
89 static bool tar_re_search=False;
90 /* Do not dump anything, just calculate sizes */
91 static bool dry_run=False;
92 /* Dump files with System attribute */
93 static bool tar_system=True;
94 /* Dump files with Hidden attribute */
95 static bool tar_hidden=True;
96 /* Be noisy - make a catalogue */
97 static bool tar_noisy=True;
98 static bool tar_real_noisy=False; /* Don't want to be really noisy by default */
101 static char **cliplist=NULL;
103 static bool must_free_cliplist = False;
104 extern const char *cmd_ptr;
106 extern bool lowercase;
108 extern bool readbraw_supported;
110 extern int get_total_time_ms;
111 extern int get_total_size;
113 static int blocksize=20;
114 static int tarhandle;
116 static void writetarheader(int f, const char *aname, uint64_t size, time_t mtime,
117 const char *amode, unsigned char ftype);
118 static NTSTATUS do_atar(const char *rname_in, char *lname,
119 struct file_info *finfo1);
120 static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo,
122 static void oct_it(uint64_t value, int ndgs, char *p);
123 static void fixtarname(char *tptr, const char *fp, size_t l);
124 static int dotarbuf(int f, char *b, int n);
125 static void dozerobuf(int f, int n);
126 static void dotareof(int f);
127 static void initarbuf(void);
129 /* restore functions */
130 static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefix);
131 static long unoct(char *p, int ndgs);
132 static void do_tarput(void);
133 static void unfixtarname(char *tptr, char *fp, int l, bool first);
136 * tar specific utitlities
139 /*******************************************************************
140 Create a string of size size+1 (for the null)
141 *******************************************************************/
143 static char *string_create_s(int size)
147 tmp = (char *)SMB_MALLOC(size+1);
150 DEBUG(0, ("Out of memory in string_create_s\n"));
156 /****************************************************************************
157 Write a tar header to buffer
158 ****************************************************************************/
160 static void writetarheader(int f, const char *aname, uint64_t size, time_t mtime,
161 const char *amode, unsigned char ftype)
167 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname));
169 memset(hb.dummy, 0, sizeof(hb.dummy));
172 /* We will be prepending a '.' in fixtarheader so use +2 to
173 * take care of the . and terminating zero. JRA.
176 /* write a GNU tar style long header */
178 b = (char *)SMB_MALLOC(l+TBLOCK+100);
180 DEBUG(0,("out of memory\n"));
183 writetarheader(f, "/./@LongLink", l+2, 0, " 0 \0", 'L');
184 memset(b, 0, l+TBLOCK+100);
185 fixtarname(b, aname, l+2);
187 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b)));
188 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
192 fixtarname(hb.dbuf.name, aname, (l+2 >= NAMSIZ) ? NAMSIZ : l + 2);
195 strlower_m(hb.dbuf.name);
197 /* write out a "standard" tar format header */
199 hb.dbuf.name[NAMSIZ-1]='\0';
200 safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1);
201 oct_it((uint64_t)0, 8, hb.dbuf.uid);
202 oct_it((uint64_t)0, 8, hb.dbuf.gid);
203 oct_it((uint64_t) size, 13, hb.dbuf.size);
204 if (size > (uint64_t)077777777777LL) {
205 /* This is a non-POSIX compatible extention to store files
208 memset(hb.dbuf.size, 0, 4);
210 for (i = 8, jp=(char*)&size; i; i--)
211 hb.dbuf.size[i+3] = *(jp++);
213 oct_it((uint64_t) mtime, 13, hb.dbuf.mtime);
214 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
215 memset(hb.dbuf.linkname, 0, NAMSIZ);
216 hb.dbuf.linkflag=ftype;
218 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;)
221 oct_it((uint64_t) chk, 8, hb.dbuf.chksum);
222 hb.dbuf.chksum[6] = '\0';
224 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
227 /****************************************************************************
228 Read a tar header into a hblock structure, and validate
229 ***************************************************************************/
231 static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefix)
238 * read in a "standard" tar format header - we're not that interested
239 * in that many fields, though
242 /* check the checksum */
243 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;)
249 /* compensate for blanks in chksum header */
250 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
253 chk += ' ' * sizeof(hb->dbuf.chksum);
255 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
257 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
258 chk, fchk, hb->dbuf.chksum));
261 DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk));
262 dump_data(5, (uint8 *)hb - TBLOCK, TBLOCK *3);
266 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
267 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
271 safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3);
273 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
274 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
275 strlen(hb->dbuf.name) + 1, True);
277 /* can't handle some links at present */
278 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
279 if (hb->dbuf.linkflag == 0) {
280 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
283 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
284 /* Do nothing here at the moment. do_tarput will handle this
285 as long as the longlink gets back to it, as it has to advance
286 the buffer pointer, etc */
288 DEBUG(0, ("this tar file appears to contain some kind \
289 of link other than a GNUtar Longlink - ignoring\n"));
295 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) ||
296 (*(finfo->name+strlen(finfo->name)-1) == '\\')) {
299 finfo->mode=0; /* we don't care about mode at the moment, we'll
300 * just make it a regular file */
304 * Bug fix by richard@sj.co.uk
306 * REC: restore times correctly (as does tar)
307 * We only get the modification time of the file; set the creation time
308 * from the mod. time, and the access time to current time
310 finfo->mtime_ts = finfo->ctime_ts =
311 convert_time_t_to_timespec((time_t)strtol(hb->dbuf.mtime, NULL, 8));
312 finfo->atime_ts = convert_time_t_to_timespec(time(NULL));
313 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
318 /****************************************************************************
319 Write out the tar buffer to tape or wherever
320 ****************************************************************************/
322 static int dotarbuf(int f, char *b, int n)
329 /* This routine and the next one should be the only ones that do write()s */
330 if (tp + n >= tbufsiz) {
334 memcpy(tarbuf + tp, b, diff);
335 fail=fail && (1+sys_write(f, tarbuf, tbufsiz));
340 while (n >= tbufsiz) {
341 fail=fail && (1 + sys_write(f, b, tbufsiz));
348 memcpy(tarbuf+tp, b, n);
352 return(fail ? writ : 0);
355 /****************************************************************************
356 Write zeros to buffer / tape
357 ****************************************************************************/
359 static void dozerobuf(int f, int n)
361 /* short routine just to write out n zeros to buffer -
362 * used to round files to nearest block
363 * and to do tar EOFs */
368 if (n+tp >= tbufsiz) {
369 memset(tarbuf+tp, 0, tbufsiz-tp);
370 if (sys_write(f, tarbuf, tbufsiz) != tbufsiz) {
371 DEBUG(0, ("dozerobuf: sys_write fail\n"));
374 memset(tarbuf, 0, (tp+=n-tbufsiz));
376 memset(tarbuf+tp, 0, n);
381 /****************************************************************************
383 ****************************************************************************/
385 static void initarbuf(void)
387 /* initialize tar buffer */
388 tbufsiz=blocksize*TBLOCK;
389 tarbuf=(char *)SMB_MALLOC(tbufsiz); /* FIXME: We might not get the buffer */
391 /* reset tar buffer pointer and tar file counter and total dumped */
392 tp=0; ntarf=0; ttarf=0;
395 /****************************************************************************
396 Write two zero blocks at end of file
397 ****************************************************************************/
399 static void dotareof(int f)
401 SMB_STRUCT_STAT stbuf;
402 /* Two zero blocks at end of file, write out full buffer */
407 (void) dozerobuf(f, TBLOCK);
408 (void) dozerobuf(f, TBLOCK);
410 if (sys_fstat(f, &stbuf, false) == -1) {
411 DEBUG(0, ("Couldn't stat file handle\n"));
415 /* Could be a pipe, in which case S_ISREG should fail,
416 * and we should write out at full size */
418 size_t towrite = S_ISREG(stbuf.st_ex_mode) ? tp : tbufsiz;
419 if (sys_write(f, tarbuf, towrite) != towrite) {
420 DEBUG(0,("dotareof: sys_write fail\n"));
425 /****************************************************************************
426 (Un)mangle DOS pathname, make nonabsolute
427 ****************************************************************************/
429 static void fixtarname(char *tptr, const char *fp, size_t l)
431 /* add a '.' to start of file name, convert from ugly dos \'s in path
432 * to lovely unix /'s :-} */
436 StrnCpy(tptr, fp, l-1);
437 string_replace(tptr, '\\', '/');
440 /****************************************************************************
441 Convert from decimal to octal string
442 ****************************************************************************/
444 static void oct_it (uint64_t value, int ndgs, char *p)
446 /* Converts long to octal string, pads with leading zeros */
448 /* skip final null, but do final space */
452 /* Loop does at least one digit */
454 p[--ndgs] = '0' + (char) (value & 7);
456 } while (ndgs > 0 && value != 0);
458 /* Do leading zeros */
463 /****************************************************************************
464 Convert from octal string to long
465 ***************************************************************************/
467 static long unoct(char *p, int ndgs)
470 /* Converts octal string to long, ignoring any non-digit */
473 if (isdigit((int)*p))
474 value = (value << 3) | (long) (*p - '0');
482 /****************************************************************************
483 Compare two strings in a slash insensitive way, allowing s1 to match s2
484 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
485 a file in any subdirectory of s1, declare a match.
486 ***************************************************************************/
488 static int strslashcmp(char *s1, char *s2)
492 while(*s1 && *s2 && (*s1 == *s2 || tolower_ascii(*s1) == tolower_ascii(*s2) ||
493 (*s1 == '\\' && *s2=='/') || (*s1 == '/' && *s2=='\\'))) {
497 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
500 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\'))
503 /* ignore trailing slash on s1 */
504 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1))
507 /* check for s1 is an "initial" string of s2 */
508 if ((*s2 == '/' || *s2 == '\\') && !*s1)
514 /****************************************************************************
515 Ensure a remote path exists (make if necessary)
516 ***************************************************************************/
518 static bool ensurepath(const char *fname)
520 /* *must* be called with buffer ready malloc'ed */
521 /* ensures path exists */
523 char *partpath, *ffname;
528 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
530 partpath = string_create_s(strlen(fname));
531 ffname = string_create_s(strlen(fname));
533 if ((partpath == NULL) || (ffname == NULL)){
534 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
542 /* fname copied to ffname so can strtok_r */
544 safe_strcpy(ffname, fname, strlen(fname));
546 /* do a `basename' on ffname, so don't try and make file name directory */
547 if ((basehack=strrchr_m(ffname, '\\')) == NULL) {
555 p=strtok_r(ffname, "\\", &saveptr);
558 safe_strcat(partpath, p, strlen(fname) + 1);
560 if (!NT_STATUS_IS_OK(cli_chkpath(cli, partpath))) {
561 if (!NT_STATUS_IS_OK(cli_mkdir(cli, partpath))) {
564 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli)));
567 DEBUG(3, ("mkdirhiering %s\n", partpath));
571 safe_strcat(partpath, "\\", strlen(fname) + 1);
572 p = strtok_r(NULL, "/\\", &saveptr);
580 static int padit(char *buf, uint64_t bufsize, uint64_t padsize)
585 DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize));
586 memset(buf, 0, (size_t)bufsize);
587 while( !berr && padsize > 0 ) {
588 bytestowrite= (int)MIN(bufsize, padsize);
589 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
590 padsize -= bytestowrite;
596 static void do_setrattr(char *name, uint16 attr, int set)
600 if (!NT_STATUS_IS_OK(cli_getatr(cli, name, &oldattr, NULL, NULL))) {
604 if (set == ATTRSET) {
607 attr = oldattr & ~attr;
610 if (!NT_STATUS_IS_OK(cli_setatr(cli, name, attr, 0))) {
611 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli)));
615 /****************************************************************************
616 append one remote file to the tar file
617 ***************************************************************************/
619 static NTSTATUS do_atar(const char *rname_in, char *lname,
620 struct file_info *finfo1)
622 uint16_t fnum = (uint16_t)-1;
626 bool shallitime=True;
628 int read_size = 65520;
631 TALLOC_CTX *ctx = talloc_stackframe();
632 NTSTATUS status = NT_STATUS_OK;
633 struct timespec tp_start;
635 clock_gettime_mono(&tp_start);
637 data = SMB_MALLOC_ARRAY(char, read_size);
639 DEBUG(0,("do_atar: out of memory.\n"));
640 status = NT_STATUS_NO_MEMORY;
644 ftype = '0'; /* An ordinary file ... */
648 finfo.size = finfo1 -> size;
649 finfo.mode = finfo1 -> mode;
650 finfo.uid = finfo1 -> uid;
651 finfo.gid = finfo1 -> gid;
652 finfo.mtime_ts = finfo1 -> mtime_ts;
653 finfo.atime_ts = finfo1 -> atime_ts;
654 finfo.ctime_ts = finfo1 -> ctime_ts;
657 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1->name,
658 (double)finfo.size));
660 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
665 rname = clean_name(ctx, rname_in);
667 status = NT_STATUS_NO_MEMORY;
671 status = cli_open(cli, rname, O_RDONLY, DENY_NONE, &fnum);
672 if (!NT_STATUS_IS_OK(status)) {
673 DEBUG(0,("%s opening remote file %s (%s)\n",
674 cli_errstr(cli),rname, client_get_cur_dir()));
678 finfo.name = string_create_s(strlen(rname));
679 if (finfo.name == NULL) {
680 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
681 status = NT_STATUS_NO_MEMORY;
685 safe_strcpy(finfo.name,rname, strlen(rname));
687 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
689 if (tar_inc && !(finfo.mode & aARCH)) {
690 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
692 } else if (!tar_system && (finfo.mode & aSYSTEM)) {
693 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
695 } else if (!tar_hidden && (finfo.mode & aHIDDEN)) {
696 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
699 bool wrote_tar_header = False;
701 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
702 finfo.name, (double)finfo.size, lname));
706 DEBUG(3,("nread=%.0f\n",(double)nread));
708 datalen = cli_read(cli, fnum, data, nread, read_size);
711 DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli)));
712 status = cli_nt_error(cli);
718 /* Only if the first read succeeds, write out the tar header. */
719 if (!wrote_tar_header) {
720 /* write a tar header, don't bother with mode - just set to 100644 */
721 writetarheader(tarhandle, rname, finfo.size,
722 finfo.mtime_ts.tv_sec, "100644 \0", ftype);
723 wrote_tar_header = True;
726 /* if file size has increased since we made file size query, truncate
727 read so tar header for this file will be correct.
730 if (nread > finfo.size) {
731 datalen -= nread - finfo.size;
732 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
733 finfo.name, (double)finfo.size));
736 /* add received bits of file to buffer - dotarbuf will
737 * write out in 512 byte intervals */
739 if (dotarbuf(tarhandle,data,datalen) != datalen) {
740 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
741 status = map_nt_error_from_unix(errno);
745 if ( (datalen == 0) && (finfo.size != 0) ) {
746 status = NT_STATUS_UNSUCCESSFUL;
747 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
752 } while ( nread < finfo.size );
754 if (wrote_tar_header) {
755 /* pad tar file with zero's if we couldn't get entire file */
756 if (nread < finfo.size) {
757 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
758 (double)finfo.size, (int)nread));
759 if (padit(data, (uint64_t)sizeof(data), finfo.size - nread)) {
760 status = map_nt_error_from_unix(errno);
761 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
765 /* round tar file to nearest block */
766 if (finfo.size % TBLOCK)
767 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
769 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
772 DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo.name));
774 status = NT_STATUS_UNSUCCESSFUL;
778 cli_close(cli, fnum);
782 struct timespec tp_end;
785 /* if shallitime is true then we didn't skip */
786 if (tar_reset && !dry_run)
787 (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
789 clock_gettime_mono(&tp_end);
790 this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000000;
791 get_total_time_ms += this_time;
792 get_total_size += finfo.size;
795 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
796 (double)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
800 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
801 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
802 finfo.size / MAX(0.001, (1.024*this_time)),
803 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
808 if (fnum != (uint16_t)-1) {
809 cli_close(cli, fnum);
817 /****************************************************************************
818 Append single file to tar file (or not)
819 ***************************************************************************/
821 static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo,
824 TALLOC_CTX *ctx = talloc_stackframe();
825 NTSTATUS status = NT_STATUS_OK;
827 if (strequal(finfo->name,"..") || strequal(finfo->name,"."))
830 /* Is it on the exclude list ? */
831 if (!tar_excl && clipn) {
834 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir())));
836 exclaim = talloc_asprintf(ctx,
838 client_get_cur_dir(),
841 return NT_STATUS_NO_MEMORY;
844 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
846 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
847 (tar_re_search && mask_match_list(exclaim, cliplist, clipn, True))) {
848 DEBUG(3,("Skipping file %s\n", exclaim));
849 TALLOC_FREE(exclaim);
852 TALLOC_FREE(exclaim);
855 if (finfo->mode & aDIR) {
856 char *saved_curdir = NULL;
858 char *mtar_mask = NULL;
860 saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
862 return NT_STATUS_NO_MEMORY;
865 DEBUG(5, ("strlen(cur_dir)=%d, \
866 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
867 (int)strlen(saved_curdir),
868 (int)strlen(finfo->name), finfo->name, saved_curdir));
870 new_cd = talloc_asprintf(ctx,
872 client_get_cur_dir(),
875 return NT_STATUS_NO_MEMORY;
877 client_set_cur_dir(new_cd);
879 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir()));
881 /* write a tar directory, don't bother with mode - just
883 writetarheader(tarhandle, client_get_cur_dir(), 0,
884 finfo->mtime_ts.tv_sec, "040755 \0", '5');
886 DEBUG(0,(" directory %s\n",
887 client_get_cur_dir()));
889 ntarf++; /* Make sure we have a file on there */
890 mtar_mask = talloc_asprintf(ctx,
892 client_get_cur_dir());
894 return NT_STATUS_NO_MEMORY;
896 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask));
897 status = do_list(mtar_mask, attribute, do_tar, False, True);
898 client_set_cur_dir(saved_curdir);
899 TALLOC_FREE(saved_curdir);
901 TALLOC_FREE(mtar_mask);
903 char *rname = talloc_asprintf(ctx,
905 client_get_cur_dir(),
908 return NT_STATUS_NO_MEMORY;
910 status = do_atar(rname,finfo->name,finfo);
916 /****************************************************************************
917 Convert from UNIX to DOS file names
918 ***************************************************************************/
920 static void unfixtarname(char *tptr, char *fp, int l, bool first)
922 /* remove '.' from start of file name, convert from unix /'s to
923 * dos \'s in path. Kill any absolute path names. But only if first!
926 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
933 if (*fp == '\\' || *fp == '/') {
939 safe_strcpy(tptr, fp, l);
940 string_replace(tptr, '/', '\\');
943 /****************************************************************************
944 Move to the next block in the buffer, which may mean read in another set of
945 blocks. FIXME, we should allow more than one block to be skipped.
946 ****************************************************************************/
948 static int next_block(char *ltarbuf, char **bufferp, int bufsiz)
950 int bufread, total = 0;
952 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp));
956 if (*bufferp >= (ltarbuf + bufsiz)) {
958 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
961 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
962 * Fixes bug where read can return short if coming from
966 bufread = read(tarhandle, ltarbuf, bufsiz);
969 while (total < bufsiz) {
970 if (bufread < 0) { /* An error, return false */
971 return (total > 0 ? -2 : bufread);
979 bufread = read(tarhandle, <arbuf[total], bufsiz - total);
983 DEBUG(5, ("Total bytes read ... %i\n", total));
991 /* Skip a file, even if it includes a long file name? */
992 static int skip_file(int skipsize)
994 int dsize = skipsize;
996 DEBUG(5, ("Skiping file. Size = %i\n", skipsize));
998 /* FIXME, we should skip more than one block at a time */
1001 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1002 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1011 /*************************************************************
1012 Get a file from the tar file and store it.
1013 When this is called, tarbuf already contains the first
1014 file block. This is a bit broken & needs fixing.
1015 **************************************************************/
1017 static int get_file(file_info2 finfo)
1019 uint16_t fnum = (uint16_t) -1;
1020 int pos = 0, dsize = 0, bpos = 0;
1024 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo.name, (double)finfo.size));
1026 if (!ensurepath(finfo.name)) {
1027 DEBUG(0, ("abandoning restore\n"));
1031 status = cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 DEBUG(0, ("abandoning restore\n"));
1037 /* read the blocks from the tar file and write to the remote file */
1039 rsize = finfo.size; /* This is how much to write */
1043 /* We can only write up to the end of the buffer */
1044 dsize = MIN(tbufsiz - (buffer_p - tarbuf) - bpos, 65520); /* Calculate the size to write */
1045 dsize = MIN(dsize, rsize); /* Should be only what is left */
1046 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize, bpos));
1048 if (cli_write(cli, fnum, 0, buffer_p + bpos, pos, dsize) != dsize) {
1049 DEBUG(0, ("Error writing remote file\n"));
1056 /* Now figure out how much to move in the buffer */
1058 /* FIXME, we should skip more than one block at a time */
1060 /* First, skip any initial part of the part written that is left over */
1061 /* from the end of the first TBLOCK */
1063 if ((bpos) && ((bpos + dsize) >= TBLOCK)) {
1064 dsize -= (TBLOCK - bpos); /* Get rid of the end of the first block */
1067 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { /* and skip the block */
1068 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1074 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1075 * If the file being extracted is an exact multiple of
1076 * TBLOCK bytes then we don't want to extract the next
1077 * block from the tarfile here, as it will be done in
1078 * the caller of get_file().
1081 while (((rsize != 0) && (dsize >= TBLOCK)) ||
1082 ((rsize == 0) && (dsize > TBLOCK))) {
1084 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
1085 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1094 /* Now close the file ... */
1096 if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
1097 DEBUG(0, ("Error %s closing remote file\n",
1102 /* Now we update the creation date ... */
1103 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
1105 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime_ts.tv_sec))) {
1106 if (tar_real_noisy) {
1107 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1108 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1113 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo.name, (double)finfo.size));
1117 /* Create a directory. We just ensure that the path exists and return as there
1118 is no file associated with a directory
1120 static int get_dir(file_info2 finfo)
1122 DEBUG(0, ("restore directory %s\n", finfo.name));
1124 if (!ensurepath(finfo.name)) {
1125 DEBUG(0, ("Problems creating directory\n"));
1132 /* Get a file with a long file name ... first file has file name, next file
1133 has the data. We only want the long file name, as the loop in do_tarput
1134 will deal with the rest.
1136 static char *get_longfilename(file_info2 finfo)
1138 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1140 int namesize = finfo.size + strlen(client_get_cur_dir()) + 2;
1141 char *longname = (char *)SMB_MALLOC(namesize);
1142 int offset = 0, left = finfo.size;
1145 DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
1146 DEBUG(5, ("Len = %.0f\n", (double)finfo.size));
1148 if (longname == NULL) {
1149 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize));
1153 /* First, add cur_dir to the long file name */
1155 if (strlen(client_get_cur_dir()) > 0) {
1156 strncpy(longname, client_get_cur_dir(), namesize);
1157 offset = strlen(client_get_cur_dir());
1160 /* Loop through the blocks picking up the name */
1163 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1164 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1165 SAFE_FREE(longname);
1169 unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
1170 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
1179 static void do_tarput(void)
1182 struct timespec tp_start;
1183 char *longfilename = NULL, linkflag;
1188 clock_gettime_mono(&tp_start);
1189 DEBUG(5, ("RJS do_tarput called ...\n"));
1191 buffer_p = tarbuf + tbufsiz; /* init this to force first read */
1193 /* Now read through those files ... */
1195 /* Get us to the next block, or the first block first time around */
1196 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1197 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1198 SAFE_FREE(longfilename);
1202 DEBUG(5, ("Reading the next header ...\n"));
1204 switch (readtarheader((union hblock *) buffer_p,
1205 &finfo, client_get_cur_dir())) {
1206 case -2: /* Hmm, not good, but not fatal */
1207 DEBUG(0, ("Skipping %s...\n", finfo.name));
1208 if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) && !skip_file(finfo.size)) {
1209 DEBUG(0, ("Short file, bailing out...\n"));
1210 SAFE_FREE(longfilename);
1216 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1217 SAFE_FREE(longfilename);
1220 case 0: /* chksum is zero - looks like an EOF */
1221 DEBUG(0, ("tar: restored %d files and directories\n", ntarf));
1222 SAFE_FREE(longfilename);
1223 return; /* Hmmm, bad here ... */
1230 /* Now, do we have a long file name? */
1231 if (longfilename != NULL) {
1232 SAFE_FREE(finfo.name); /* Free the space already allocated */
1233 finfo.name = longfilename;
1234 longfilename = NULL;
1237 /* Well, now we have a header, process the file ... */
1238 /* Should we skip the file? We have the long name as well here */
1239 skip = clipn && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl) ||
1240 (tar_re_search && mask_match_list(finfo.name, cliplist, clipn, True)));
1242 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
1244 skip_file(finfo.size);
1248 /* We only get this far if we should process the file */
1249 linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag;
1251 case '0': /* Should use symbolic names--FIXME */
1253 * Skip to the next block first, so we can get the file, FIXME, should
1254 * be in get_file ...
1255 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1256 * Fixes bug where file size in tarfile is zero.
1258 if ((finfo.size != 0) && next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
1259 DEBUG(0, ("Short file, bailing out...\n"));
1262 if (!get_file(finfo)) {
1263 DEBUG(0, ("Abandoning restore\n"));
1268 if (!get_dir(finfo)) {
1269 DEBUG(0, ("Abandoning restore \n"));
1274 SAFE_FREE(longfilename);
1275 longfilename = get_longfilename(finfo);
1276 if (!longfilename) {
1277 DEBUG(0, ("abandoning restore\n"));
1280 DEBUG(5, ("Long file name: %s\n", longfilename));
1284 skip_file(finfo.size); /* Don't handle these yet */
1291 * samba interactive commands
1294 /****************************************************************************
1296 ***************************************************************************/
1300 TALLOC_CTX *ctx = talloc_tos();
1304 if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1305 DEBUG(0, ("blocksize <n>\n"));
1310 if (block < 0 || block > 65535) {
1311 DEBUG(0, ("blocksize out of range"));
1316 DEBUG(2,("blocksize is now %d\n", blocksize));
1320 /****************************************************************************
1321 command to set incremental / reset mode
1322 ***************************************************************************/
1324 int cmd_tarmode(void)
1326 TALLOC_CTX *ctx = talloc_tos();
1329 while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1330 if (strequal(buf, "full"))
1332 else if (strequal(buf, "inc"))
1334 else if (strequal(buf, "reset"))
1336 else if (strequal(buf, "noreset"))
1338 else if (strequal(buf, "system"))
1340 else if (strequal(buf, "nosystem"))
1342 else if (strequal(buf, "hidden"))
1344 else if (strequal(buf, "nohidden"))
1346 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
1348 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
1351 DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
1355 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1356 tar_inc ? "incremental" : "full",
1357 tar_system ? "system" : "nosystem",
1358 tar_hidden ? "hidden" : "nohidden",
1359 tar_reset ? "reset" : "noreset",
1360 tar_noisy ? "verbose" : "quiet"));
1364 /****************************************************************************
1365 Feeble attrib command
1366 ***************************************************************************/
1368 int cmd_setmode(void)
1370 TALLOC_CTX *ctx = talloc_tos();
1377 attra[0] = attra[1] = 0;
1379 if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1380 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1384 fname = talloc_asprintf(ctx,
1386 client_get_cur_dir(),
1392 while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1404 attra[direct]|=aRONLY;
1407 attra[direct]|=aHIDDEN;
1410 attra[direct]|=aSYSTEM;
1413 attra[direct]|=aARCH;
1416 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1422 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0) {
1423 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1427 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
1428 do_setrattr(fname, attra[ATTRSET], ATTRSET);
1429 do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
1434 Convert list of tokens to array; dependent on above routine.
1435 Uses the global cmd_ptr from above - bit of a hack.
1438 static char **toktocliplist(int *ctok, const char *sep)
1440 char *s=(char *)cmd_ptr;
1447 while(*s && strchr_m(sep,*s))
1456 while(*s && (!strchr_m(sep,*s)))
1458 while(*s && strchr_m(sep,*s))
1465 if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
1482 /****************************************************************************
1483 Principal command for creating / extracting
1484 ***************************************************************************/
1488 TALLOC_CTX *ctx = talloc_tos();
1494 if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
1495 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1499 argl=toktocliplist(&argcl, NULL);
1500 if (!tar_parseargs(argcl, argl, buf, 0)) {
1505 ret = process_tar();
1510 /****************************************************************************
1511 Command line (option) version
1512 ***************************************************************************/
1514 int process_tar(void)
1516 TALLOC_CTX *ctx = talloc_tos();
1532 if (clipn && tar_excl) {
1534 char *tarmac = NULL;
1536 for (i=0; i<clipn; i++) {
1537 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
1539 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
1540 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
1543 if (strrchr_m(cliplist[i], '\\')) {
1546 char *saved_dir = talloc_strdup(ctx,
1547 client_get_cur_dir());
1552 if (*cliplist[i]=='\\') {
1553 tarmac = talloc_strdup(ctx,
1556 tarmac = talloc_asprintf(ctx,
1558 client_get_cur_dir(),
1565 * Strip off the last \\xxx
1566 * xxx element of tarmac to set
1567 * it as current directory.
1569 p = strrchr_m(tarmac, '\\');
1576 client_set_cur_dir(tarmac);
1579 * Restore the character we
1586 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
1587 do_list(tarmac,attribute,do_tar, False, True);
1589 client_set_cur_dir(saved_dir);
1591 TALLOC_FREE(saved_dir);
1592 TALLOC_FREE(tarmac);
1594 tarmac = talloc_asprintf(ctx,
1596 client_get_cur_dir(),
1601 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
1602 do_list(tarmac,attribute,do_tar, False, True);
1603 TALLOC_FREE(tarmac);
1607 char *mask = talloc_asprintf(ctx,
1609 client_get_cur_dir());
1613 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask));
1614 do_list(mask,attribute,do_tar,False, True);
1619 dotareof(tarhandle);
1624 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf));
1625 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf));
1629 if (must_free_cliplist) {
1631 for (i = 0; i < clipn; ++i) {
1632 SAFE_FREE(cliplist[i]);
1634 SAFE_FREE(cliplist);
1637 must_free_cliplist = False;
1642 /****************************************************************************
1643 Find a token (filename) in a clip list
1644 ***************************************************************************/
1646 static int clipfind(char **aret, int ret, char *tok)
1651 /* ignore leading slashes or dots in token */
1652 while(strchr_m("/\\.", *tok))
1658 /* ignore leading slashes or dots in list */
1659 while(strchr_m("/\\.", *pkey))
1662 if (!strslashcmp(pkey, tok))
1668 /****************************************************************************
1669 Read list of files to include from the file and initialize cliplist
1671 ***************************************************************************/
1673 static int read_inclusion_file(char *filename)
1675 XFILE *inclusion = NULL;
1676 char buf[PATH_MAX + 1];
1677 char *inclusion_buffer = NULL;
1678 int inclusion_buffer_size = 0;
1679 int inclusion_buffer_sofar = 0;
1686 buf[PATH_MAX] = '\0'; /* guarantee null-termination */
1687 if ((inclusion = x_fopen(filename, O_RDONLY, 0)) == NULL) {
1688 /* XXX It would be better to include a reason for failure, but without
1689 * autoconf, it's hard to use strerror, sys_errlist, etc.
1691 DEBUG(0,("Unable to open inclusion file %s\n", filename));
1695 while ((! error) && (x_fgets(buf, sizeof(buf)-1, inclusion))) {
1696 if (inclusion_buffer == NULL) {
1697 inclusion_buffer_size = 1024;
1698 if ((inclusion_buffer = (char *)SMB_MALLOC(inclusion_buffer_size)) == NULL) {
1699 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1705 if (buf[strlen(buf)-1] == '\n') {
1706 buf[strlen(buf)-1] = '\0';
1709 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
1710 inclusion_buffer_size *= 2;
1711 inclusion_buffer = (char *)SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);
1712 if (!inclusion_buffer) {
1713 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1714 inclusion_buffer_size));
1720 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
1721 inclusion_buffer_sofar += strlen(buf) + 1;
1724 x_fclose(inclusion);
1727 /* Allocate an array of clipn + 1 char*'s for cliplist */
1728 cliplist = SMB_MALLOC_ARRAY(char *, clipn + 1);
1729 if (cliplist == NULL) {
1730 DEBUG(0,("failure allocating memory for cliplist\n"));
1733 cliplist[clipn] = NULL;
1734 p = inclusion_buffer;
1735 for (i = 0; (! error) && (i < clipn); i++) {
1736 /* set current item to NULL so array will be null-terminated even if
1737 * malloc fails below. */
1739 if ((tmpstr = (char *)SMB_MALLOC(strlen(p)+1)) == NULL) {
1740 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));
1743 unfixtarname(tmpstr, p, strlen(p) + 1, True);
1744 cliplist[i] = tmpstr;
1745 if ((p = strchr_m(p, '\000')) == NULL) {
1746 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1752 must_free_cliplist = True;
1756 SAFE_FREE(inclusion_buffer);
1760 /* We know cliplist is always null-terminated */
1761 for (pp = cliplist; *pp; ++pp) {
1764 SAFE_FREE(cliplist);
1766 must_free_cliplist = False;
1771 /* cliplist and its elements are freed at the end of process_tar. */
1775 /****************************************************************************
1776 Parse tar arguments. Sets tar_type, tar_excl, etc.
1777 ***************************************************************************/
1779 int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
1781 int newOptind = Optind;
1782 char tar_clipfl='\0';
1784 /* Reset back to defaults - could be from interactive version
1785 * reset mode and archive mode left as they are though
1797 if (tar_type=='c') {
1798 printf("Tar must be followed by only one of c or x.\n");
1804 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
1805 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1817 DEBUG(0,("Option N must be followed by valid file name\n"));
1820 SMB_STRUCT_STAT stbuf;
1822 if (sys_stat(argv[Optind], &stbuf,
1824 newer_than = convert_timespec_to_time_t(
1826 DEBUG(1,("Getting files newer than %s",
1827 time_to_asc(newer_than)));
1831 DEBUG(0,("Error setting newer-than time\n"));
1844 DEBUG(0,("Only one of I,X,F must be specified\n"));
1851 DEBUG(0,("Only one of I,X,F must be specified\n"));
1858 DEBUG(0,("Only one of I,X,F must be specified\n"));
1864 DEBUG(0, ("tar_re_search set\n"));
1865 tar_re_search = True;
1868 if (tar_type == 'c') {
1869 DEBUG(0, ("dry_run set\n"));
1872 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1877 DEBUG(0,("Unknown tar option\n"));
1883 printf("Option T must be followed by one of c or x.\n");
1887 /* tar_excl is true if cliplist lists files to be included.
1888 * Both 'I' and 'F' mean include. */
1889 tar_excl=tar_clipfl!='X';
1891 if (tar_clipfl=='F') {
1892 if (argc-Optind-1 != 1) {
1893 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1897 /* Optind points at the tar output file, Optind+1 at the inclusion file. */
1898 if (! read_inclusion_file(argv[Optind+1])) {
1901 } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
1906 cliplist=argv+Optind+1;
1907 clipn=argc-Optind-1;
1910 if ((tmplist=SMB_MALLOC_ARRAY(char *,clipn)) == NULL) {
1911 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn));
1915 for (clipcount = 0; clipcount < clipn; clipcount++) {
1917 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
1919 if ((tmpstr = (char *)SMB_MALLOC(strlen(cliplist[clipcount])+1)) == NULL) {
1920 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount));
1925 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);
1926 tmplist[clipcount] = tmpstr;
1927 DEBUG(5, ("Processed an item, %s\n", tmpstr));
1929 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
1933 must_free_cliplist = True;
1938 if (Optind+1<argc && tar_re_search && tar_clipfl != 'F') {
1939 /* Doing regular expression seaches not from an inclusion file. */
1940 clipn=argc-Optind-1;
1941 cliplist=argv+Optind+1;
1945 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
1946 /* Sets tar handle to either 0 or 1, as appropriate */
1947 tarhandle=(tar_type=='c');
1949 * Make sure that dbf points to stderr if we are using stdout for
1952 if (tarhandle == 1) {
1953 setup_logging("smbclient", DEBUG_STDERR);
1955 if (!argv[Optind]) {
1956 DEBUG(0,("Must specify tar filename\n"));
1959 if (!strcmp(argv[Optind], "-")) {
1964 if (tar_type=='c' && dry_run) {
1966 } else if ((tar_type=='x' && (tarhandle = sys_open(argv[Optind], O_RDONLY, 0)) == -1)
1967 || (tar_type=='c' && (tarhandle=sys_creat(argv[Optind], 0644)) < 0)) {
1968 DEBUG(0,("Error opening local file %s - %s\n", argv[Optind], strerror(errno)));