root/source3/client/clitar.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. string_create_s
  2. writetarheader
  3. readtarheader
  4. dotarbuf
  5. dozerobuf
  6. initarbuf
  7. dotareof
  8. fixtarname
  9. oct_it
  10. unoct
  11. strslashcmp
  12. ensurepath
  13. padit
  14. do_setrattr
  15. do_atar
  16. do_tar
  17. unfixtarname
  18. next_block
  19. skip_file
  20. get_file
  21. get_dir
  22. get_longfilename
  23. do_tarput
  24. cmd_block
  25. cmd_tarmode
  26. cmd_setmode
  27. toktocliplist
  28. cmd_tar
  29. process_tar
  30. clipfind
  31. read_inclusion_file
  32. tar_parseargs

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

/* [<][>][^][v][top][bottom][index][help] */