updating documentation to reflect code a little bit.
[Samba.git] / source / client / clitar.c
bloba4c1f00adf33b06d7678bea620db1f0c5b9750a2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Tar Extensions
5 Copyright (C) Ricky Poulten 1995
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "clitar.h"
26 extern BOOL recurse;
28 #define SEPARATORS " \t\n\r"
29 extern int DEBUGLEVEL;
30 extern int Client;
32 /* These defines are for the do_setrattr routine, to indicate
33 * setting and reseting of file attributes in the function call */
34 #define ATTRSET 1
35 #define ATTRRESET 0
37 static int attribute = aDIR | aSYSTEM | aHIDDEN;
39 #ifndef CLIENT_TIMEOUT
40 #define CLIENT_TIMEOUT (30*1000)
41 #endif
43 static char *tarbuf;
44 static int tp, ntarf, tbufsiz;
45 /* Incremental mode */
46 BOOL tar_inc=False;
47 /* Reset archive bit */
48 BOOL tar_reset=False;
49 /* Include / exclude mode (true=include, false=exclude) */
50 BOOL tar_excl=True;
51 char tar_type='\0';
52 static char **cliplist=NULL;
53 static int clipn=0;
55 extern file_info def_finfo;
56 extern BOOL lowercase;
57 extern int cnum;
58 extern BOOL readbraw_supported;
59 extern int max_xmit;
60 extern pstring cur_dir;
61 extern int get_total_time_ms;
62 extern int get_total_size;
63 extern int Protocol;
65 int blocksize=20;
66 int tarhandle;
68 static void writetarheader();
69 static void do_atar();
70 static void do_tar();
71 static void oct_it();
72 static void fixtarname();
73 static int dotarbuf();
74 static void dozerobuf();
75 static void dotareof();
76 static void initarbuf();
77 static int do_setrattr();
79 /* restore functions */
80 static long readtarheader();
81 static long unoct();
82 static void do_tarput();
83 static void unfixtarname();
86 * tar specific utitlities
89 /****************************************************************************
90 Write a tar header to buffer
91 ****************************************************************************/
92 static void writetarheader(int f, char *aname, int size, time_t mtime,
93 char *amode)
95 union hblock hb;
96 int i, chk, l;
97 char *jp;
99 memset(hb.dummy, 0, sizeof(hb.dummy));
101 l=strlen(aname);
102 if (l >= NAMSIZ)
104 DEBUG(0, ("tar file %s name length exceeds NAMSIZ\n", aname));
107 /* use l + 1 to do the null too */
108 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
110 if (lowercase)
111 strlower(hb.dbuf.name);
113 /* write out a "standard" tar format header */
115 hb.dbuf.name[NAMSIZ-1]='\0';
116 strcpy(hb.dbuf.mode, amode);
117 oct_it(0L, 8, hb.dbuf.uid);
118 oct_it(0L, 8, hb.dbuf.gid);
119 oct_it((long) size, 13, hb.dbuf.size);
120 oct_it((long) mtime, 13, hb.dbuf.mtime);
121 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
122 hb.dbuf.linkflag='0';
123 memset(hb.dbuf.linkname, 0, NAMSIZ);
125 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
127 oct_it((long) chk, 8, hb.dbuf.chksum);
128 hb.dbuf.chksum[6] = '\0';
130 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
133 /****************************************************************************
134 Read a tar header into a hblock structure, and validate
135 ***************************************************************************/
136 static long readtarheader(union hblock *hb, file_info *finfo, char *prefix)
138 long chk, fchk;
139 int i;
140 char *jp;
143 * read in a "standard" tar format header - we're not that interested
144 * in that many fields, though
147 /* check the checksum */
148 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
150 if (chk == 0)
151 return chk;
153 /* compensate for blanks in chksum header */
154 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
155 chk-=(0xFF & *jp++);
157 chk += ' ' * sizeof(hb->dbuf.chksum);
159 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
161 DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
162 chk, fchk, hb->dbuf.chksum));
164 if (fchk != chk)
166 DEBUG(0, ("checksums don't match %d %d\n", fchk, chk));
167 return -1;
170 strcpy(finfo->name, prefix);
172 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
173 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
174 strlen(hb->dbuf.name) + 1);
176 /* can't handle links at present */
177 if (hb->dbuf.linkflag != '0') {
178 if (hb->dbuf.linkflag == 0) {
179 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
180 finfo->name));
181 } else {
182 DEBUG(0, ("this tar file appears to contain some kind of link - ignoring\n"));
183 return -2;
187 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
188 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
190 finfo->mode=aDIR;
192 else
193 finfo->mode=0; /* we don't care about mode at the moment, we'll
194 * just make it a regular file */
196 * Bug fix by richard@sj.co.uk
198 * REC: restore times correctly (as does tar)
199 * We only get the modification time of the file; set the creation time
200 * from the mod. time, and the access time to current time
202 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
203 finfo->atime = time(NULL);
204 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
206 return True;
209 /****************************************************************************
210 Write out the tar buffer to tape or wherever
211 ****************************************************************************/
212 static int dotarbuf(int f, char *b, int n)
214 int fail=1, writ=n;
216 /* This routine and the next one should be the only ones that do write()s */
217 if (tp + n >= tbufsiz)
219 int diff;
221 diff=tbufsiz-tp;
222 memcpy(tarbuf + tp, b, diff);
223 fail=fail && (1+write(f, tarbuf, tbufsiz));
224 n-=diff;
225 b+=diff;
226 tp=0;
228 while (n >= tbufsiz)
230 fail=fail && (1 + write(f, b, tbufsiz));
231 n-=tbufsiz;
232 b+=tbufsiz;
235 if (n>0) {
236 memcpy(tarbuf+tp, b, n);
237 tp+=n;
240 return(fail ? writ : 0);
243 /****************************************************************************
244 Write a zeros to buffer / tape
245 ****************************************************************************/
246 static void dozerobuf(int f, int n)
248 /* short routine just to write out n zeros to buffer -
249 * used to round files to nearest block
250 * and to do tar EOFs */
252 if (n+tp >= tbufsiz)
254 memset(tarbuf+tp, 0, tbufsiz-tp);
255 write(f, tarbuf, tbufsiz);
256 memset(tarbuf, 0, (tp+=n-tbufsiz));
258 else
260 memset(tarbuf+tp, 0, n);
261 tp+=n;
265 /****************************************************************************
266 Malloc tape buffer
267 ****************************************************************************/
268 static void initarbuf()
270 /* initialize tar buffer */
271 tbufsiz=blocksize*TBLOCK;
272 tarbuf=malloc(tbufsiz);
274 /* reset tar buffer pointer and tar file counter */
275 tp=0; ntarf=0;
278 /****************************************************************************
279 Write two zero blocks at end of file
280 ****************************************************************************/
281 static void dotareof(int f)
283 struct stat stbuf;
284 /* Two zero blocks at end of file, write out full buffer */
286 (void) dozerobuf(f, TBLOCK);
287 (void) dozerobuf(f, TBLOCK);
289 if (fstat(f, &stbuf) == -1)
291 DEBUG(0, ("Couldn't stat file handle\n"));
292 return;
295 /* Could be a pipe, in which case S_ISREG should fail,
296 * and we should write out at full size */
297 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
300 /****************************************************************************
301 (Un)mangle DOS pathname, make nonabsolute
302 ****************************************************************************/
303 static void fixtarname(char *tptr, char *fp, int l)
305 /* add a '.' to start of file name, convert from ugly dos \'s in path
306 * to lovely unix /'s :-} */
308 *tptr++='.';
309 #ifdef KANJI
310 while (l > 0) {
311 if (is_shift_jis (*fp)) {
312 *tptr++ = *fp++;
313 *tptr++ = *fp++;
314 l -= 2;
315 } else if (is_kana (*fp)) {
316 *tptr++ = *fp++;
317 l--;
318 } else if (*fp == '\\') {
319 *tptr++ = '/';
320 fp++;
321 l--;
322 } else {
323 *tptr++ = *fp++;
324 l--;
327 #else
328 while (l--) { *tptr=(*fp == '\\') ? '/' : *fp; tptr++; fp++; }
329 #endif
332 /****************************************************************************
333 Convert from decimal to octal string
334 ****************************************************************************/
335 static void oct_it (register long value, register int ndgs, register char *p)
337 /* Converts long to octal string, pads with leading zeros */
339 /* skip final null, but do final space */
340 --ndgs;
341 p[--ndgs] = ' ';
343 /* Loop does at least one digit */
344 do {
345 p[--ndgs] = '0' + (char) (value & 7);
346 value >>= 3;
348 while (ndgs > 0 && value != 0);
350 /* Do leading zeros */
351 while (ndgs > 0)
352 p[--ndgs] = '0';
355 /****************************************************************************
356 Convert from octal string to long
357 ***************************************************************************/
358 static long unoct(char *p, int ndgs)
360 long value=0;
361 /* Converts octal string to long, ignoring any non-digit */
363 while (--ndgs)
365 if (isdigit(*p))
366 value = (value << 3) | (long) (*p - '0');
368 p++;
371 return value;
374 /****************************************************************************
375 Compare two strings in a slash insensitive way
376 ***************************************************************************/
377 int strslashcmp(const char *s1, const char *s2)
379 while(*s1 && *s2 &&
380 (*s1 == *s2
381 || tolower(*s1) == tolower(*s2)
382 || (*s1 == '\\' && *s2=='/')
383 || (*s1 == '/' && *s2=='\\'))) {
384 s1++; s2++;
387 return *s1-*s2;
391 * general smb utility functions
393 /****************************************************************************
394 Set DOS file attributes
395 ***************************************************************************/
396 static int do_setrattr(char *fname, int attr, int setit)
399 * First get the existing attribs from existing file
401 char *inbuf,*outbuf;
402 char *p;
403 pstring name;
404 int fattr;
406 strcpy(name,fname);
407 strcpy(fname,"\\");
408 strcat(fname,name);
410 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
411 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
413 if (!inbuf || !outbuf)
415 DEBUG(0,("out of memory\n"));
416 return False;
419 /* send an smb getatr message */
421 memset(outbuf,0,smb_size);
422 set_message(outbuf,0,2 + strlen(fname),True);
423 CVAL(outbuf,smb_com) = SMBgetatr;
424 SSVAL(outbuf,smb_tid,cnum);
425 setup_pkt(outbuf);
427 p = smb_buf(outbuf);
428 *p++ = 4;
429 strcpy(p,fname);
430 p += (strlen(fname)+1);
432 *p++ = 4;
433 *p++ = 0;
435 send_smb(Client,outbuf);
436 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
438 if (CVAL(inbuf,smb_rcls) != 0)
439 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
440 else
442 DEBUG(5,("\nattr 0x%X time %d size %d\n",
443 (int)CVAL(inbuf,smb_vwv0),
444 SVAL(inbuf,smb_vwv1),
445 SVAL(inbuf,smb_vwv3)));
448 fattr=CVAL(inbuf,smb_vwv0);
450 /* combine found attributes with bits to be set or reset */
452 attr=setit ? (fattr | attr) : (fattr & ~attr);
454 /* now try and set attributes by sending smb reset message */
456 /* clear out buffer and start again */
457 memset(outbuf,0,smb_size);
458 set_message(outbuf,8,4 + strlen(fname),True);
459 CVAL(outbuf,smb_com) = SMBsetatr;
460 SSVAL(outbuf,smb_tid,cnum);
461 setup_pkt(outbuf);
463 SSVAL(outbuf,smb_vwv0,attr);
465 p = smb_buf(outbuf);
466 *p++ = 4;
467 strcpy(p,fname);
468 p += (strlen(fname)+1);
470 *p++ = 4;
471 *p++ = 0;
473 send_smb(Client,outbuf);
474 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
476 if (CVAL(inbuf,smb_rcls) != 0)
478 DEBUG(0,("%s setting attributes on file %s\n",
479 smb_errstr(inbuf), fname));
480 free(inbuf);free(outbuf);
481 return(False);
484 free(inbuf);free(outbuf);
485 return(True);
488 /****************************************************************************
489 Create a file on a share
490 ***************************************************************************/
491 static BOOL smbcreat(file_info finfo, int *fnum, char *inbuf, char *outbuf)
493 char *p;
494 /* *must* be called with buffer ready malloc'ed */
495 /* open remote file */
497 memset(outbuf,0,smb_size);
498 set_message(outbuf,3,2 + strlen(finfo.name),True);
499 CVAL(outbuf,smb_com) = SMBcreate;
500 SSVAL(outbuf,smb_tid,cnum);
501 setup_pkt(outbuf);
503 SSVAL(outbuf,smb_vwv0,finfo.mode);
504 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
506 p = smb_buf(outbuf);
507 *p++ = 4;
508 strcpy(p,finfo.name);
510 send_smb(Client,outbuf);
511 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
513 if (CVAL(inbuf,smb_rcls) != 0)
515 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
516 finfo.name));
517 return 0;
520 *fnum = SVAL(inbuf,smb_vwv0);
521 return True;
524 /****************************************************************************
525 Write a file to a share
526 ***************************************************************************/
527 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
528 char *bufferp, char *inbuf, char *outbuf)
530 /* *must* be called with buffer ready malloc'ed */
532 memset(outbuf,0,smb_size);
533 set_message(outbuf,5,n + 3,True);
535 memcpy(smb_buf(outbuf)+3, bufferp, n);
537 set_message(outbuf,5,n + 3, False);
538 CVAL(outbuf,smb_com) = SMBwrite;
539 SSVAL(outbuf,smb_tid,cnum);
540 setup_pkt(outbuf);
542 SSVAL(outbuf,smb_vwv0,fnum);
543 SSVAL(outbuf,smb_vwv1,n);
544 SIVAL(outbuf,smb_vwv2,low);
545 SSVAL(outbuf,smb_vwv4,left);
546 CVAL(smb_buf(outbuf),0) = 1;
547 SSVAL(smb_buf(outbuf),1,n);
549 send_smb(Client,outbuf);
550 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
552 if (CVAL(inbuf,smb_rcls) != 0)
554 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
555 return False;
558 if (n != SVAL(inbuf,smb_vwv0))
560 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
561 SVAL(inbuf,smb_vwv0), n));
562 return False;
565 return True;
568 /****************************************************************************
569 Close a file on a share
570 ***************************************************************************/
571 static BOOL smbshut(file_info finfo, int fnum, char *inbuf, char *outbuf)
573 /* *must* be called with buffer ready malloc'ed */
575 memset(outbuf,0,smb_size);
576 set_message(outbuf,3,0,True);
577 CVAL(outbuf,smb_com) = SMBclose;
578 SSVAL(outbuf,smb_tid,cnum);
579 setup_pkt(outbuf);
581 SSVAL(outbuf,smb_vwv0,fnum);
582 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
584 DEBUG(3,("Setting date to %s (0x%X)",
585 asctime(LocalTime(&finfo.mtime)),
586 finfo.mtime));
588 send_smb(Client,outbuf);
589 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
591 if (CVAL(inbuf,smb_rcls) != 0)
593 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
594 finfo.name));
595 return False;
598 return True;
601 /****************************************************************************
602 Verify existence of path on share
603 ***************************************************************************/
604 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
606 char *p;
608 memset(outbuf,0,smb_size);
609 set_message(outbuf,0,4 + strlen(fname),True);
610 CVAL(outbuf,smb_com) = SMBchkpth;
611 SSVAL(outbuf,smb_tid,cnum);
612 setup_pkt(outbuf);
614 p = smb_buf(outbuf);
615 *p++ = 4;
616 strcpy(p,fname);
618 send_smb(Client,outbuf);
619 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
621 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
623 return(CVAL(inbuf,smb_rcls) == 0);
626 /****************************************************************************
627 Make a directory on share
628 ***************************************************************************/
629 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
631 /* *must* be called with buffer ready malloc'ed */
632 char *p;
634 memset(outbuf,0,smb_size);
635 set_message(outbuf,0,2 + strlen(fname),True);
637 CVAL(outbuf,smb_com) = SMBmkdir;
638 SSVAL(outbuf,smb_tid,cnum);
639 setup_pkt(outbuf);
641 p = smb_buf(outbuf);
642 *p++ = 4;
643 strcpy(p,fname);
645 send_smb(Client,outbuf);
646 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
648 if (CVAL(inbuf,smb_rcls) != 0)
650 DEBUG(0,("%s making remote directory %s\n",
651 smb_errstr(inbuf),fname));
652 return(False);
655 return(True);
658 /****************************************************************************
659 Ensure a remote path exists (make if necessary)
660 ***************************************************************************/
661 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
663 /* *must* be called with buffer ready malloc'ed */
664 /* ensures path exists */
666 pstring partpath, ffname;
667 char *p=fname, *basehack;
669 *partpath = 0;
671 /* fname copied to ffname so can strtok */
673 strcpy(ffname, fname);
675 /* do a `basename' on ffname, so don't try and make file name directory */
676 if ((basehack=strrchr(ffname, '\\')) == NULL)
677 return True;
678 else
679 *basehack='\0';
681 p=strtok(ffname, "\\");
683 while (p)
685 strcat(partpath, p);
687 if (!smbchkpath(partpath, inbuf, outbuf)) {
688 if (!smbmkdir(partpath, inbuf, outbuf))
690 DEBUG(0, ("Error mkdirhiering\n"));
691 return False;
693 else
694 DEBUG(3, ("mkdirhiering %s\n", partpath));
698 strcat(partpath, "\\");
699 p = strtok(NULL,"/\\");
702 return True;
706 * smbclient functions
708 /****************************************************************************
709 append one remote file to the tar file
710 ***************************************************************************/
711 static void do_atar(char *rname,char *lname,file_info *finfo1)
713 int fnum;
714 uint32 nread=0;
715 char *p;
716 char *inbuf,*outbuf;
717 file_info finfo;
718 BOOL close_done = False;
719 BOOL shallitime=True;
720 BOOL ignore_close_error = False;
721 char *dataptr=NULL;
722 int datalen=0;
724 struct timeval tp_start;
725 GetTimeOfDay(&tp_start);
727 if (finfo1)
728 finfo = *finfo1;
729 else
730 finfo = def_finfo;
732 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
733 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
735 if (!inbuf || !outbuf)
737 DEBUG(0,("out of memory\n"));
738 return;
741 memset(outbuf,0,smb_size);
742 set_message(outbuf,15,1 + strlen(rname),True);
744 CVAL(outbuf,smb_com) = SMBopenX;
745 SSVAL(outbuf,smb_tid,cnum);
746 setup_pkt(outbuf);
748 SSVAL(outbuf,smb_vwv0,0xFF);
749 SSVAL(outbuf,smb_vwv2,1);
750 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
751 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
752 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
753 SSVAL(outbuf,smb_vwv8,1);
755 p = smb_buf(outbuf);
756 strcpy(p,rname);
757 p = skip_string(p,1);
759 dos_clean_name(rname);
761 /* do a chained openX with a readX? */
762 if (finfo.size > 0)
764 SSVAL(outbuf,smb_vwv0,SMBreadX);
765 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
766 memset(p,0,200);
767 p -= smb_wct;
768 SSVAL(p,smb_wct,10);
769 SSVAL(p,smb_vwv0,0xFF);
770 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
771 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
772 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
775 send_smb(Client,outbuf);
776 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
778 if (CVAL(inbuf,smb_rcls) != 0)
780 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
781 SVAL(inbuf,smb_err) == ERRnoresource &&
782 reopen_connection(inbuf,outbuf))
784 do_atar(rname,lname,finfo1);
785 free(inbuf);free(outbuf);
786 return;
789 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
790 free(inbuf);free(outbuf);
791 return;
794 strcpy(finfo.name,rname);
795 if (!finfo1)
797 finfo.mode = SVAL(inbuf,smb_vwv3);
798 finfo.size = IVAL(inbuf,smb_vwv4);
799 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
800 finfo.atime = finfo.ctime = finfo.mtime;
803 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
805 fnum = SVAL(inbuf,smb_vwv2);
807 if (tar_inc && !(finfo.mode & aARCH))
809 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
810 shallitime=0;
812 else
814 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
816 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
817 datalen = SVAL(p,smb_vwv5);
818 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
820 else
822 dataptr = NULL;
823 datalen = 0;
826 DEBUG(2,("getting file %s of size %d bytes as a tar file %s",
827 finfo.name,
828 finfo.size,
829 lname));
831 /* write a tar header, don't bother with mode - just set to 100644 */
832 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0");
834 while (nread < finfo.size && !close_done)
836 int method = -1;
837 static BOOL can_chain_close=True;
839 p=NULL;
841 DEBUG(3,("nread=%d\n",nread));
843 /* 3 possible read types. readbraw if a large block is required.
844 readX + close if not much left and read if neither is supported */
846 /* we might have already read some data from a chained readX */
847 if (dataptr && datalen>0)
848 method=3;
850 /* if we can finish now then readX+close */
851 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
852 ((finfo.size - nread) <
853 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
854 method = 0;
856 /* if we support readraw then use that */
857 if (method<0 && readbraw_supported)
858 method = 1;
860 /* if we can then use readX */
861 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
862 method = 2;
865 switch (method)
867 /* use readX */
868 case 0:
869 case 2:
870 if (method == 0)
871 close_done = True;
873 /* use readX + close */
874 memset(outbuf,0,smb_size);
875 set_message(outbuf,10,0,True);
876 CVAL(outbuf,smb_com) = SMBreadX;
877 SSVAL(outbuf,smb_tid,cnum);
878 setup_pkt(outbuf);
880 if (close_done)
882 CVAL(outbuf,smb_vwv0) = SMBclose;
883 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
885 else
886 CVAL(outbuf,smb_vwv0) = 0xFF;
889 SSVAL(outbuf,smb_vwv2,fnum);
890 SIVAL(outbuf,smb_vwv3,nread);
891 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
892 SSVAL(outbuf,smb_vwv6,0);
893 SIVAL(outbuf,smb_vwv7,0);
894 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
896 if (close_done)
898 p = smb_buf(outbuf);
899 memset(p,0,9);
901 CVAL(p,0) = 3;
902 SSVAL(p,1,fnum);
903 SIVALS(p,3,-1);
905 /* now set the total packet length */
906 smb_setlen(outbuf,smb_len(outbuf)+9);
909 send_smb(Client,outbuf);
910 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
912 if (CVAL(inbuf,smb_rcls) != 0)
914 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
915 break;
918 if (close_done &&
919 SVAL(inbuf,smb_vwv0) != SMBclose)
921 /* NOTE: WfWg sometimes just ignores the chained
922 command! This seems to break the spec? */
923 DEBUG(3,("Rejected chained close?\n"));
924 close_done = False;
925 can_chain_close = False;
926 ignore_close_error = True;
929 datalen = SVAL(inbuf,smb_vwv5);
930 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
931 break;
934 /* use readbraw */
935 case 1:
937 static int readbraw_size = 0xFFFF;
939 extern int Client;
940 memset(outbuf,0,smb_size);
941 set_message(outbuf,8,0,True);
942 CVAL(outbuf,smb_com) = SMBreadbraw;
943 SSVAL(outbuf,smb_tid,cnum);
944 setup_pkt(outbuf);
945 SSVAL(outbuf,smb_vwv0,fnum);
946 SIVAL(outbuf,smb_vwv1,nread);
947 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
948 SSVAL(outbuf,smb_vwv4,0);
949 SIVALS(outbuf,smb_vwv5,-1);
950 send_smb(Client,outbuf);
952 /* Now read the raw data into the buffer and write it */
953 if(read_smb_length(Client,inbuf,0) == -1) {
954 DEBUG(0,("Failed to read length in readbraw\n"));
955 exit(1);
958 /* Even though this is not an smb message, smb_len
959 returns the generic length of an smb message */
960 datalen = smb_len(inbuf);
962 if (datalen == 0)
964 /* we got a readbraw error */
965 DEBUG(4,("readbraw error - reducing size\n"));
966 readbraw_size = (readbraw_size * 9) / 10;
968 if (readbraw_size < max_xmit)
970 DEBUG(0,("disabling readbraw\n"));
971 readbraw_supported = False;
974 dataptr=NULL;
975 continue;
978 if(read_data(Client,inbuf,datalen) != datalen) {
979 DEBUG(0,("Failed to read data in readbraw\n"));
980 exit(1);
982 dataptr = inbuf;
984 break;
986 case 3:
987 /* we've already read some data with a chained readX */
988 break;
990 default:
991 /* use plain read */
992 memset(outbuf,0,smb_size);
993 set_message(outbuf,5,0,True);
994 CVAL(outbuf,smb_com) = SMBread;
995 SSVAL(outbuf,smb_tid,cnum);
996 setup_pkt(outbuf);
998 SSVAL(outbuf,smb_vwv0,fnum);
999 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1000 SIVAL(outbuf,smb_vwv2,nread);
1001 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1003 send_smb(Client,outbuf);
1004 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1006 if (CVAL(inbuf,smb_rcls) != 0)
1008 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1009 break;
1012 datalen = SVAL(inbuf,smb_vwv0);
1013 dataptr = smb_buf(inbuf) + 3;
1014 break;
1018 /* add received bits of file to buffer - dotarbuf will
1019 * write out in 512 byte intervals */
1020 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1022 DEBUG(0,("Error writing local file\n"));
1023 break;
1026 nread += datalen;
1027 if (datalen == 0)
1029 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1030 break;
1033 dataptr=NULL;
1034 datalen=0;
1037 /* round tar file to nearest block */
1038 if (finfo.size % TBLOCK)
1039 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1041 ntarf++;
1044 if (!close_done)
1046 memset(outbuf,0,smb_size);
1047 set_message(outbuf,3,0,True);
1048 CVAL(outbuf,smb_com) = SMBclose;
1049 SSVAL(outbuf,smb_tid,cnum);
1050 setup_pkt(outbuf);
1052 SSVAL(outbuf,smb_vwv0,fnum);
1053 SIVALS(outbuf,smb_vwv1,-1);
1055 send_smb(Client,outbuf);
1056 receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1058 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1060 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1061 free(inbuf);free(outbuf);
1062 return;
1066 if (shallitime)
1068 struct timeval tp_end;
1069 int this_time;
1071 /* if shallitime is true then we didn't skip */
1072 if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1074 GetTimeOfDay(&tp_end);
1075 this_time =
1076 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1077 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1078 get_total_time_ms += this_time;
1079 get_total_size += finfo.size;
1081 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1082 DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
1083 finfo.size / MAX(0.001, (1.024*this_time)),
1084 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1087 free(inbuf);free(outbuf);
1090 /****************************************************************************
1091 Append single file to tar file (or not)
1092 ***************************************************************************/
1093 static void do_tar(file_info *finfo)
1095 pstring rname;
1097 if (strequal(finfo->name,".") || strequal(finfo->name,".."))
1098 return;
1100 /* Is it on the exclude list ? */
1101 if (!tar_excl && clipn) {
1102 pstring exclaim;
1104 strcpy(exclaim, cur_dir);
1105 *(exclaim+strlen(exclaim)-1)='\0';
1107 if (clipfind(cliplist, clipn, exclaim)) {
1108 DEBUG(3,("Skipping directory %s\n", exclaim));
1109 return;
1112 strcat(exclaim, "\\");
1113 strcat(exclaim, finfo->name);
1115 if (clipfind(cliplist, clipn, exclaim)) {
1116 DEBUG(3,("Skipping file %s\n", exclaim));
1117 return;
1121 if (finfo->mode & aDIR)
1123 pstring saved_curdir;
1124 pstring mtar_mask;
1125 char *inbuf,*outbuf;
1127 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1128 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1130 if (!inbuf || !outbuf)
1132 DEBUG(0,("out of memory\n"));
1133 return;
1136 strcpy(saved_curdir,cur_dir);
1138 strcat(cur_dir,finfo->name);
1139 strcat(cur_dir,"\\");
1141 /* write a tar directory, don't bother with mode - just set it to
1142 * 40755 */
1143 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0");
1144 strcpy(mtar_mask,cur_dir);
1145 strcat(mtar_mask,"*");
1147 do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse);
1148 strcpy(cur_dir,saved_curdir);
1149 free(inbuf);free(outbuf);
1151 else
1153 strcpy(rname,cur_dir);
1154 strcat(rname,finfo->name);
1155 do_atar(rname,finfo->name,finfo);
1159 /****************************************************************************
1160 Convert from UNIX to DOS file names
1161 ***************************************************************************/
1162 static void unfixtarname(char *tptr, char *fp, int l)
1164 /* remove '.' from start of file name, convert from unix /'s to
1165 * dos \'s in path. Kill any absolute path names.
1168 if (*fp == '.') fp++;
1169 if (*fp == '\\' || *fp == '/') fp++;
1171 #ifdef KANJI
1172 while (l > 0) {
1173 if (is_shift_jis (*fp)) {
1174 *tptr++ = *fp++;
1175 *tptr++ = *fp++;
1176 l -= 2;
1177 } else if (is_kana (*fp)) {
1178 *tptr++ = *fp++;
1179 l--;
1180 } else if (*fp == '/') {
1181 *tptr++ = '\\';
1182 fp++;
1183 l--;
1184 } else {
1185 *tptr++ = *fp++;
1186 l--;
1189 #else
1190 while (l--) { *tptr=(*fp == '/') ? '\\' : *fp; tptr++; fp++; }
1191 #endif
1194 static void do_tarput()
1196 file_info finfo;
1197 int nread=0, bufread;
1198 char *inbuf,*outbuf;
1199 int fsize=0;
1200 int fnum;
1201 struct timeval tp_start;
1202 BOOL tskip=False; /* We'll take each file as it comes */
1204 GetTimeOfDay(&tp_start);
1206 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1207 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1209 if (!inbuf || !outbuf)
1211 DEBUG(0,("out of memory\n"));
1212 return;
1216 * Must read in tbufsiz dollops
1219 /* These should be the only reads in clitar.c */
1220 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1221 char *bufferp, *endofbuffer;
1222 int chunk;
1224 /* Code to handle a short read.
1225 * We always need a TBLOCK full of stuff
1227 if (bufread % TBLOCK) {
1228 int lchunk=TBLOCK-(bufread % TBLOCK);
1229 int lread;
1231 /* It's a shorty - a short read that is */
1232 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1234 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1235 bufread+=lread;
1236 if (!(lchunk-=lread)) break;
1239 /* If we've reached EOF then that must be a short file */
1240 if (lread<=0) break;
1243 bufferp=tarbuf;
1244 endofbuffer=tarbuf+bufread;
1246 if (tskip) {
1247 if (fsize<bufread) {
1248 tskip=False;
1249 bufferp+=fsize;
1250 fsize=0;
1251 } else {
1252 if (fsize==bufread) tskip=False;
1253 fsize-=bufread;
1254 continue;
1258 do {
1259 if (!fsize)
1261 switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir))
1263 case -2: /* something dodgy but not fatal about this */
1264 DEBUG(0, ("skipping %s...\n", finfo.name));
1265 bufferp+=TBLOCK; /* header - like a link */
1266 continue;
1267 case -1:
1268 DEBUG(0, ("abandoning restore\n"));
1269 free(inbuf); free(outbuf);
1270 return;
1271 case 0: /* chksum is zero - we assume that one all zero
1272 *header block will do for eof */
1273 DEBUG(0,
1274 ("total of %d tar files restored to share\n", ntarf));
1275 free(inbuf); free(outbuf);
1276 return;
1277 default:
1278 break;
1281 tskip=clipn
1282 && (clipfind(cliplist, clipn, finfo.name) ^ tar_excl);
1283 if (tskip) {
1284 bufferp+=TBLOCK;
1285 if (finfo.mode & aDIR)
1286 continue;
1287 else if ((fsize=finfo.size) % TBLOCK) {
1288 fsize+=TBLOCK-(fsize%TBLOCK);
1290 if (fsize<endofbuffer-bufferp) {
1291 bufferp+=fsize;
1292 fsize=0;
1293 continue;
1294 } else {
1295 fsize-=endofbuffer-bufferp;
1296 break;
1300 if (finfo.mode & aDIR)
1302 if (!smbchkpath(finfo.name, inbuf, outbuf)
1303 && !smbmkdir(finfo.name, inbuf, outbuf))
1305 DEBUG(0, ("abandoning restore\n"));
1306 free(inbuf); free(outbuf);
1307 return;
1309 else
1311 bufferp+=TBLOCK;
1312 continue;
1316 fsize=finfo.size;
1318 if (ensurepath(finfo.name, inbuf, outbuf)
1319 && !smbcreat(finfo, &fnum, inbuf, outbuf))
1321 DEBUG(0, ("abandoning restore\n"));
1322 free(inbuf);free(outbuf);
1323 return;
1326 DEBUG(0,("restore tar file %s of size %d bytes\n",
1327 finfo.name,finfo.size));
1329 nread=0;
1330 if ((bufferp+=TBLOCK) >= endofbuffer) break;
1331 } /* if (!fsize) */
1333 /* write out the file in chunk sized chunks - don't
1334 * go past end of buffer though */
1335 chunk=(fsize-nread < endofbuffer - bufferp)
1336 ? fsize - nread : endofbuffer - bufferp;
1338 while (chunk > 0) {
1339 int minichunk=MIN(chunk, max_xmit-200);
1341 if (!smbwrite(fnum, /* file descriptor */
1342 minichunk, /* n */
1343 nread, /* offset low */
1344 0, /* offset high - not implemented */
1345 fsize-nread, /* left - only hint to server */
1346 bufferp,
1347 inbuf,
1348 outbuf))
1350 DEBUG(0, ("Error writing remote file\n"));
1351 free(inbuf); free(outbuf);
1352 return;
1354 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
1356 bufferp+=minichunk; nread+=minichunk;
1357 chunk-=minichunk;
1360 if (nread>=fsize)
1362 if (!smbshut(finfo, fnum, inbuf, outbuf))
1364 DEBUG(0, ("Error closing remote file\n"));
1365 free(inbuf);free(outbuf);
1366 return;
1368 if (fsize % TBLOCK) bufferp+=TBLOCK - (fsize % TBLOCK);
1369 DEBUG(5, ("bufferp is now %d (psn=%d)\n",
1370 (long) bufferp, (long)(bufferp - tarbuf)));
1371 ntarf++;
1372 fsize=0;
1374 } while (bufferp < endofbuffer);
1377 DEBUG(0, ("premature eof on tar file ?\n"));
1378 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
1380 free(inbuf); free(outbuf);
1384 * samba interactive commands
1387 /****************************************************************************
1388 Blocksize command
1389 ***************************************************************************/
1390 void cmd_block(void)
1392 fstring buf;
1393 int block;
1395 if (!next_token(NULL,buf,NULL))
1397 DEBUG(0, ("blocksize <n>\n"));
1398 return;
1401 block=atoi(buf);
1402 if (block < 0 || block > 65535)
1404 DEBUG(0, ("blocksize out of range"));
1405 return;
1408 blocksize=block;
1409 DEBUG(2,("blocksize is now %d\n", blocksize));
1412 /****************************************************************************
1413 command to set incremental / reset mode
1414 ***************************************************************************/
1415 void cmd_tarmode(void)
1417 fstring buf;
1419 while (next_token(NULL,buf,NULL)) {
1420 if (strequal(buf, "full"))
1421 tar_inc=False;
1422 else if (strequal(buf, "inc"))
1423 tar_inc=True;
1424 else if (strequal(buf, "reset"))
1425 tar_reset=True;
1426 else if (strequal(buf, "noreset"))
1427 tar_reset=False;
1428 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
1431 DEBUG(0, ("tarmode is now %s, %s\n",
1432 tar_inc ? "incremental" : "full",
1433 tar_reset ? "reset" : "noreset"));
1436 /****************************************************************************
1437 Feeble attrib command
1438 ***************************************************************************/
1439 void cmd_setmode(void)
1441 char *q;
1442 fstring buf;
1443 pstring fname;
1444 int attra[2];
1445 int direct=1;
1447 attra[0] = attra[1] = 0;
1449 if (!next_token(NULL,buf,NULL))
1451 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1452 return;
1455 strcpy(fname, cur_dir);
1456 strcat(fname, buf);
1458 while (next_token(NULL,buf,NULL)) {
1459 q=buf;
1461 while(*q)
1462 switch (*q++) {
1463 case '+': direct=1;
1464 break;
1465 case '-': direct=0;
1466 break;
1467 case 'r': attra[direct]|=aRONLY;
1468 break;
1469 case 'h': attra[direct]|=aHIDDEN;
1470 break;
1471 case 's': attra[direct]|=aSYSTEM;
1472 break;
1473 case 'a': attra[direct]|=aARCH;
1474 break;
1475 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1476 return;
1480 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
1482 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1483 return;
1486 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
1487 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
1488 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
1491 /****************************************************************************
1492 Principal command for creating / extracting
1493 ***************************************************************************/
1494 void cmd_tar(char *inbuf, char *outbuf)
1496 fstring buf;
1497 char **argl;
1498 int argcl;
1500 if (!next_token(NULL,buf,NULL))
1502 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
1503 return;
1506 argl=toktocliplist(&argcl, NULL);
1507 if (!tar_parseargs(argcl, argl, buf, 0))
1508 return;
1510 process_tar(inbuf, outbuf);
1512 free(argl);
1515 /****************************************************************************
1516 Command line (option) version
1517 ***************************************************************************/
1518 int process_tar(char *inbuf, char *outbuf)
1520 initarbuf();
1521 switch(tar_type) {
1522 case 'x':
1523 do_tarput();
1524 free(tarbuf);
1525 close(tarhandle);
1526 break;
1527 case 'r':
1528 case 'c':
1529 if (clipn && tar_excl) {
1530 int i;
1531 pstring tarmac;
1533 for (i=0; i<clipn; i++) {
1534 DEBUG(0,("arg %d = %s\n", i, cliplist[i]));
1536 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
1537 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
1540 if (strrchr(cliplist[i], '\\')) {
1541 pstring saved_dir;
1543 strcpy(saved_dir, cur_dir);
1545 if (*cliplist[i]=='\\') {
1546 strcpy(tarmac, cliplist[i]);
1547 } else {
1548 strcpy(tarmac, cur_dir);
1549 strcat(tarmac, cliplist[i]);
1551 strcpy(cur_dir, tarmac);
1552 *(strrchr(cur_dir, '\\')+1)='\0';
1554 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse);
1555 strcpy(cur_dir,saved_dir);
1556 } else {
1557 strcpy(tarmac, cur_dir);
1558 strcat(tarmac, cliplist[i]);
1559 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse);
1562 } else {
1563 pstring mask;
1564 strcpy(mask,cur_dir);
1565 strcat(mask,"\\*");
1566 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse);
1569 if (ntarf) dotareof(tarhandle);
1570 close(tarhandle);
1571 free(tarbuf);
1573 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
1574 break;
1577 return(0);
1580 /****************************************************************************
1581 Find a token (filename) in a clip list
1582 ***************************************************************************/
1583 int clipfind(char **aret, int ret, char *tok)
1585 if (aret==NULL) return 0;
1587 /* ignore leading slashes or dots in token */
1588 while(strchr("/\\.", *tok)) tok++;
1590 while(ret--) {
1591 char *pkey=*aret++;
1593 /* ignore leading slashes or dots in list */
1594 while(strchr("/\\.", *pkey)) pkey++;
1596 if (!strslashcmp(pkey, tok)) return 1;
1599 return 0;
1602 /****************************************************************************
1603 Parse tar arguments. Sets tar_type, tar_excl, etc.
1604 ***************************************************************************/
1605 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
1607 char tar_clipfl='\0';
1609 /* Reset back to defaults - could be from interactive version
1610 * reset mode and archive mode left as they are though
1612 tar_type='\0';
1613 tar_excl=True;
1615 while (*Optarg)
1616 switch(*Optarg++) {
1617 case 'c':
1618 tar_type='c';
1619 break;
1620 case 'x':
1621 if (tar_type=='c') {
1622 printf("Tar must be followed by only one of c or x.\n");
1623 return 0;
1625 tar_type='x';
1626 break;
1627 case 'b':
1628 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
1629 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1630 return 0;
1631 } else {
1632 Optind++;
1634 break;
1635 case 'g':
1636 tar_inc=True;
1637 break;
1638 case 'N':
1639 if (Optind>=argc) {
1640 DEBUG(0,("Option N must be followed by valid file name\n"));
1641 return 0;
1642 } else {
1643 struct stat stbuf;
1644 extern time_t newer_than;
1646 if (sys_stat(argv[Optind], &stbuf) == 0) {
1647 newer_than = stbuf.st_mtime;
1648 DEBUG(1,("Getting files newer than %s",
1649 asctime(LocalTime(&newer_than))));
1650 Optind++;
1651 } else {
1652 DEBUG(0,("Error setting newer-than time\n"));
1653 return 0;
1656 break;
1657 case 'a':
1658 tar_reset=True;
1659 break;
1660 case 'I':
1661 if (tar_clipfl) {
1662 DEBUG(0,("Only one of I,X must be specified\n"));
1663 return 0;
1665 tar_clipfl='I';
1666 break;
1667 case 'X':
1668 if (tar_clipfl) {
1669 DEBUG(0,("Only one of I,X must be specified\n"));
1670 return 0;
1672 tar_clipfl='X';
1673 break;
1674 default:
1675 DEBUG(0,("Unknown tar option\n"));
1676 return 0;
1679 if (!tar_type) {
1680 printf("Option T must be followed by one of c or x.\n");
1681 return 0;
1684 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
1685 /* Sets tar handle to either 0 or 1, as appropriate */
1686 tarhandle=(tar_type=='c');
1687 } else {
1688 tar_excl=tar_clipfl!='X';
1690 if (Optind+1<argc) {
1691 cliplist=argv+Optind+1;
1692 clipn=argc-Optind-1;
1695 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
1696 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
1698 DEBUG(0,("Error opening local file %s\n",argv[Optind]));
1699 return(0);
1703 return 1;