this is the bug change to using connection_struct* instead of cnum.
[Samba/gbeck.git] / source / client / clitar.c
blob035e4f7607c22b5695f88e0f61fa1e942dc6753b
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Tar Extensions
5 Copyright (C) Ricky Poulten 1995-1998
6 Copyright (C) Richard Sharpe 1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* The following changes developed by Richard Sharpe for Canon Information
23 Systems Research Australia (CISRA)
25 1. Restore can now restore files with long file names
26 2. Save now saves directory information so that we can restore
27 directory creation times
28 3. tar now accepts both UNIX path names and DOS path names. I prefer
29 those lovely /'s to those UGLY \'s :-)
30 4. the files to exclude can be specified as a regular expression by adding
31 an r flag to the other tar flags. Eg:
33 -TcrX file.tar "*.(obj|exe)"
35 will skip all .obj and .exe files
39 #include "includes.h"
40 #include "clitar.h"
42 typedef struct file_info_struct file_info2;
44 struct file_info_struct
46 int size;
47 int mode;
48 int uid;
49 int gid;
50 /* These times are normally kept in GMT */
51 time_t mtime;
52 time_t atime;
53 time_t ctime;
54 char *name; /* This is dynamically allocate */
56 file_info2 *next, *prev; /* Used in the stack ... */
60 typedef struct
62 file_info2 *top;
63 int items;
65 } stack;
67 stack dir_stack = {NULL, 0}; /* Want an empty stack */
69 extern BOOL recurse;
71 #define SEPARATORS " \t\n\r"
72 extern int DEBUGLEVEL;
73 extern int Client;
75 /* These defines are for the do_setrattr routine, to indicate
76 * setting and reseting of file attributes in the function call */
77 #define ATTRSET 1
78 #define ATTRRESET 0
80 static int attribute = aDIR | aSYSTEM | aHIDDEN;
82 #ifndef CLIENT_TIMEOUT
83 #define CLIENT_TIMEOUT (30*1000)
84 #endif
86 static char *tarbuf;
87 static int tp, ntarf, tbufsiz, ttarf;
88 /* Incremental mode */
89 BOOL tar_inc=False;
90 /* Reset archive bit */
91 BOOL tar_reset=False;
92 /* Include / exclude mode (true=include, false=exclude) */
93 BOOL tar_excl=True;
94 /* use regular expressions for search on file names */
95 BOOL tar_re_search=False;
96 #ifdef HAVE_REGEX_H
97 regex_t *preg;
98 #endif
99 /* Dump files with System attribute */
100 BOOL tar_system=True;
101 /* Dump files with Hidden attribute */
102 BOOL tar_hidden=True;
103 /* Be noisy - make a catalogue */
104 BOOL tar_noisy=True;
105 BOOL tar_real_noisy=True;
107 char tar_type='\0';
108 static char **cliplist=NULL;
109 static int clipn=0;
110 static BOOL must_free_cliplist = False;
112 extern file_info def_finfo;
113 extern BOOL lowercase;
114 extern int cnum;
115 extern BOOL readbraw_supported;
116 extern int max_xmit;
117 extern pstring cur_dir;
118 extern int get_total_time_ms;
119 extern int get_total_size;
120 extern int Protocol;
122 int blocksize=20;
123 int tarhandle;
125 static void writetarheader(int f, char *aname, int size, time_t mtime,
126 char *amode, unsigned char ftype);
127 static void do_atar(char *rname,char *lname,file_info *finfo1);
128 static void do_tar(file_info *finfo);
129 static void oct_it(long value, int ndgs, char *p);
130 static void fixtarname(char *tptr, char *fp, int l);
131 static int dotarbuf(int f, char *b, int n);
132 static void dozerobuf(int f, int n);
133 static void dotareof(int f);
134 static void initarbuf(void);
135 static int do_setrattr(char *fname, int attr, int setit);
137 /* restore functions */
138 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix);
139 static long unoct(char *p, int ndgs);
140 static void do_tarput(void);
141 static void unfixtarname(char *tptr, char *fp, int l, BOOL first);
144 * tar specific utitlities
147 #if 0 /* Removed to get around gcc 'defined but not used' error. */
150 * Stack routines, push_dir, pop_dir, top_dir_name
153 static BOOL push_dir(stack *tar_dir_stack, file_info2 *dir)
155 dir -> next = tar_dir_stack -> top;
156 dir -> prev = NULL;
157 tar_dir_stack -> items++;
158 tar_dir_stack -> top = dir;
159 return(True);
163 static file_info2 *pop_dir(stack *tar_dir_stack)
165 file_info2 *ptr;
167 ptr = tar_dir_stack -> top;
168 if (tar_dir_stack -> top != NULL) {
170 tar_dir_stack -> top = tar_dir_stack -> top -> next;
171 tar_dir_stack -> items--;
175 return ptr;
179 static char *top_dir_name(stack *tar_dir_stack)
182 return(tar_dir_stack -> top != NULL?tar_dir_stack -> top -> name:NULL);
186 static BOOL sub_dir(char *dir1, char *dir2)
189 return(True);
193 #endif /* Removed to get around gcc 'defined but not used' error. */
195 /*******************************************************************
196 Create a string of size size+1 (for the null)
197 *******************************************************************/
198 static char *string_create_s(int size)
200 char *tmp;
202 tmp = (char *)malloc(size+1);
204 if (tmp == NULL) {
206 DEBUG(0, ("Out of memory in string_create_s\n"));
210 return(tmp);
214 /****************************************************************************
215 Write a tar header to buffer
216 ****************************************************************************/
217 static void writetarheader(int f, char *aname, int size, time_t mtime,
218 char *amode, unsigned char ftype)
220 union hblock hb;
221 int i, chk, l;
222 char *jp;
224 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
226 memset(hb.dummy, 0, sizeof(hb.dummy));
228 l=strlen(aname);
229 if (l >= NAMSIZ) {
230 /* write a GNU tar style long header */
231 char *b;
232 b = (char *)malloc(l+TBLOCK+100);
233 if (!b) {
234 DEBUG(0,("out of memory\n"));
235 exit(1);
237 writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L');
238 memset(b, 0, l+TBLOCK+100);
239 fixtarname(b, aname, l);
240 i = strlen(b)+1;
241 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
242 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
243 free(b);
246 /* use l + 1 to do the null too */
247 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
249 if (lowercase)
250 strlower(hb.dbuf.name);
252 /* write out a "standard" tar format header */
254 hb.dbuf.name[NAMSIZ-1]='\0';
255 safe_strcpy(hb.dbuf.mode, amode, strlen(amode));
256 oct_it(0L, 8, hb.dbuf.uid);
257 oct_it(0L, 8, hb.dbuf.gid);
258 oct_it((long) size, 13, hb.dbuf.size);
259 oct_it((long) mtime, 13, hb.dbuf.mtime);
260 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
261 memset(hb.dbuf.linkname, 0, NAMSIZ);
262 hb.dbuf.linkflag=ftype;
264 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
266 oct_it((long) chk, 8, hb.dbuf.chksum);
267 hb.dbuf.chksum[6] = '\0';
269 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
272 /****************************************************************************
273 Read a tar header into a hblock structure, and validate
274 ***************************************************************************/
275 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
277 long chk, fchk;
278 int i;
279 char *jp;
282 * read in a "standard" tar format header - we're not that interested
283 * in that many fields, though
286 /* check the checksum */
287 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
289 if (chk == 0)
290 return chk;
292 /* compensate for blanks in chksum header */
293 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
294 chk-=(0xFF & *jp++);
296 chk += ' ' * sizeof(hb->dbuf.chksum);
298 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
300 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
301 chk, fchk, hb->dbuf.chksum));
303 if (fchk != chk)
305 DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk));
306 /* for (i = 0; i < sizeof(hb -> dummy); i++) {
307 fprintf(stdout, "%2X ", hb -> dummy[i]);
309 fprintf(stdout, "\n");
310 fprintf(stdout, "%s\n", hb -> dummy);
311 fprintf(stdout, "Tarbuf = %X, hb = %X\n", (int)tarbuf, (int)hb);*/
312 return -1;
315 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
317 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
318 return(-1);
322 safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3);
324 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
325 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
326 strlen(hb->dbuf.name) + 1, True);
328 /* can't handle some links at present */
329 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
330 if (hb->dbuf.linkflag == 0) {
331 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
332 finfo->name));
333 } else {
334 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
335 /* Do nothing here at the moment. do_tarput will handle this
336 as long as the longlink gets back to it, as it has to advance
337 the buffer pointer, etc */
339 } else {
340 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
341 return -2;
346 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
347 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
349 finfo->mode=aDIR;
351 else
352 finfo->mode=0; /* we don't care about mode at the moment, we'll
353 * just make it a regular file */
355 * Bug fix by richard@sj.co.uk
357 * REC: restore times correctly (as does tar)
358 * We only get the modification time of the file; set the creation time
359 * from the mod. time, and the access time to current time
361 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
362 finfo->atime = time(NULL);
363 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
365 return True;
368 /****************************************************************************
369 Write out the tar buffer to tape or wherever
370 ****************************************************************************/
371 static int dotarbuf(int f, char *b, int n)
373 int fail=1, writ=n;
375 /* This routine and the next one should be the only ones that do write()s */
376 if (tp + n >= tbufsiz)
378 int diff;
380 diff=tbufsiz-tp;
381 memcpy(tarbuf + tp, b, diff);
382 fail=fail && (1+write(f, tarbuf, tbufsiz));
383 n-=diff;
384 b+=diff;
385 tp=0;
387 while (n >= tbufsiz)
389 fail=fail && (1 + write(f, b, tbufsiz));
390 n-=tbufsiz;
391 b+=tbufsiz;
394 if (n>0) {
395 memcpy(tarbuf+tp, b, n);
396 tp+=n;
399 return(fail ? writ : 0);
402 /****************************************************************************
403 Write zeros to buffer / tape
404 ****************************************************************************/
405 static void dozerobuf(int f, int n)
407 /* short routine just to write out n zeros to buffer -
408 * used to round files to nearest block
409 * and to do tar EOFs */
411 if (n+tp >= tbufsiz)
413 memset(tarbuf+tp, 0, tbufsiz-tp);
415 write(f, tarbuf, tbufsiz);
416 memset(tarbuf, 0, (tp+=n-tbufsiz));
418 else
420 memset(tarbuf+tp, 0, n);
421 tp+=n;
425 /****************************************************************************
426 Malloc tape buffer
427 ****************************************************************************/
428 static void initarbuf()
430 /* initialize tar buffer */
431 tbufsiz=blocksize*TBLOCK;
432 tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */
434 /* reset tar buffer pointer and tar file counter and total dumped */
435 tp=0; ntarf=0; ttarf=0;
438 /****************************************************************************
439 Write two zero blocks at end of file
440 ****************************************************************************/
441 static void dotareof(int f)
443 struct stat stbuf;
444 /* Two zero blocks at end of file, write out full buffer */
446 (void) dozerobuf(f, TBLOCK);
447 (void) dozerobuf(f, TBLOCK);
449 if (fstat(f, &stbuf) == -1)
451 DEBUG(0, ("Couldn't stat file handle\n"));
452 return;
455 /* Could be a pipe, in which case S_ISREG should fail,
456 * and we should write out at full size */
457 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
460 /****************************************************************************
461 (Un)mangle DOS pathname, make nonabsolute
462 ****************************************************************************/
463 static void fixtarname(char *tptr, char *fp, int l)
465 /* add a '.' to start of file name, convert from ugly dos \'s in path
466 * to lovely unix /'s :-} */
468 *tptr++='.';
470 while (l > 0) {
471 int skip;
472 if((skip = skip_multibyte_char( *fp)) != 0) {
473 if (skip == 2) {
474 *tptr++ = *fp++;
475 *tptr++ = *fp++;
476 l -= 2;
477 } else if (skip == 1) {
478 *tptr++ = *fp++;
479 l--;
481 } else if (*fp == '\\') {
482 *tptr++ = '/';
483 fp++;
484 l--;
485 } else {
486 *tptr++ = *fp++;
487 l--;
492 /****************************************************************************
493 Convert from decimal to octal string
494 ****************************************************************************/
495 static void oct_it (long value, int ndgs, char *p)
497 /* Converts long to octal string, pads with leading zeros */
499 /* skip final null, but do final space */
500 --ndgs;
501 p[--ndgs] = ' ';
503 /* Loop does at least one digit */
504 do {
505 p[--ndgs] = '0' + (char) (value & 7);
506 value >>= 3;
508 while (ndgs > 0 && value != 0);
510 /* Do leading zeros */
511 while (ndgs > 0)
512 p[--ndgs] = '0';
515 /****************************************************************************
516 Convert from octal string to long
517 ***************************************************************************/
518 static long unoct(char *p, int ndgs)
520 long value=0;
521 /* Converts octal string to long, ignoring any non-digit */
523 while (--ndgs)
525 if (isdigit(*p))
526 value = (value << 3) | (long) (*p - '0');
528 p++;
531 return value;
534 /****************************************************************************
535 Compare two strings in a slash insensitive way, allowing s1 to match s2
536 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
537 a file in any subdirectory of s1, declare a match.
538 ***************************************************************************/
539 static int strslashcmp(char *s1, char *s2)
541 char *s1_0=s1;
543 while(*s1 && *s2 &&
544 (*s1 == *s2
545 || tolower(*s1) == tolower(*s2)
546 || (*s1 == '\\' && *s2=='/')
547 || (*s1 == '/' && *s2=='\\'))) {
548 s1++; s2++;
551 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
552 string of s2.
554 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
556 /* ignore trailing slash on s1 */
557 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
559 /* check for s1 is an "initial" string of s2 */
560 if (*s2 == '/' || *s2 == '\\') return 0;
562 return *s1-*s2;
566 * general smb utility functions
568 /**********************************************************************
569 do_setrtime, set time on a file or dir ...
570 **********************************************************************/
572 static int do_setrtime(char *fname, int mtime, BOOL err_silent)
574 char *inbuf, *outbuf, *p;
575 char *name;
577 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
579 name = (char *)malloc(strlen(fname) + 1 + 1);
580 if (name == NULL) {
582 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
583 return False;
587 if (*fname != '\\')
588 safe_strcpy(name, "\\", strlen(fname) + 1);
589 else
590 safe_strcpy(name, "", strlen(fname) + 1);
591 safe_strcat(name, fname, strlen(fname) + 1);
593 if (fname[strlen(name) - 1] == '\\')
594 name[strlen(name) - 1] = '\0';
596 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
597 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
599 if (!inbuf || !outbuf) {
601 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
602 free(name);
603 return False;
607 memset(outbuf, 0, smb_size);
608 set_message(outbuf, 8, 4 + strlen(name), True);
609 CVAL(outbuf, smb_com) = SMBsetatr;
610 SSVAL(outbuf, smb_tid, cnum);
611 cli_setup_pkt(outbuf);
613 SSVAL(outbuf, smb_vwv0, 0);
614 put_dos_date3(outbuf, smb_vwv1, mtime);
616 p = smb_buf(outbuf);
617 *p++ = 4;
618 safe_strcpy(p, name, strlen(name));
619 p+= (strlen(fname)+1);
621 *p++ = 4;
622 *p++ = 0;
624 send_smb(Client, outbuf);
625 client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
627 if (CVAL(inbuf,smb_rcls) != 0)
629 if (!err_silent) {
630 DEBUG(0,("%s setting attributes on file %s\n",
631 smb_errstr(inbuf), fname));
633 free(name);free(inbuf);free(outbuf);
634 return(False);
637 free(name);
638 free(inbuf);free(outbuf);
639 return(True);
643 /****************************************************************************
644 Set DOS file attributes
645 ***************************************************************************/
646 static int do_setrattr(char *fname, int attr, int setit)
649 * First get the existing attribs from existing file
651 char *inbuf,*outbuf;
652 char *p;
653 char *name;
654 int fattr;
656 name = (char *)malloc(strlen(fname) + 1 + 1);
657 if (name == NULL) {
659 DEBUG(0, ("Failed to allocate space in do_setrattr while setting time on file: %s", fname));
660 return False;
664 safe_strcpy(name, "\\", strlen(fname) + 1);
665 safe_strcat(name, fname, strlen(fname) + 1);
667 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
668 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
670 if (!inbuf || !outbuf)
672 DEBUG(0,("out of memory\n"));
673 free(name);
674 return False;
677 /* send an smb getatr message */
679 memset(outbuf,0,smb_size);
680 set_message(outbuf,0,2 + strlen(fname),True);
681 CVAL(outbuf,smb_com) = SMBgetatr;
682 SSVAL(outbuf,smb_tid,cnum);
683 cli_setup_pkt(outbuf);
685 p = smb_buf(outbuf);
686 *p++ = 4;
687 safe_strcpy(p,name, strlen(name));
688 p += (strlen(name)+1);
690 *p++ = 4;
691 *p++ = 0;
693 send_smb(Client,outbuf);
694 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
696 if (CVAL(inbuf,smb_rcls) != 0)
697 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
698 else
700 DEBUG(5,("\nattr 0x%X time %d size %d\n",
701 (int)CVAL(inbuf,smb_vwv0),
702 SVAL(inbuf,smb_vwv1),
703 SVAL(inbuf,smb_vwv3)));
706 fattr=CVAL(inbuf,smb_vwv0);
708 /* combine found attributes with bits to be set or reset */
710 attr=setit ? (fattr | attr) : (fattr & ~attr);
712 /* now try and set attributes by sending smb reset message */
714 /* clear out buffer and start again */
715 memset(outbuf,0,smb_size);
716 set_message(outbuf,8,4 + strlen(name),True);
717 CVAL(outbuf,smb_com) = SMBsetatr;
718 SSVAL(outbuf,smb_tid,cnum);
719 cli_setup_pkt(outbuf);
721 SSVAL(outbuf,smb_vwv0,attr);
723 p = smb_buf(outbuf);
724 *p++ = 4;
725 safe_strcpy(p,name, strlen(name));
726 p += (strlen(name)+1);
728 *p++ = 4;
729 *p++ = 0;
731 send_smb(Client,outbuf);
732 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
734 if (CVAL(inbuf,smb_rcls) != 0)
736 DEBUG(0,("%s setting attributes on file %s\n",
737 smb_errstr(inbuf), name));
738 free(name);free(inbuf);free(outbuf);
739 return(False);
742 free(name);
743 free(inbuf);free(outbuf);
744 return(True);
747 /****************************************************************************
748 Create a file on a share
749 ***************************************************************************/
750 static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
752 char *p;
753 /* *must* be called with buffer ready malloc'ed */
754 /* open remote file */
756 memset(outbuf,0,smb_size);
757 set_message(outbuf,3,2 + strlen(finfo.name),True);
758 CVAL(outbuf,smb_com) = SMBcreate;
759 SSVAL(outbuf,smb_tid,cnum);
760 cli_setup_pkt(outbuf);
762 SSVAL(outbuf,smb_vwv0,finfo.mode);
763 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
765 p = smb_buf(outbuf);
766 *p++ = 4;
767 safe_strcpy(p,finfo.name, strlen(finfo.name));
769 send_smb(Client,outbuf);
770 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
772 if (CVAL(inbuf,smb_rcls) != 0)
774 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
775 finfo.name));
776 return 0;
779 *fnum = SVAL(inbuf,smb_vwv0);
780 return True;
783 /****************************************************************************
784 Write a file to a share
785 ***************************************************************************/
786 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
787 char *bufferp, char *inbuf, char *outbuf)
789 /* *must* be called with buffer ready malloc'ed */
791 memset(outbuf,0,smb_size);
792 set_message(outbuf,5,n + 3,True);
794 memcpy(smb_buf(outbuf)+3, bufferp, n);
796 set_message(outbuf,5,n + 3, False);
797 CVAL(outbuf,smb_com) = SMBwrite;
798 SSVAL(outbuf,smb_tid,cnum);
799 cli_setup_pkt(outbuf);
801 SSVAL(outbuf,smb_vwv0,fnum);
802 SSVAL(outbuf,smb_vwv1,n);
803 SIVAL(outbuf,smb_vwv2,low);
804 SSVAL(outbuf,smb_vwv4,left);
805 CVAL(smb_buf(outbuf),0) = 1;
806 SSVAL(smb_buf(outbuf),1,n);
808 send_smb(Client,outbuf);
809 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
811 if (CVAL(inbuf,smb_rcls) != 0)
813 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
814 return False;
817 if (n != SVAL(inbuf,smb_vwv0))
819 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
820 SVAL(inbuf,smb_vwv0), n));
821 return False;
824 return True;
827 /****************************************************************************
828 Close a file on a share
829 ***************************************************************************/
830 static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
832 /* *must* be called with buffer ready malloc'ed */
834 memset(outbuf,0,smb_size);
835 set_message(outbuf,3,0,True);
836 CVAL(outbuf,smb_com) = SMBclose;
837 SSVAL(outbuf,smb_tid,cnum);
838 cli_setup_pkt(outbuf);
840 SSVAL(outbuf,smb_vwv0,fnum);
841 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
843 DEBUG(3,("Setting date to %s (0x%lX)",
844 asctime(LocalTime(&finfo.mtime)),
845 finfo.mtime));
847 send_smb(Client,outbuf);
848 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
850 if (CVAL(inbuf,smb_rcls) != 0)
852 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
853 finfo.name));
854 return False;
857 return True;
860 /****************************************************************************
861 Verify existence of path on share
862 ***************************************************************************/
863 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
865 char *p;
867 memset(outbuf,0,smb_size);
868 set_message(outbuf,0,4 + strlen(fname),True);
869 CVAL(outbuf,smb_com) = SMBchkpth;
870 SSVAL(outbuf,smb_tid,cnum);
871 cli_setup_pkt(outbuf);
873 p = smb_buf(outbuf);
874 *p++ = 4;
875 safe_strcpy(p,fname, strlen(fname));
877 send_smb(Client,outbuf);
878 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
880 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
882 return(CVAL(inbuf,smb_rcls) == 0);
885 /****************************************************************************
886 Make a directory on share
887 ***************************************************************************/
888 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
890 /* *must* be called with buffer ready malloc'ed */
891 char *p;
893 memset(outbuf,0,smb_size);
894 set_message(outbuf,0,2 + strlen(fname),True);
896 CVAL(outbuf,smb_com) = SMBmkdir;
897 SSVAL(outbuf,smb_tid,cnum);
898 cli_setup_pkt(outbuf);
900 p = smb_buf(outbuf);
901 *p++ = 4;
902 safe_strcpy(p,fname, strlen(fname));
904 send_smb(Client,outbuf);
905 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
907 if (CVAL(inbuf,smb_rcls) != 0)
909 DEBUG(0,("%s making remote directory %s\n",
910 smb_errstr(inbuf),fname));
911 return(False);
914 return(True);
917 /****************************************************************************
918 Ensure a remote path exists (make if necessary)
919 ***************************************************************************/
920 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
922 /* *must* be called with buffer ready malloc'ed */
923 /* ensures path exists */
925 char *partpath, *ffname;
926 char *p=fname, *basehack;
928 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
930 partpath = string_create_s(strlen(fname));
931 ffname = string_create_s(strlen(fname));
933 if ((partpath == NULL) || (ffname == NULL)){
935 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
936 return(False);
940 *partpath = 0;
942 /* fname copied to ffname so can strtok */
944 safe_strcpy(ffname, fname, strlen(fname));
946 /* do a `basename' on ffname, so don't try and make file name directory */
947 if ((basehack=strrchr(ffname, '\\')) == NULL)
948 return True;
949 else
950 *basehack='\0';
952 p=strtok(ffname, "\\");
954 while (p)
956 safe_strcat(partpath, p, strlen(fname) + 1);
958 if (!smbchkpath(partpath, inbuf, outbuf)) {
959 if (!smbmkdir(partpath, inbuf, outbuf))
961 DEBUG(0, ("Error mkdirhiering\n"));
962 return False;
964 else
965 DEBUG(3, ("mkdirhiering %s\n", partpath));
969 safe_strcat(partpath, "\\", strlen(fname) + 1);
970 p = strtok(NULL,"/\\");
973 return True;
976 int padit(char *buf, int bufsize, int padsize)
978 int berr= 0;
979 int bytestowrite;
981 DEBUG(5, ("Padding with %d zeros\n", padsize));
982 memset(buf, 0, bufsize);
983 while( !berr && padsize > 0 ) {
984 bytestowrite= MIN(bufsize, padsize);
985 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
986 padsize -= bytestowrite;
989 return berr;
993 * smbclient functions
995 /****************************************************************************
996 append one remote file to the tar file
997 ***************************************************************************/
998 static void do_atar(char *rname,char *lname,file_info *finfo1)
1000 int fnum;
1001 uint32 nread=0;
1002 char *p, ftype;
1003 char *inbuf,*outbuf;
1004 file_info2 finfo;
1005 BOOL close_done = False;
1006 BOOL shallitime=True;
1007 BOOL ignore_close_error = False;
1008 char *dataptr=NULL;
1009 int datalen=0;
1011 struct timeval tp_start;
1012 GetTimeOfDay(&tp_start);
1014 ftype = '0'; /* An ordinary file ... */
1016 if (finfo1) {
1017 finfo.size = finfo1 -> size;
1018 finfo.mode = finfo1 -> mode;
1019 finfo.uid = finfo1 -> uid;
1020 finfo.gid = finfo1 -> gid;
1021 finfo.mtime = finfo1 -> mtime;
1022 finfo.atime = finfo1 -> atime;
1023 finfo.ctime = finfo1 -> ctime;
1025 else {
1026 finfo.size = def_finfo.size;
1027 finfo.mode = def_finfo.mode;
1028 finfo.uid = def_finfo.uid;
1029 finfo.gid = def_finfo.gid;
1030 finfo.mtime = def_finfo.mtime;
1031 finfo.atime = def_finfo.atime;
1032 finfo.ctime = def_finfo.ctime;
1036 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1037 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1039 if (!inbuf || !outbuf)
1041 DEBUG(0,("out of memory\n"));
1042 return;
1045 memset(outbuf,0,smb_size);
1046 set_message(outbuf,15,1 + strlen(rname),True);
1048 CVAL(outbuf,smb_com) = SMBopenX;
1049 SSVAL(outbuf,smb_tid,cnum);
1050 cli_setup_pkt(outbuf);
1052 SSVAL(outbuf,smb_vwv0,0xFF);
1053 SSVAL(outbuf,smb_vwv2,1);
1054 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1055 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1056 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1057 SSVAL(outbuf,smb_vwv8,1);
1059 p = smb_buf(outbuf);
1060 safe_strcpy(p, rname, strlen(rname));
1061 p = skip_string(p,1);
1063 dos_clean_name(rname);
1065 /* do a chained openX with a readX? */
1066 if (finfo.size > 0)
1068 SSVAL(outbuf,smb_vwv0,SMBreadX);
1069 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
1070 memset(p,0,200);
1071 p -= smb_wct;
1072 SSVAL(p,smb_wct,10);
1073 SSVAL(p,smb_vwv0,0xFF);
1074 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1075 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
1076 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1079 send_smb(Client,outbuf);
1080 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1082 if (CVAL(inbuf,smb_rcls) != 0)
1084 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1085 SVAL(inbuf,smb_err) == ERRnoresource &&
1086 cli_reopen_connection(inbuf,outbuf))
1088 do_atar(rname,lname,finfo1);
1089 free(inbuf);free(outbuf);
1090 return;
1093 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
1094 free(inbuf);free(outbuf);
1095 return;
1098 finfo.name = string_create_s(strlen(rname));
1099 if (finfo.name == NULL) {
1101 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
1102 free(inbuf); free(outbuf);
1103 return;
1107 safe_strcpy(finfo.name,rname, strlen(rname));
1108 if (!finfo1)
1110 finfo.mode = SVAL(inbuf,smb_vwv3);
1111 finfo.size = IVAL(inbuf,smb_vwv4);
1112 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
1113 finfo.atime = finfo.ctime = finfo.mtime;
1116 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
1118 fnum = SVAL(inbuf,smb_vwv2);
1120 if (tar_inc && !(finfo.mode & aARCH))
1122 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
1123 shallitime=0;
1125 else if (!tar_system && (finfo.mode & aSYSTEM))
1127 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
1128 shallitime=0;
1130 else if (!tar_hidden && (finfo.mode & aHIDDEN))
1132 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
1133 shallitime=0;
1135 else
1137 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1139 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
1140 datalen = SVAL(p,smb_vwv5);
1141 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
1143 else
1145 dataptr = NULL;
1146 datalen = 0;
1149 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1150 finfo.name,
1151 finfo.size,
1152 lname));
1154 /* write a tar header, don't bother with mode - just set to 100644 */
1155 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
1157 while (nread < finfo.size && !close_done)
1159 int method = -1;
1160 static BOOL can_chain_close=True;
1162 p=NULL;
1164 DEBUG(3,("nread=%d\n",nread));
1166 /* 3 possible read types. readbraw if a large block is required.
1167 readX + close if not much left and read if neither is supported */
1169 /* we might have already read some data from a chained readX */
1170 if (dataptr && datalen>0)
1171 method=3;
1173 /* if we can finish now then readX+close */
1174 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1175 ((finfo.size - nread) <
1176 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1177 method = 0;
1179 /* if we support readraw then use that */
1180 if (method<0 && readbraw_supported)
1181 method = 1;
1183 /* if we can then use readX */
1184 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1185 method = 2;
1188 switch (method)
1190 /* use readX */
1191 case 0:
1192 case 2:
1193 if (method == 0)
1194 close_done = True;
1196 /* use readX + close */
1197 memset(outbuf,0,smb_size);
1198 set_message(outbuf,10,0,True);
1199 CVAL(outbuf,smb_com) = SMBreadX;
1200 SSVAL(outbuf,smb_tid,cnum);
1201 cli_setup_pkt(outbuf);
1203 if (close_done)
1205 CVAL(outbuf,smb_vwv0) = SMBclose;
1206 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
1208 else
1209 CVAL(outbuf,smb_vwv0) = 0xFF;
1212 SSVAL(outbuf,smb_vwv2,fnum);
1213 SIVAL(outbuf,smb_vwv3,nread);
1214 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1215 SSVAL(outbuf,smb_vwv6,0);
1216 SIVAL(outbuf,smb_vwv7,0);
1217 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
1219 if (close_done)
1221 p = smb_buf(outbuf);
1222 memset(p,0,9);
1224 CVAL(p,0) = 3;
1225 SSVAL(p,1,fnum);
1226 SIVALS(p,3,-1);
1228 /* now set the total packet length */
1229 smb_setlen(outbuf,smb_len(outbuf)+9);
1232 send_smb(Client,outbuf);
1233 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1235 if (CVAL(inbuf,smb_rcls) != 0)
1237 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1238 break;
1241 if (close_done &&
1242 SVAL(inbuf,smb_vwv0) != SMBclose)
1244 /* NOTE: WfWg sometimes just ignores the chained
1245 command! This seems to break the spec? */
1246 DEBUG(3,("Rejected chained close?\n"));
1247 close_done = False;
1248 can_chain_close = False;
1249 ignore_close_error = True;
1252 datalen = SVAL(inbuf,smb_vwv5);
1253 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
1254 break;
1257 /* use readbraw */
1258 case 1:
1260 static int readbraw_size = 0xFFFF;
1262 extern int Client;
1263 memset(outbuf,0,smb_size);
1264 set_message(outbuf,8,0,True);
1265 CVAL(outbuf,smb_com) = SMBreadbraw;
1266 SSVAL(outbuf,smb_tid,cnum);
1267 cli_setup_pkt(outbuf);
1268 SSVAL(outbuf,smb_vwv0,fnum);
1269 SIVAL(outbuf,smb_vwv1,nread);
1270 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1271 SSVAL(outbuf,smb_vwv4,0);
1272 SIVALS(outbuf,smb_vwv5,-1);
1273 send_smb(Client,outbuf);
1275 /* Now read the raw data into the buffer and write it */
1276 if(read_smb_length(Client,inbuf,0) == -1) {
1277 DEBUG(0,("Failed to read length in readbraw\n"));
1278 exit(1);
1281 /* Even though this is not an smb message, smb_len
1282 returns the generic length of an smb message */
1283 datalen = smb_len(inbuf);
1285 if (datalen == 0)
1287 /* we got a readbraw error */
1288 DEBUG(4,("readbraw error - reducing size\n"));
1289 readbraw_size = (readbraw_size * 9) / 10;
1291 if (readbraw_size < max_xmit)
1293 DEBUG(0,("disabling readbraw\n"));
1294 readbraw_supported = False;
1297 dataptr=NULL;
1298 continue;
1301 if(read_data(Client,inbuf,datalen) != datalen) {
1302 DEBUG(0,("Failed to read data in readbraw\n"));
1303 exit(1);
1305 dataptr = inbuf;
1307 break;
1309 case 3:
1310 /* we've already read some data with a chained readX */
1311 break;
1313 default:
1314 /* use plain read */
1315 memset(outbuf,0,smb_size);
1316 set_message(outbuf,5,0,True);
1317 CVAL(outbuf,smb_com) = SMBread;
1318 SSVAL(outbuf,smb_tid,cnum);
1319 cli_setup_pkt(outbuf);
1321 SSVAL(outbuf,smb_vwv0,fnum);
1322 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1323 SIVAL(outbuf,smb_vwv2,nread);
1324 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1326 send_smb(Client,outbuf);
1327 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1329 if (CVAL(inbuf,smb_rcls) != 0)
1331 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1332 break;
1335 datalen = SVAL(inbuf,smb_vwv0);
1336 dataptr = smb_buf(inbuf) + 3;
1337 break;
1341 /* add received bits of file to buffer - dotarbuf will
1342 * write out in 512 byte intervals */
1343 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1345 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
1346 break;
1349 nread += datalen;
1350 if (datalen == 0)
1352 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1353 break;
1356 dataptr=NULL;
1357 datalen=0;
1360 /* pad tar file with zero's if we couldn't get entire file */
1361 if (nread < finfo.size)
1363 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
1364 if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
1365 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
1368 /* round tar file to nearest block */
1369 if (finfo.size % TBLOCK)
1370 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1372 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1373 ntarf++;
1376 if (!close_done)
1378 memset(outbuf,0,smb_size);
1379 set_message(outbuf,3,0,True);
1380 CVAL(outbuf,smb_com) = SMBclose;
1381 SSVAL(outbuf,smb_tid,cnum);
1382 cli_setup_pkt(outbuf);
1384 SSVAL(outbuf,smb_vwv0,fnum);
1385 SIVALS(outbuf,smb_vwv1,-1);
1387 send_smb(Client,outbuf);
1388 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1390 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1392 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1393 free(inbuf);free(outbuf);
1394 return;
1398 if (shallitime)
1400 struct timeval tp_end;
1401 int this_time;
1403 /* if shallitime is true then we didn't skip */
1404 if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1406 GetTimeOfDay(&tp_end);
1407 this_time =
1408 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1409 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1410 get_total_time_ms += this_time;
1411 get_total_size += finfo.size;
1413 if (tar_noisy)
1415 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
1416 finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
1417 finfo.name));
1420 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1421 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1422 finfo.size / MAX(0.001, (1.024*this_time)),
1423 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1426 free(inbuf);free(outbuf);
1429 /****************************************************************************
1430 Append single file to tar file (or not)
1431 ***************************************************************************/
1432 static void do_tar(file_info *finfo)
1434 pstring rname;
1436 if (strequal(finfo->name,".."))
1437 return;
1439 /* Is it on the exclude list ? */
1440 if (!tar_excl && clipn) {
1441 pstring exclaim;
1443 DEBUG(5, ("Excl: strlen(cur_dir) = %i\n", strlen(cur_dir)));
1445 safe_strcpy(exclaim, cur_dir, sizeof(pstring));
1446 *(exclaim+strlen(exclaim)-1)='\0';
1448 safe_strcat(exclaim, "\\", sizeof(pstring));
1449 safe_strcat(exclaim, finfo->name, sizeof(exclaim));
1451 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
1453 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
1454 #ifdef HAVE_REGEX_H
1455 (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
1456 #else
1457 (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
1458 #endif
1459 DEBUG(3,("Skipping file %s\n", exclaim));
1460 return;
1464 if (finfo->mode & aDIR)
1466 pstring saved_curdir;
1467 pstring mtar_mask;
1468 char *inbuf,*outbuf;
1470 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1471 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1473 if (!inbuf || !outbuf)
1475 DEBUG(0,("out of memory\n"));
1476 return;
1479 safe_strcpy(saved_curdir, cur_dir, sizeof(saved_curdir));
1481 DEBUG(5, ("Sizeof(cur_dir)=%i, strlen(cur_dir)=%i, strlen(finfo->name)=%i\nname=%s,cur_dir=%s\n", sizeof(cur_dir), strlen(cur_dir), strlen(finfo->name), finfo->name, cur_dir));
1483 safe_strcat(cur_dir,finfo->name, sizeof(cur_dir));
1484 safe_strcat(cur_dir,"\\", sizeof(cur_dir));
1486 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
1488 /* write a tar directory, don't bother with mode - just set it to
1489 * 40755 */
1490 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
1491 if (tar_noisy) {
1493 DEBUG(0, (" directory %s\n", cur_dir));
1496 ntarf++; /* Make sure we have a file on there */
1497 safe_strcpy(mtar_mask,cur_dir, sizeof(pstring));
1498 safe_strcat(mtar_mask,"*", sizeof(pstring));
1499 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1500 safe_strcpy(cur_dir,saved_curdir, sizeof(pstring));
1501 free(inbuf);free(outbuf);
1503 else
1505 safe_strcpy(rname,cur_dir, sizeof(pstring));
1506 safe_strcat(rname,finfo->name, sizeof(pstring));
1507 do_atar(rname,finfo->name,finfo);
1511 /****************************************************************************
1512 Convert from UNIX to DOS file names
1513 ***************************************************************************/
1514 static void unfixtarname(char *tptr, char *fp, int l, BOOL first)
1516 /* remove '.' from start of file name, convert from unix /'s to
1517 * dos \'s in path. Kill any absolute path names. But only if first!
1520 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", tptr, fp, l));
1522 if (first) {
1523 if (*fp == '.') {
1524 fp++;
1525 l--;
1527 if (*fp == '\\' || *fp == '/') {
1528 fp++;
1529 l--;
1533 while (l > 0) {
1534 int skip;
1535 if(( skip = skip_multibyte_char( *fp )) != 0) {
1536 if (skip == 2) {
1537 *tptr++ = *fp++;
1538 *tptr++ = *fp++;
1539 l -= 2;
1540 } else if (skip == 1) {
1541 *tptr++ = *fp++;
1542 l--;
1544 } else if (*fp == '/') {
1545 *tptr++ = '\\';
1546 fp++;
1547 l--;
1548 } else {
1549 *tptr++ = *fp++;
1550 l--;
1555 #if 0 /* Removed to get around gcc 'defined but not used' error. */
1557 /****************************************************************************
1558 Move to the next block in the buffer, which may mean read in another set of
1559 blocks.
1560 ****************************************************************************/
1561 static int next_block(char *ltarbuf, char *bufferp, int bufsiz)
1563 int bufread, total = 0;
1565 if (bufferp >= (ltarbuf + bufsiz)) {
1567 for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
1569 if (bufread <= 0) { /* An error, return false */
1570 return (total > 0 ? -2 : bufread);
1575 bufferp = ltarbuf;
1578 else {
1580 bufferp += TBLOCK;
1584 return(0);
1588 static int skip_file(int skip)
1591 return(0);
1594 static int get_file(file_info2 finfo)
1597 return(0);
1601 static int get_dir(file_info2 finfo)
1604 return(0);
1608 static char * get_longfilename(file_info2 finfo)
1611 return(NULL);
1615 static char * bufferp;
1617 static void do_tarput2(void)
1619 file_info2 finfo, *finfo2;
1620 struct timeval tp_start;
1621 char *inbuf, *outbuf, *longfilename = NULL;
1622 int skip = False;
1624 GetTimeOfDay(&tp_start);
1626 bufferp = tarbuf + tbufsiz; /* init this to force first read */
1628 if (push_dir(&dir_stack, &finfo)) {
1630 finfo2 = pop_dir(&dir_stack);
1631 inbuf = top_dir_name(&dir_stack); /* FIXME */
1632 if (sub_dir(inbuf, finfo2 -> name)){
1634 DEBUG(0, (""));
1639 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1640 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1642 if (!inbuf || !outbuf) {
1644 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1645 return;
1649 if (next_block(tarbuf, bufferp, tbufsiz) <= 0) {
1651 DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno)));
1655 /* Now read through those files ... */
1657 while (True) {
1659 switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) {
1661 case -2: /* Hmm, not good, but not fatal */
1662 DEBUG(0, ("Skipping %s...\n", finfo.name));
1663 if ((next_block(tarbuf, bufferp, tbufsiz) <= 0) &&
1664 !skip_file(finfo.size)) {
1666 DEBUG(0, ("Short file, bailing out...\n"));
1667 free(inbuf); free(outbuf);
1668 continue;
1672 break;
1674 case -1:
1675 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1676 free(inbuf); free(outbuf);
1677 return;
1679 case 0: /* chksum is zero - looks like an EOF */
1680 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1681 free(inbuf); free(outbuf);
1682 return; /* Hmmm, bad here ... */
1684 default:
1685 break;
1689 /* Now, do we have a long file name? */
1691 if (longfilename != NULL) {
1692 if (strlen(longfilename) < sizeof(finfo.name)) { /* if we have space */
1694 strncpy(finfo.name, longfilename, sizeof(finfo.name) - 1);
1695 free(longfilename);
1696 longfilename = NULL;
1699 else {
1701 DEBUG(0, ("filename: %s too long, skipping\n", strlen(longfilename)));
1702 skip = True;
1707 /* Well, now we have a header, process the file ... */
1709 /* Should we skip the file? */
1711 if (skip) {
1713 skip_file(finfo.size);
1714 continue;
1718 /* We only get this far if we should process the file */
1720 switch (((union hblock *)bufferp) -> dbuf.linkflag) {
1722 case '0': /* Should use symbolic names--FIXME */
1723 get_file(finfo);
1724 break;
1726 case '5':
1727 get_dir(finfo);
1728 break;
1730 case 'L':
1731 longfilename = get_longfilename(finfo);
1732 break;
1734 default:
1735 skip_file(finfo.size); /* Don't handle these yet */
1736 break;
1744 #endif /* Removed to get around gcc 'defined but not used' error. */
1746 static void do_tarput()
1748 file_info2 finfo;
1749 int nread=0, bufread;
1750 char *inbuf,*outbuf, *longname = NULL;
1751 int fsize=0;
1752 int fnum;
1753 struct timeval tp_start;
1754 BOOL tskip=False; /* We'll take each file as it comes */
1756 finfo.name = NULL; /* No name in here ... */
1758 GetTimeOfDay(&tp_start);
1760 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1761 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1763 if (!inbuf || !outbuf)
1765 DEBUG(0,("out of memory\n"));
1766 return;
1770 * Must read in tbufsiz dollops
1773 /* These should be the only reads in clitar.c */
1774 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1775 char *buffer_p, *endofbuffer;
1776 int chunk;
1778 /* Code to handle a short read.
1779 * We always need a TBLOCK full of stuff
1781 if (bufread % TBLOCK) {
1782 int lchunk=TBLOCK-(bufread % TBLOCK);
1783 int lread;
1785 /* It's a shorty - a short read that is */
1786 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1788 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1789 bufread+=lread;
1790 if (!(lchunk-=lread)) break;
1793 /* If we've reached EOF then that must be a short file */
1794 if (lread<=0) break;
1797 buffer_p=tarbuf;
1798 endofbuffer=tarbuf+bufread;
1800 if (tskip) {
1801 if (fsize<bufread) {
1802 tskip=False;
1803 buffer_p+=fsize;
1804 fsize=0;
1805 } else {
1806 if (fsize==bufread) tskip=False;
1807 fsize-=bufread;
1808 continue;
1812 do {
1813 if (!fsize)
1815 int next_header = 1; /* Want at least one header */
1816 while (next_header)
1818 if (buffer_p >= endofbuffer) {
1820 bufread = read(tarhandle, tarbuf, tbufsiz);
1821 buffer_p = tarbuf;
1824 next_header = 0; /* Don't want the next one ... */
1826 if (finfo.name != NULL) { /* Free the space */
1828 free(finfo.name);
1829 finfo.name = NULL;
1832 DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n",
1833 (int)tarbuf, (int)buffer_p, (int)endofbuffer));
1834 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
1836 case -2: /* something dodgy but not fatal about this */
1837 DEBUG(0, ("skipping %s...\n", finfo.name));
1838 buffer_p+=TBLOCK; /* header - like a link */
1839 continue;
1840 case -1:
1841 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
1842 free(inbuf); free(outbuf);
1843 return;
1844 case 0: /* chksum is zero - we assume that one all zero
1845 *header block will do for eof */
1846 DEBUG(0,
1847 ("total of %d tar files restored to share\n", ntarf));
1848 free(inbuf); free(outbuf);
1849 return;
1850 default:
1851 break;
1854 /* If we have a longname left from the last time through,
1855 copy it into finfo.name and free it.
1857 The size of a pstring is the limiting factor on filenames
1858 and directory names now. The total pathname length must be
1859 less than sizeof(pstring) - 1, which is currently 1023. */
1861 if (longname != NULL) {
1863 free(finfo.name); /* Free the name in the finfo */
1864 finfo.name = string_create_s(strlen(longname) + 2);
1865 strncpy(finfo.name, longname, strlen(longname) + 1);
1866 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
1867 free(longname);
1868 longname = NULL;
1872 /* Check if a long-link. We do this before the clip checking
1873 because clip-checking should clip on real name - RJS */
1875 if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
1876 int file_len, first = 0; char *cp;
1878 /* Skip this header, but pick up length, get the name and
1879 fix the name and skip the name. Hmmm, what about end of
1880 buffer??? */
1882 longname = malloc(finfo.size + strlen(cur_dir) + 1);
1883 if (longname == NULL) {
1885 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1886 finfo.size + strlen(cur_dir) + 1)
1888 free(inbuf); free(outbuf);
1889 return;
1893 bzero(longname, finfo.size + strlen(cur_dir) +1);
1895 buffer_p += TBLOCK; /* Skip that longlink header */
1897 /* This needs restructuring ... */
1899 safe_strcpy(longname, cur_dir, strlen(cur_dir) + 1);
1900 cp = longname + strlen(cur_dir);
1901 file_len = finfo.size;
1903 DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n",
1904 (int)longname, (int)cp, file_len));
1906 while (file_len > 0) {
1908 if (buffer_p >= endofbuffer) {
1910 bufread = read(tarhandle, tarbuf, tbufsiz);
1912 buffer_p = tarbuf;
1916 unfixtarname(cp, buffer_p, file_len >= TBLOCK?TBLOCK:file_len, first == 0);
1918 first++; /* Not the first anymore */
1919 cp = cp + strlen(cp); /* Move to end of string */
1920 buffer_p += TBLOCK;
1921 file_len -= TBLOCK;
1922 DEBUG(5, ("cp=%0X, file_len=%i\n", (int)cp, file_len));
1923 next_header = 1; /* Force read of next header */
1928 tskip=clipn
1929 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1930 #ifdef HAVE_REGEX_H
1931 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1932 #else
1933 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1934 #endif
1935 if (tskip) {
1936 buffer_p+=TBLOCK;
1937 if (finfo.mode & aDIR)
1938 continue;
1939 else if ((fsize=finfo.size) % TBLOCK) {
1940 fsize+=TBLOCK-(fsize%TBLOCK);
1942 if (fsize<endofbuffer-buffer_p) {
1943 buffer_p+=fsize;
1944 fsize=0;
1945 continue;
1946 } else {
1947 fsize-=endofbuffer-buffer_p;
1948 break;
1952 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
1954 if (finfo.mode & aDIR)
1957 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1958 DEBUG(0, ("restore tar dir %s of size %d bytes\n",
1959 finfo.name, finfo.size));
1961 if (!ensurepath(finfo.name, inbuf, outbuf))
1963 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
1964 free(inbuf); free(outbuf);
1965 return;
1967 else
1969 /* Now we update the creation date ... */
1971 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
1973 if (!do_setrtime(finfo.name, finfo.mtime, True)) {
1975 if (tar_real_noisy) {
1976 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1978 /*return; - Win 95 does not like setting time on dirs */
1982 ntarf++;
1983 buffer_p+=TBLOCK;
1984 continue;
1988 fsize=finfo.size;
1990 if (ensurepath(finfo.name, inbuf, outbuf)
1991 && !smbcreat(finfo, &fnum, inbuf, outbuf))
1993 DEBUG(0, ("abandoning restore\n"));
1994 free(inbuf);free(outbuf);
1995 return;
1998 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
1999 finfo.name, finfo.size));
2001 /* if (!finfo.size) {
2002 if (!smbshut(finfo, fnum, inbuf, outbuf)){
2003 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
2004 free(inbuf);free(outbuf);
2005 return;
2007 } */
2009 nread=0;
2010 if ((buffer_p+=TBLOCK) >= endofbuffer) break;
2011 } /* if (!fsize) */
2013 /* write out the file in chunk sized chunks - don't
2014 * go past end of buffer though */
2015 chunk=(fsize-nread < endofbuffer - buffer_p)
2016 ? fsize - nread : endofbuffer - buffer_p;
2018 while (chunk > 0) {
2019 int minichunk=MIN(chunk, max_xmit-200);
2021 if (!smbwrite(fnum, /* file descriptor */
2022 minichunk, /* n */
2023 nread, /* offset low */
2024 0, /* offset high - not implemented */
2025 fsize-nread, /* left - only hint to server */
2026 buffer_p,
2027 inbuf,
2028 outbuf))
2030 DEBUG(0, ("Error writing remote file\n"));
2031 free(inbuf); free(outbuf);
2032 return;
2034 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
2036 buffer_p+=minichunk; nread+=minichunk;
2037 chunk-=minichunk;
2040 if (nread>=fsize)
2042 if (!smbshut(finfo, fnum, inbuf, outbuf))
2044 DEBUG(0, ("Error closing remote file\n"));
2045 free(inbuf);free(outbuf);
2046 return;
2048 if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
2049 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
2050 (int) buffer_p, (int)(buffer_p - tarbuf)));
2051 ntarf++;
2052 fsize=0;
2055 } while (buffer_p < endofbuffer);
2058 DEBUG(0, ("premature eof on tar file ?\n"));
2059 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
2061 free(inbuf); free(outbuf);
2065 * samba interactive commands
2068 /****************************************************************************
2069 Blocksize command
2070 ***************************************************************************/
2071 void cmd_block(char *dum_in, char *dum_out)
2073 fstring buf;
2074 int block;
2076 if (!next_token(NULL,buf,NULL))
2078 DEBUG(0, ("blocksize <n>\n"));
2079 return;
2082 block=atoi(buf);
2083 if (block < 0 || block > 65535)
2085 DEBUG(0, ("blocksize out of range"));
2086 return;
2089 blocksize=block;
2090 DEBUG(2,("blocksize is now %d\n", blocksize));
2093 /****************************************************************************
2094 command to set incremental / reset mode
2095 ***************************************************************************/
2096 void cmd_tarmode(char *dum_in, char *dum_out)
2098 fstring buf;
2100 while (next_token(NULL,buf,NULL)) {
2101 if (strequal(buf, "full"))
2102 tar_inc=False;
2103 else if (strequal(buf, "inc"))
2104 tar_inc=True;
2105 else if (strequal(buf, "reset"))
2106 tar_reset=True;
2107 else if (strequal(buf, "noreset"))
2108 tar_reset=False;
2109 else if (strequal(buf, "system"))
2110 tar_system=True;
2111 else if (strequal(buf, "nosystem"))
2112 tar_system=False;
2113 else if (strequal(buf, "hidden"))
2114 tar_hidden=True;
2115 else if (strequal(buf, "nohidden"))
2116 tar_hidden=False;
2117 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2118 tar_noisy=True;
2119 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2120 tar_noisy=False;
2121 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2124 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2125 tar_inc ? "incremental" : "full",
2126 tar_system ? "system" : "nosystem",
2127 tar_hidden ? "hidden" : "nohidden",
2128 tar_reset ? "reset" : "noreset",
2129 tar_noisy ? "verbose" : "quiet"));
2133 /****************************************************************************
2134 Feeble attrib command
2135 ***************************************************************************/
2136 void cmd_setmode(char *dum_in, char *dum_out)
2138 char *q;
2139 fstring buf;
2140 pstring fname;
2141 int attra[2];
2142 int direct=1;
2144 attra[0] = attra[1] = 0;
2146 if (!next_token(NULL,buf,NULL))
2148 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2149 return;
2152 safe_strcpy(fname, cur_dir, sizeof(pstring));
2153 safe_strcat(fname, buf, sizeof(pstring));
2155 while (next_token(NULL,buf,NULL)) {
2156 q=buf;
2158 while(*q)
2159 switch (*q++) {
2160 case '+': direct=1;
2161 break;
2162 case '-': direct=0;
2163 break;
2164 case 'r': attra[direct]|=aRONLY;
2165 break;
2166 case 'h': attra[direct]|=aHIDDEN;
2167 break;
2168 case 's': attra[direct]|=aSYSTEM;
2169 break;
2170 case 'a': attra[direct]|=aARCH;
2171 break;
2172 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2173 return;
2177 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2179 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2180 return;
2183 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2184 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2185 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2188 /****************************************************************************
2189 Principal command for creating / extracting
2190 ***************************************************************************/
2191 void cmd_tar(char *inbuf, char *outbuf)
2193 fstring buf;
2194 char **argl;
2195 int argcl;
2197 if (!next_token(NULL,buf,NULL))
2199 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
2200 return;
2203 argl=toktocliplist(&argcl, NULL);
2204 if (!tar_parseargs(argcl, argl, buf, 0))
2205 return;
2207 process_tar(inbuf, outbuf);
2209 free(argl);
2212 /****************************************************************************
2213 Command line (option) version
2214 ***************************************************************************/
2215 int process_tar(char *inbuf, char *outbuf)
2217 initarbuf();
2218 switch(tar_type) {
2219 case 'x':
2221 #if 0
2222 do_tarput2();
2223 #else
2224 do_tarput();
2225 #endif
2226 free(tarbuf);
2227 close(tarhandle);
2228 break;
2229 case 'r':
2230 case 'c':
2231 if (clipn && tar_excl) {
2232 int i;
2233 pstring tarmac;
2235 for (i=0; i<clipn; i++) {
2236 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2238 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2239 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2242 if (strrchr(cliplist[i], '\\')) {
2243 pstring saved_dir;
2245 safe_strcpy(saved_dir, cur_dir, sizeof(pstring));
2247 if (*cliplist[i]=='\\') {
2248 safe_strcpy(tarmac, cliplist[i], sizeof(pstring));
2249 } else {
2250 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2251 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2253 safe_strcpy(cur_dir, tarmac, sizeof(pstring));
2254 *(strrchr(cur_dir, '\\')+1)='\0';
2256 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2257 safe_strcpy(cur_dir,saved_dir, sizeof(pstring));
2258 } else {
2259 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2260 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2261 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2264 } else {
2265 pstring mask;
2266 safe_strcpy(mask,cur_dir, sizeof(pstring));
2267 safe_strcat(mask,"\\*", sizeof(pstring));
2268 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2271 if (ntarf) dotareof(tarhandle);
2272 close(tarhandle);
2273 free(tarbuf);
2275 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2276 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2277 break;
2280 if (must_free_cliplist) {
2281 int i;
2282 for (i = 0; i < clipn; ++i) {
2283 free(cliplist[i]);
2285 free(cliplist);
2286 cliplist = NULL;
2287 clipn = 0;
2288 must_free_cliplist = False;
2291 return(0);
2294 /****************************************************************************
2295 Find a token (filename) in a clip list
2296 ***************************************************************************/
2297 int clipfind(char **aret, int ret, char *tok)
2299 if (aret==NULL) return 0;
2301 /* ignore leading slashes or dots in token */
2302 while(strchr("/\\.", *tok)) tok++;
2304 while(ret--) {
2305 char *pkey=*aret++;
2307 /* ignore leading slashes or dots in list */
2308 while(strchr("/\\.", *pkey)) pkey++;
2310 if (!strslashcmp(pkey, tok)) return 1;
2313 return 0;
2316 /****************************************************************************
2317 Read list of files to include from the file and initialize cliplist
2318 accordingly.
2319 ***************************************************************************/
2320 static int read_inclusion_file(char *filename)
2322 FILE *inclusion = NULL;
2323 char buf[MAXPATHLEN + 1];
2324 char *inclusion_buffer = NULL;
2325 int inclusion_buffer_size = 0;
2326 int inclusion_buffer_sofar = 0;
2327 char *p;
2328 char *tmpstr;
2329 int i;
2330 int error = 0;
2332 clipn = 0;
2333 buf[MAXPATHLEN] = '\0'; /* guarantee null-termination */
2334 if ((inclusion = fopen(filename, "r")) == NULL) {
2335 /* XXX It would be better to include a reason for failure, but without
2336 * autoconf, it's hard to use strerror, sys_errlist, etc.
2338 DEBUG(0,("Unable to open inclusion file %s\n", filename));
2339 return 0;
2342 while ((! error) && (fgets(buf, sizeof(buf)-1, inclusion))) {
2343 if (inclusion_buffer == NULL) {
2344 inclusion_buffer_size = 1024;
2345 if ((inclusion_buffer = malloc(inclusion_buffer_size)) == NULL) {
2346 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
2347 error = 1;
2348 break;
2352 if (buf[strlen(buf)-1] == '\n') {
2353 buf[strlen(buf)-1] = '\0';
2356 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
2357 inclusion_buffer_size *= 2;
2358 inclusion_buffer = Realloc(inclusion_buffer,inclusion_buffer_size);
2359 if (! inclusion_buffer) {
2360 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
2361 inclusion_buffer_size));
2362 error = 1;
2363 break;
2367 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
2368 inclusion_buffer_sofar += strlen(buf) + 1;
2369 clipn++;
2371 fclose(inclusion);
2373 if (! error) {
2374 /* Allocate an array of clipn + 1 char*'s for cliplist */
2375 cliplist = malloc((clipn + 1) * sizeof(char *));
2376 if (cliplist == NULL) {
2377 DEBUG(0,("failure allocating memory for cliplist\n"));
2378 error = 1;
2379 } else {
2380 cliplist[clipn] = NULL;
2381 p = inclusion_buffer;
2382 for (i = 0; (! error) && (i < clipn); i++) {
2383 /* set current item to NULL so array will be null-terminated even if
2384 * malloc fails below. */
2385 cliplist[i] = NULL;
2386 if ((tmpstr = (char *)malloc(strlen(p)+1)) == NULL) {
2387 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));
2388 error = 1;
2389 } else {
2390 unfixtarname(tmpstr, p, strlen(p) + 1, True);
2391 cliplist[i] = tmpstr;
2392 if ((p = strchr(p, '\000')) == NULL) {
2393 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
2394 abort();
2397 ++p;
2399 must_free_cliplist = True;
2403 if (inclusion_buffer) {
2404 free(inclusion_buffer);
2406 if (error) {
2407 if (cliplist) {
2408 char **pp;
2409 /* We know cliplist is always null-terminated */
2410 for (pp = cliplist; *pp; ++pp) {
2411 free(*pp);
2413 free(cliplist);
2414 cliplist = NULL;
2415 must_free_cliplist = False;
2417 return 0;
2420 /* cliplist and its elements are freed at the end of process_tar. */
2421 return 1;
2424 /****************************************************************************
2425 Parse tar arguments. Sets tar_type, tar_excl, etc.
2426 ***************************************************************************/
2427 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2429 char tar_clipfl='\0';
2431 /* Reset back to defaults - could be from interactive version
2432 * reset mode and archive mode left as they are though
2434 tar_type='\0';
2435 tar_excl=True;
2437 while (*Optarg)
2438 switch(*Optarg++) {
2439 case 'c':
2440 tar_type='c';
2441 break;
2442 case 'x':
2443 if (tar_type=='c') {
2444 printf("Tar must be followed by only one of c or x.\n");
2445 return 0;
2447 tar_type='x';
2448 break;
2449 case 'b':
2450 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2451 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2452 return 0;
2453 } else {
2454 Optind++;
2456 break;
2457 case 'g':
2458 tar_inc=True;
2459 break;
2460 case 'N':
2461 if (Optind>=argc) {
2462 DEBUG(0,("Option N must be followed by valid file name\n"));
2463 return 0;
2464 } else {
2465 struct stat stbuf;
2466 extern time_t newer_than;
2468 if (sys_stat(argv[Optind], &stbuf) == 0) {
2469 newer_than = stbuf.st_mtime;
2470 DEBUG(1,("Getting files newer than %s",
2471 asctime(LocalTime(&newer_than))));
2472 Optind++;
2473 } else {
2474 DEBUG(0,("Error setting newer-than time\n"));
2475 return 0;
2478 break;
2479 case 'a':
2480 tar_reset=True;
2481 break;
2482 case 'I':
2483 if (tar_clipfl) {
2484 DEBUG(0,("Only one of I,X,F must be specified\n"));
2485 return 0;
2487 tar_clipfl='I';
2488 break;
2489 case 'X':
2490 if (tar_clipfl) {
2491 DEBUG(0,("Only one of I,X,F must be specified\n"));
2492 return 0;
2494 tar_clipfl='X';
2495 break;
2496 case 'F':
2497 if (tar_clipfl) {
2498 DEBUG(0,("Only one of I,X,F must be specified\n"));
2499 return 0;
2501 tar_clipfl='F';
2502 break;
2503 case 'r':
2504 DEBUG(0, ("tar_re_search set\n"));
2505 tar_re_search = True;
2506 break;
2507 default:
2508 DEBUG(0,("Unknown tar option\n"));
2509 return 0;
2512 if (!tar_type) {
2513 printf("Option T must be followed by one of c or x.\n");
2514 return 0;
2517 /* tar_excl is true if cliplist lists files to be included.
2518 * Both 'I' and 'F' mean include. */
2519 tar_excl=tar_clipfl!='X';
2521 if (tar_clipfl=='F') {
2522 if (argc-Optind-1 != 1) {
2523 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
2524 return 0;
2526 if (! read_inclusion_file(argv[Optind+1])) {
2527 return 0;
2529 } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2530 char *tmpstr;
2531 char **tmplist;
2532 int clipcount;
2534 cliplist=argv+Optind+1;
2535 clipn=argc-Optind-1;
2536 clipcount = clipn;
2538 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2539 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2540 clipn)
2542 return 0;
2545 for (clipcount = 0; clipcount < clipn; clipcount++) {
2547 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2549 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2550 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2551 clipcount)
2553 return 0;
2555 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);
2556 tmplist[clipcount] = tmpstr;
2557 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2559 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2561 cliplist = tmplist;
2562 must_free_cliplist = True;
2565 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2566 #ifdef HAVE_REGEX_H
2567 int errcode;
2569 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2571 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2572 return;
2576 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2577 char errstr[1024];
2578 size_t errlen;
2580 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2582 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2583 return;
2586 #endif
2588 clipn=argc-Optind-1;
2589 cliplist=argv+Optind+1;
2593 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2594 /* Sets tar handle to either 0 or 1, as appropriate */
2595 tarhandle=(tar_type=='c');
2596 } else {
2597 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2598 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2600 DEBUG(0,("Error opening local file %s - %s\n",
2601 argv[Optind], strerror(errno)));
2602 return(0);
2606 return 1;