2 Unix SMB/Netbios implementation.
5 Copyright (C) Ricky Poulten 1995-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 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.
21 /* The following changes developed by Richard Sharpe for Canon Information
22 Systems Research Australia (CISRA) are Copyright (C) 1998 by CISRA and are
23 made available under the terms of the GPL as listed above:
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
42 typedef struct file_info_struct file_info2;
44 struct file_info_struct
50 /* These times are normally kept in GMT */
54 char *name; /* This is dynamically allocate */
56 file_info2 *next, *prev; /* Used in the stack ... */
67 stack dir_stack = {NULL, 0}; /* Want an empty stack */
71 #define SEPARATORS " \t\n\r"
72 extern int DEBUGLEVEL;
75 /* These defines are for the do_setrattr routine, to indicate
76 * setting and reseting of file attributes in the function call */
80 static int attribute = aDIR | aSYSTEM | aHIDDEN;
82 #ifndef CLIENT_TIMEOUT
83 #define CLIENT_TIMEOUT (30*1000)
87 static int tp, ntarf, tbufsiz, ttarf;
88 /* Incremental mode */
90 /* Reset archive bit */
92 /* Include / exclude mode (true=include, false=exclude) */
94 /* use regular expressions for search on file names */
95 BOOL tar_re_search=False;
99 /* Dump files with System attribute */
100 BOOL tar_system=False;
101 /* Dump files with Hidden attribute */
102 BOOL tar_hidden=True;
103 /* Be noisy - make a catalogue */
107 static char **cliplist=NULL;
110 extern file_info def_finfo;
111 extern BOOL lowercase;
113 extern BOOL readbraw_supported;
115 extern pstring cur_dir;
116 extern int get_total_time_ms;
117 extern int get_total_size;
123 static void writetarheader(int f, char *aname, int size, time_t mtime,
124 char *amode, unsigned char ftype);
125 static void do_atar(char *rname,char *lname,file_info *finfo1);
126 static void do_tar(file_info *finfo);
127 static void oct_it(long value, int ndgs, char *p);
128 static void fixtarname(char *tptr, char *fp, int l);
129 static int dotarbuf(int f, char *b, int n);
130 static void dozerobuf(int f, int n);
131 static void dotareof(int f);
132 static void initarbuf(void);
133 static int do_setrattr(char *fname, int attr, int setit);
135 /* restore functions */
136 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix);
137 static long unoct(char *p, int ndgs);
138 static void do_tarput(void);
139 static void unfixtarname(char *tptr, char *fp, int l);
142 * tar specific utitlities
145 #if 0 /* Removed to get around gcc 'defined but not used' error. */
148 * Stack routines, push_dir, pop_dir, top_dir_name
151 static BOOL push_dir(stack *tar_dir_stack, file_info2 *dir)
153 dir -> next = tar_dir_stack -> top;
155 tar_dir_stack -> items++;
156 tar_dir_stack -> top = dir;
161 static file_info2 *pop_dir(stack *tar_dir_stack)
165 ptr = tar_dir_stack -> top;
166 if (tar_dir_stack -> top != NULL) {
168 tar_dir_stack -> top = tar_dir_stack -> top -> next;
169 tar_dir_stack -> items--;
177 static char *top_dir_name(stack *tar_dir_stack)
180 return(tar_dir_stack -> top != NULL?tar_dir_stack -> top -> name:NULL);
184 static BOOL sub_dir(char *dir1, char *dir2)
191 #endif /* Removed to get around gcc 'defined but not used' error. */
193 /* Create a string of size size+1 (for the null) */
194 static char * string_create_s(int size)
198 tmp = (char *)malloc(size+1);
202 DEBUG(0, ("Out of memory in string_create_s\n"));
210 /****************************************************************************
211 Write a tar header to buffer
212 ****************************************************************************/
213 static void writetarheader(int f, char *aname, int size, time_t mtime,
214 char *amode, unsigned char ftype)
220 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
222 memset(hb.dummy, 0, sizeof(hb.dummy));
226 /* write a GNU tar style long header */
228 b = (char *)malloc(l+TBLOCK+100);
230 DEBUG(0,("out of memory\n"));
233 writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L');
234 memset(b, 0, l+TBLOCK+100);
235 fixtarname(b, aname, l+1);
237 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
238 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
242 /* use l + 1 to do the null too */
243 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
246 strlower(hb.dbuf.name);
248 /* write out a "standard" tar format header */
250 hb.dbuf.name[NAMSIZ-1]='\0';
251 strcpy(hb.dbuf.mode, amode);
252 oct_it(0L, 8, hb.dbuf.uid);
253 oct_it(0L, 8, hb.dbuf.gid);
254 oct_it((long) size, 13, hb.dbuf.size);
255 oct_it((long) mtime, 13, hb.dbuf.mtime);
256 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
257 memset(hb.dbuf.linkname, 0, NAMSIZ);
258 hb.dbuf.linkflag=ftype;
260 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
262 oct_it((long) chk, 8, hb.dbuf.chksum);
263 hb.dbuf.chksum[6] = '\0';
265 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
268 /****************************************************************************
269 Read a tar header into a hblock structure, and validate
270 ***************************************************************************/
271 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
278 * read in a "standard" tar format header - we're not that interested
279 * in that many fields, though
282 /* check the checksum */
283 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
288 /* compensate for blanks in chksum header */
289 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
292 chk += ' ' * sizeof(hb->dbuf.chksum);
294 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
296 DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
297 chk, fchk, hb->dbuf.chksum));
301 DEBUG(0, ("checksums don't match %d %d\n", fchk, chk));
305 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
307 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
312 strcpy(finfo->name, prefix);
314 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
315 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
316 strlen(hb->dbuf.name) + 1);
318 /* can't handle some links at present */
319 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
320 if (hb->dbuf.linkflag == 0) {
321 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
324 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
325 /* Do nothing here at the moment. do_tarput will handle this
326 as long as the longlink gets back to it, as it has to advance
327 the buffer pointer, etc */
330 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
336 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
337 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
342 finfo->mode=0; /* we don't care about mode at the moment, we'll
343 * just make it a regular file */
345 * Bug fix by richard@sj.co.uk
347 * REC: restore times correctly (as does tar)
348 * We only get the modification time of the file; set the creation time
349 * from the mod. time, and the access time to current time
351 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
352 finfo->atime = time(NULL);
353 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
358 /****************************************************************************
359 Write out the tar buffer to tape or wherever
360 ****************************************************************************/
361 static int dotarbuf(int f, char *b, int n)
365 /* This routine and the next one should be the only ones that do write()s */
366 if (tp + n >= tbufsiz)
371 memcpy(tarbuf + tp, b, diff);
372 fail=fail && (1+write(f, tarbuf, tbufsiz));
379 fail=fail && (1 + write(f, b, tbufsiz));
385 memcpy(tarbuf+tp, b, n);
389 return(fail ? writ : 0);
392 /****************************************************************************
393 Write zeros to buffer / tape
394 ****************************************************************************/
395 static void dozerobuf(int f, int n)
397 /* short routine just to write out n zeros to buffer -
398 * used to round files to nearest block
399 * and to do tar EOFs */
403 memset(tarbuf+tp, 0, tbufsiz-tp);
405 write(f, tarbuf, tbufsiz);
406 memset(tarbuf, 0, (tp+=n-tbufsiz));
410 memset(tarbuf+tp, 0, n);
415 /****************************************************************************
417 ****************************************************************************/
418 static void initarbuf()
420 /* initialize tar buffer */
421 tbufsiz=blocksize*TBLOCK;
422 tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */
424 /* reset tar buffer pointer and tar file counter and total dumped */
425 tp=0; ntarf=0; ttarf=0;
428 /****************************************************************************
429 Write two zero blocks at end of file
430 ****************************************************************************/
431 static void dotareof(int f)
434 /* Two zero blocks at end of file, write out full buffer */
436 (void) dozerobuf(f, TBLOCK);
437 (void) dozerobuf(f, TBLOCK);
439 if (fstat(f, &stbuf) == -1)
441 DEBUG(0, ("Couldn't stat file handle\n"));
445 /* Could be a pipe, in which case S_ISREG should fail,
446 * and we should write out at full size */
447 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
450 /****************************************************************************
451 (Un)mangle DOS pathname, make nonabsolute
452 ****************************************************************************/
453 static void fixtarname(char *tptr, char *fp, int l)
455 /* add a '.' to start of file name, convert from ugly dos \'s in path
456 * to lovely unix /'s :-} */
462 if((skip = skip_multibyte_char( *fp)) != 0) {
467 } else if (skip == 1) {
471 } else if (*fp == '\\') {
482 /****************************************************************************
483 Convert from decimal to octal string
484 ****************************************************************************/
485 static void oct_it (long value, int ndgs, char *p)
487 /* Converts long to octal string, pads with leading zeros */
489 /* skip final null, but do final space */
493 /* Loop does at least one digit */
495 p[--ndgs] = '0' + (char) (value & 7);
498 while (ndgs > 0 && value != 0);
500 /* Do leading zeros */
505 /****************************************************************************
506 Convert from octal string to long
507 ***************************************************************************/
508 static long unoct(char *p, int ndgs)
511 /* Converts octal string to long, ignoring any non-digit */
516 value = (value << 3) | (long) (*p - '0');
524 /****************************************************************************
525 Compare two strings in a slash insensitive way, allowing s1 to match s2
526 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
527 a file in any subdirectory of s1, declare a match.
528 ***************************************************************************/
529 static int strslashcmp(char *s1, char *s2)
535 || tolower(*s1) == tolower(*s2)
536 || (*s1 == '\\' && *s2=='/')
537 || (*s1 == '/' && *s2=='\\'))) {
541 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
544 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
546 /* ignore trailing slash on s1 */
547 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
549 /* check for s1 is an "initial" string of s2 */
550 if (*s2 == '/' || *s2 == '\\') return 0;
556 * general smb utility functions
558 /**********************************************************************
559 do_setrtime, set time on a file or dir ...
560 **********************************************************************/
562 static int do_setrtime(char *fname, int mtime)
564 char *inbuf, *outbuf, *p;
567 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
569 name = (char *)malloc(strlen(fname) + 1 + 1);
572 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
581 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
582 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
584 if (!inbuf || !outbuf) {
586 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
591 memset(outbuf, 0, smb_size);
592 set_message(outbuf, 8, 4 + strlen(fname), True);
593 CVAL(outbuf, smb_com) = SMBsetatr;
594 SSVAL(outbuf, smb_tid, cnum);
595 cli_setup_pkt(outbuf);
597 SSVAL(outbuf, smb_vwv0, 0);
598 put_dos_date3(outbuf, smb_vwv1, mtime);
603 p+= (strlen(fname)+1);
608 send_smb(Client, outbuf);
609 client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
611 if (CVAL(inbuf,smb_rcls) != 0)
613 DEBUG(0,("%s setting attributes on file %s\n",
614 smb_errstr(inbuf), fname));
615 free(inbuf);free(outbuf);
619 free(inbuf);free(outbuf);
624 /****************************************************************************
625 Set DOS file attributes
626 ***************************************************************************/
627 static int do_setrattr(char *fname, int attr, int setit)
630 * First get the existing attribs from existing file
641 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
642 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
644 if (!inbuf || !outbuf)
646 DEBUG(0,("out of memory\n"));
650 /* send an smb getatr message */
652 memset(outbuf,0,smb_size);
653 set_message(outbuf,0,2 + strlen(fname),True);
654 CVAL(outbuf,smb_com) = SMBgetatr;
655 SSVAL(outbuf,smb_tid,cnum);
656 cli_setup_pkt(outbuf);
661 p += (strlen(fname)+1);
666 send_smb(Client,outbuf);
667 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
669 if (CVAL(inbuf,smb_rcls) != 0)
670 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
673 DEBUG(5,("\nattr 0x%X time %d size %d\n",
674 (int)CVAL(inbuf,smb_vwv0),
675 SVAL(inbuf,smb_vwv1),
676 SVAL(inbuf,smb_vwv3)));
679 fattr=CVAL(inbuf,smb_vwv0);
681 /* combine found attributes with bits to be set or reset */
683 attr=setit ? (fattr | attr) : (fattr & ~attr);
685 /* now try and set attributes by sending smb reset message */
687 /* clear out buffer and start again */
688 memset(outbuf,0,smb_size);
689 set_message(outbuf,8,4 + strlen(fname),True);
690 CVAL(outbuf,smb_com) = SMBsetatr;
691 SSVAL(outbuf,smb_tid,cnum);
692 cli_setup_pkt(outbuf);
694 SSVAL(outbuf,smb_vwv0,attr);
699 p += (strlen(fname)+1);
704 send_smb(Client,outbuf);
705 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
707 if (CVAL(inbuf,smb_rcls) != 0)
709 DEBUG(0,("%s setting attributes on file %s\n",
710 smb_errstr(inbuf), fname));
711 free(inbuf);free(outbuf);
715 free(inbuf);free(outbuf);
719 /****************************************************************************
720 Create a file on a share
721 ***************************************************************************/
722 static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
725 /* *must* be called with buffer ready malloc'ed */
726 /* open remote file */
728 memset(outbuf,0,smb_size);
729 set_message(outbuf,3,2 + strlen(finfo.name),True);
730 CVAL(outbuf,smb_com) = SMBcreate;
731 SSVAL(outbuf,smb_tid,cnum);
732 cli_setup_pkt(outbuf);
734 SSVAL(outbuf,smb_vwv0,finfo.mode);
735 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
739 strcpy(p,finfo.name);
741 send_smb(Client,outbuf);
742 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
744 if (CVAL(inbuf,smb_rcls) != 0)
746 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
751 *fnum = SVAL(inbuf,smb_vwv0);
755 /****************************************************************************
756 Write a file to a share
757 ***************************************************************************/
758 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
759 char *bufferp, char *inbuf, char *outbuf)
761 /* *must* be called with buffer ready malloc'ed */
763 memset(outbuf,0,smb_size);
764 set_message(outbuf,5,n + 3,True);
766 memcpy(smb_buf(outbuf)+3, bufferp, n);
768 set_message(outbuf,5,n + 3, False);
769 CVAL(outbuf,smb_com) = SMBwrite;
770 SSVAL(outbuf,smb_tid,cnum);
771 cli_setup_pkt(outbuf);
773 SSVAL(outbuf,smb_vwv0,fnum);
774 SSVAL(outbuf,smb_vwv1,n);
775 SIVAL(outbuf,smb_vwv2,low);
776 SSVAL(outbuf,smb_vwv4,left);
777 CVAL(smb_buf(outbuf),0) = 1;
778 SSVAL(smb_buf(outbuf),1,n);
780 send_smb(Client,outbuf);
781 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
783 if (CVAL(inbuf,smb_rcls) != 0)
785 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
789 if (n != SVAL(inbuf,smb_vwv0))
791 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
792 SVAL(inbuf,smb_vwv0), n));
799 /****************************************************************************
800 Close a file on a share
801 ***************************************************************************/
802 static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
804 /* *must* be called with buffer ready malloc'ed */
806 memset(outbuf,0,smb_size);
807 set_message(outbuf,3,0,True);
808 CVAL(outbuf,smb_com) = SMBclose;
809 SSVAL(outbuf,smb_tid,cnum);
810 cli_setup_pkt(outbuf);
812 SSVAL(outbuf,smb_vwv0,fnum);
813 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
815 DEBUG(3,("Setting date to %s (0x%X)",
816 asctime(LocalTime(&finfo.mtime)),
819 send_smb(Client,outbuf);
820 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
822 if (CVAL(inbuf,smb_rcls) != 0)
824 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
832 /****************************************************************************
833 Verify existence of path on share
834 ***************************************************************************/
835 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
839 memset(outbuf,0,smb_size);
840 set_message(outbuf,0,4 + strlen(fname),True);
841 CVAL(outbuf,smb_com) = SMBchkpth;
842 SSVAL(outbuf,smb_tid,cnum);
843 cli_setup_pkt(outbuf);
849 send_smb(Client,outbuf);
850 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
852 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
854 return(CVAL(inbuf,smb_rcls) == 0);
857 /****************************************************************************
858 Make a directory on share
859 ***************************************************************************/
860 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
862 /* *must* be called with buffer ready malloc'ed */
865 memset(outbuf,0,smb_size);
866 set_message(outbuf,0,2 + strlen(fname),True);
868 CVAL(outbuf,smb_com) = SMBmkdir;
869 SSVAL(outbuf,smb_tid,cnum);
870 cli_setup_pkt(outbuf);
876 send_smb(Client,outbuf);
877 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
879 if (CVAL(inbuf,smb_rcls) != 0)
881 DEBUG(0,("%s making remote directory %s\n",
882 smb_errstr(inbuf),fname));
889 /****************************************************************************
890 Ensure a remote path exists (make if necessary)
891 ***************************************************************************/
892 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
894 /* *must* be called with buffer ready malloc'ed */
895 /* ensures path exists */
897 char *partpath, *ffname;
898 char *p=fname, *basehack;
900 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
902 partpath = string_create_s(strlen(fname));
903 ffname = string_create_s(strlen(fname));
905 if ((partpath == NULL) || (ffname == NULL)){
907 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
914 /* fname copied to ffname so can strtok */
916 strcpy(ffname, fname);
918 /* do a `basename' on ffname, so don't try and make file name directory */
919 if ((basehack=strrchr(ffname, '\\')) == NULL)
924 p=strtok(ffname, "\\");
930 if (!smbchkpath(partpath, inbuf, outbuf)) {
931 if (!smbmkdir(partpath, inbuf, outbuf))
933 DEBUG(0, ("Error mkdirhiering\n"));
937 DEBUG(3, ("mkdirhiering %s\n", partpath));
941 strcat(partpath, "\\");
942 p = strtok(NULL,"/\\");
948 int padit(char *buf, int bufsize, int padsize)
953 DEBUG(5, ("Padding with %d zeros\n", padsize));
954 memset(buf, 0, bufsize);
955 while( !berr && padsize > 0 ) {
956 bytestowrite= MIN(bufsize, padsize);
957 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
958 padsize -= bytestowrite;
965 * smbclient functions
967 /****************************************************************************
968 append one remote file to the tar file
969 ***************************************************************************/
970 static void do_atar(char *rname,char *lname,file_info *finfo1)
977 BOOL close_done = False;
978 BOOL shallitime=True;
979 BOOL ignore_close_error = False;
983 struct timeval tp_start;
984 GetTimeOfDay(&tp_start);
986 ftype = '0'; /* An ordinary file ... */
993 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
994 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
996 if (!inbuf || !outbuf)
998 DEBUG(0,("out of memory\n"));
1002 memset(outbuf,0,smb_size);
1003 set_message(outbuf,15,1 + strlen(rname),True);
1005 CVAL(outbuf,smb_com) = SMBopenX;
1006 SSVAL(outbuf,smb_tid,cnum);
1007 cli_setup_pkt(outbuf);
1009 SSVAL(outbuf,smb_vwv0,0xFF);
1010 SSVAL(outbuf,smb_vwv2,1);
1011 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1012 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1013 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1014 SSVAL(outbuf,smb_vwv8,1);
1016 p = smb_buf(outbuf);
1018 p = skip_string(p,1);
1020 dos_clean_name(rname);
1022 /* do a chained openX with a readX? */
1025 SSVAL(outbuf,smb_vwv0,SMBreadX);
1026 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
1029 SSVAL(p,smb_wct,10);
1030 SSVAL(p,smb_vwv0,0xFF);
1031 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1032 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
1033 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1036 send_smb(Client,outbuf);
1037 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1039 if (CVAL(inbuf,smb_rcls) != 0)
1041 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1042 SVAL(inbuf,smb_err) == ERRnoresource &&
1043 cli_reopen_connection(inbuf,outbuf))
1045 do_atar(rname,lname,finfo1);
1046 free(inbuf);free(outbuf);
1050 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
1051 free(inbuf);free(outbuf);
1055 strcpy(finfo.name,rname);
1058 finfo.mode = SVAL(inbuf,smb_vwv3);
1059 finfo.size = IVAL(inbuf,smb_vwv4);
1060 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
1061 finfo.atime = finfo.ctime = finfo.mtime;
1064 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
1066 fnum = SVAL(inbuf,smb_vwv2);
1068 if (tar_inc && !(finfo.mode & aARCH))
1070 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
1073 else if (!tar_system && (finfo.mode & aSYSTEM))
1075 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
1078 else if (!tar_hidden && (finfo.mode & aHIDDEN))
1080 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
1085 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1087 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
1088 datalen = SVAL(p,smb_vwv5);
1089 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
1097 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1102 /* write a tar header, don't bother with mode - just set to 100644 */
1103 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
1105 while (nread < finfo.size && !close_done)
1108 static BOOL can_chain_close=True;
1112 DEBUG(3,("nread=%d\n",nread));
1114 /* 3 possible read types. readbraw if a large block is required.
1115 readX + close if not much left and read if neither is supported */
1117 /* we might have already read some data from a chained readX */
1118 if (dataptr && datalen>0)
1121 /* if we can finish now then readX+close */
1122 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1123 ((finfo.size - nread) <
1124 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1127 /* if we support readraw then use that */
1128 if (method<0 && readbraw_supported)
1131 /* if we can then use readX */
1132 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1144 /* use readX + close */
1145 memset(outbuf,0,smb_size);
1146 set_message(outbuf,10,0,True);
1147 CVAL(outbuf,smb_com) = SMBreadX;
1148 SSVAL(outbuf,smb_tid,cnum);
1149 cli_setup_pkt(outbuf);
1153 CVAL(outbuf,smb_vwv0) = SMBclose;
1154 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
1157 CVAL(outbuf,smb_vwv0) = 0xFF;
1160 SSVAL(outbuf,smb_vwv2,fnum);
1161 SIVAL(outbuf,smb_vwv3,nread);
1162 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1163 SSVAL(outbuf,smb_vwv6,0);
1164 SIVAL(outbuf,smb_vwv7,0);
1165 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
1169 p = smb_buf(outbuf);
1176 /* now set the total packet length */
1177 smb_setlen(outbuf,smb_len(outbuf)+9);
1180 send_smb(Client,outbuf);
1181 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1183 if (CVAL(inbuf,smb_rcls) != 0)
1185 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1190 SVAL(inbuf,smb_vwv0) != SMBclose)
1192 /* NOTE: WfWg sometimes just ignores the chained
1193 command! This seems to break the spec? */
1194 DEBUG(3,("Rejected chained close?\n"));
1196 can_chain_close = False;
1197 ignore_close_error = True;
1200 datalen = SVAL(inbuf,smb_vwv5);
1201 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
1208 static int readbraw_size = 0xFFFF;
1211 memset(outbuf,0,smb_size);
1212 set_message(outbuf,8,0,True);
1213 CVAL(outbuf,smb_com) = SMBreadbraw;
1214 SSVAL(outbuf,smb_tid,cnum);
1215 cli_setup_pkt(outbuf);
1216 SSVAL(outbuf,smb_vwv0,fnum);
1217 SIVAL(outbuf,smb_vwv1,nread);
1218 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1219 SSVAL(outbuf,smb_vwv4,0);
1220 SIVALS(outbuf,smb_vwv5,-1);
1221 send_smb(Client,outbuf);
1223 /* Now read the raw data into the buffer and write it */
1224 if(read_smb_length(Client,inbuf,0) == -1) {
1225 DEBUG(0,("Failed to read length in readbraw\n"));
1229 /* Even though this is not an smb message, smb_len
1230 returns the generic length of an smb message */
1231 datalen = smb_len(inbuf);
1235 /* we got a readbraw error */
1236 DEBUG(4,("readbraw error - reducing size\n"));
1237 readbraw_size = (readbraw_size * 9) / 10;
1239 if (readbraw_size < max_xmit)
1241 DEBUG(0,("disabling readbraw\n"));
1242 readbraw_supported = False;
1249 if(read_data(Client,inbuf,datalen) != datalen) {
1250 DEBUG(0,("Failed to read data in readbraw\n"));
1258 /* we've already read some data with a chained readX */
1262 /* use plain read */
1263 memset(outbuf,0,smb_size);
1264 set_message(outbuf,5,0,True);
1265 CVAL(outbuf,smb_com) = SMBread;
1266 SSVAL(outbuf,smb_tid,cnum);
1267 cli_setup_pkt(outbuf);
1269 SSVAL(outbuf,smb_vwv0,fnum);
1270 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1271 SIVAL(outbuf,smb_vwv2,nread);
1272 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1274 send_smb(Client,outbuf);
1275 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1277 if (CVAL(inbuf,smb_rcls) != 0)
1279 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1283 datalen = SVAL(inbuf,smb_vwv0);
1284 dataptr = smb_buf(inbuf) + 3;
1289 /* add received bits of file to buffer - dotarbuf will
1290 * write out in 512 byte intervals */
1291 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1293 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
1300 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1308 /* pad tar file with zero's if we couldn't get entire file */
1309 if (nread < finfo.size)
1311 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
1312 if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
1313 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
1316 /* round tar file to nearest block */
1317 if (finfo.size % TBLOCK)
1318 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1320 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1326 memset(outbuf,0,smb_size);
1327 set_message(outbuf,3,0,True);
1328 CVAL(outbuf,smb_com) = SMBclose;
1329 SSVAL(outbuf,smb_tid,cnum);
1330 cli_setup_pkt(outbuf);
1332 SSVAL(outbuf,smb_vwv0,fnum);
1333 SIVALS(outbuf,smb_vwv1,-1);
1335 send_smb(Client,outbuf);
1336 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1338 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1340 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1341 free(inbuf);free(outbuf);
1348 struct timeval tp_end;
1351 /* if shallitime is true then we didn't skip */
1352 if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1354 GetTimeOfDay(&tp_end);
1356 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1357 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1358 get_total_time_ms += this_time;
1359 get_total_size += finfo.size;
1361 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1362 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1363 finfo.size / MAX(0.001, (1.024*this_time)),
1364 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1367 printf("%10d (%7.1f kb/s) %s\n",
1368 finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
1374 free(inbuf);free(outbuf);
1377 /****************************************************************************
1378 Append single file to tar file (or not)
1379 ***************************************************************************/
1380 static void do_tar(file_info *finfo)
1384 if (strequal(finfo->name,".."))
1387 /* Is it on the exclude list ? */
1388 if (!tar_excl && clipn) {
1391 strcpy(exclaim, cur_dir);
1392 *(exclaim+strlen(exclaim)-1)='\0';
1394 strcat(exclaim, "\\");
1395 strcat(exclaim, finfo->name);
1397 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
1399 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
1401 (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
1403 (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
1405 DEBUG(3,("Skipping file %s\n", exclaim));
1410 if (finfo->mode & aDIR)
1412 pstring saved_curdir;
1414 char *inbuf,*outbuf;
1416 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1417 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1419 if (!inbuf || !outbuf)
1421 DEBUG(0,("out of memory\n"));
1425 strcpy(saved_curdir,cur_dir);
1427 strcat(cur_dir,finfo->name);
1428 strcat(cur_dir,"\\");
1430 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
1432 /* write a tar directory, don't bother with mode - just set it to
1434 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
1435 ntarf++; /* Make sure we have a file on there */
1436 strcpy(mtar_mask,cur_dir);
1437 strcat(mtar_mask,"*");
1438 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1439 strcpy(cur_dir,saved_curdir);
1440 free(inbuf);free(outbuf);
1444 strcpy(rname,cur_dir);
1445 strcat(rname,finfo->name);
1446 do_atar(rname,finfo->name,finfo);
1450 /****************************************************************************
1451 Convert from UNIX to DOS file names
1452 ***************************************************************************/
1453 static void unfixtarname(char *tptr, char *fp, int l)
1455 /* remove '.' from start of file name, convert from unix /'s to
1456 * dos \'s in path. Kill any absolute path names.
1459 if (*fp == '.') fp++;
1460 if (*fp == '\\' || *fp == '/') fp++;
1464 if(( skip = skip_multibyte_char( *fp )) != 0) {
1469 } else if (skip == 1) {
1473 } else if (*fp == '/') {
1484 #if 0 /* Removed to get around gcc 'defined but not used' error. */
1486 /****************************************************************************
1487 Move to the next block in the buffer, which may mean read in another set of
1489 ****************************************************************************/
1490 static int next_block(char *ltarbuf, char *bufferp, int bufsiz)
1492 int bufread, total = 0;
1494 if (bufferp >= (ltarbuf + bufsiz)) {
1496 for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
1498 if (bufread <= 0) { /* An error, return false */
1499 return (total > 0 ? -2 : bufread);
1517 static int skip_file(int skip)
1523 static int get_file(file_info2 finfo)
1530 static int get_dir(file_info2 finfo)
1537 static char * get_longfilename(file_info2 finfo)
1544 static char * bufferp;
1546 static void do_tarput2(void)
1548 file_info2 finfo, *finfo2;
1549 struct timeval tp_start;
1550 char *inbuf, *outbuf, *longfilename = NULL;
1553 GetTimeOfDay(&tp_start);
1555 bufferp = tarbuf + tbufsiz; /* init this to force first read */
1557 if (push_dir(&dir_stack, &finfo)) {
1559 finfo2 = pop_dir(&dir_stack);
1560 inbuf = top_dir_name(&dir_stack); /* FIXME */
1561 if (sub_dir(inbuf, finfo2 -> name)){
1568 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1569 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1571 if (!inbuf || !outbuf) {
1573 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1578 if (next_block(tarbuf, bufferp, tbufsiz) <= 0) {
1580 DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno)));
1584 /* Now read through those files ... */
1588 switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) {
1590 case -2: /* Hmm, not good, but not fatal */
1591 DEBUG(0, ("Skipping %s...\n", finfo.name));
1592 if ((next_block(tarbuf, bufferp, tbufsiz) <= 0) &&
1593 !skip_file(finfo.size)) {
1595 DEBUG(0, ("Short file, bailing out...\n"));
1596 free(inbuf); free(outbuf);
1604 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1605 free(inbuf); free(outbuf);
1608 case 0: /* chksum is zero - looks like an EOF */
1609 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1610 free(inbuf); free(outbuf);
1611 return; /* Hmmm, bad here ... */
1618 /* Now, do we have a long file name? */
1620 if (longfilename != NULL) {
1621 if (strlen(longfilename) < sizeof(finfo.name)) { /* if we have space */
1623 strncpy(finfo.name, longfilename, sizeof(finfo.name) - 1);
1625 longfilename = NULL;
1630 DEBUG(0, ("filename: %s too long, skipping\n", strlen(longfilename)));
1636 /* Well, now we have a header, process the file ... */
1638 /* Should we skip the file? */
1642 skip_file(finfo.size);
1647 /* We only get this far if we should process the file */
1649 switch (((union hblock *)bufferp) -> dbuf.linkflag) {
1651 case '0': /* Should use symbolic names--FIXME */
1660 longfilename = get_longfilename(finfo);
1664 skip_file(finfo.size); /* Don't handle these yet */
1673 #endif /* Removed to get around gcc 'defined but not used' error. */
1675 static void do_tarput()
1678 int nread=0, bufread;
1679 char *inbuf,*outbuf, *longname = NULL;
1682 struct timeval tp_start;
1683 BOOL tskip=False; /* We'll take each file as it comes */
1685 finfo.name = NULL; /* No name in here ... */
1687 GetTimeOfDay(&tp_start);
1689 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1690 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1692 if (!inbuf || !outbuf)
1694 DEBUG(0,("out of memory\n"));
1699 * Must read in tbufsiz dollops
1702 /* These should be the only reads in clitar.c */
1703 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1704 char *buffer_p, *endofbuffer;
1707 /* Code to handle a short read.
1708 * We always need a TBLOCK full of stuff
1710 if (bufread % TBLOCK) {
1711 int lchunk=TBLOCK-(bufread % TBLOCK);
1714 /* It's a shorty - a short read that is */
1715 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1717 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1719 if (!(lchunk-=lread)) break;
1722 /* If we've reached EOF then that must be a short file */
1723 if (lread<=0) break;
1727 endofbuffer=tarbuf+bufread;
1730 if (fsize<bufread) {
1735 if (fsize==bufread) tskip=False;
1744 int next_header = 1; /* Want at least one header */
1747 if (buffer_p >= endofbuffer) {
1749 bufread = read(tarhandle, tarbuf, tbufsiz);
1753 next_header = 0; /* Don't want the next one ... */
1755 if (finfo.name != NULL) { /* Free the space */
1761 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
1763 case -2: /* something dodgy but not fatal about this */
1764 DEBUG(0, ("skipping %s...\n", finfo.name));
1765 buffer_p+=TBLOCK; /* header - like a link */
1768 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
1769 free(inbuf); free(outbuf);
1771 case 0: /* chksum is zero - we assume that one all zero
1772 *header block will do for eof */
1774 ("total of %d tar files restored to share\n", ntarf));
1775 free(inbuf); free(outbuf);
1781 /* If we have a longname left from the last time through,
1782 copy it into finfo.name and free it.
1784 The size of a pstring is the limiting factor on filenames
1785 and directory names now. The total pathname length must be
1786 less than sizeof(pstring) - 1, which is currently 1023. */
1788 if (longname != NULL) {
1790 free(finfo.name); /* Free the name in the finfo */
1791 finfo.name = string_create_s(strlen(longname) + 2);
1792 strncpy(finfo.name, longname, strlen(longname) + 1);
1793 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
1799 /* Check if a long-link. We do this before the clip checking
1800 because clip-checking should clip on real name - RJS */
1802 if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
1804 /* Skip this header, but pick up length, get the name and
1805 fix the name and skip the name. Hmmm, what about end of
1808 DEBUG(5, ("Buffer size = %i\n", finfo.size + strlen(cur_dir) +1));
1809 longname = malloc(finfo.size + strlen(cur_dir) + 1);
1810 if (longname == NULL) {
1812 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1813 finfo.size + strlen(cur_dir) + 1)
1815 free(inbuf); free(outbuf);
1819 buffer_p += TBLOCK; /* Skip that longlink header */
1821 /* This needs restructuring ... */
1823 if (buffer_p >= endofbuffer) {
1825 bufread = read(tarhandle, tarbuf, tbufsiz);
1831 strncpy(longname, cur_dir, strlen(cur_dir) + 1);
1832 unfixtarname(longname+strlen(cur_dir), buffer_p, finfo.size);
1833 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
1835 /* Next rounds up to next TBLOCK and takes care of us being right
1836 on a TBLOCK boundary */
1838 buffer_p += (((finfo.size - 1)/TBLOCK)+1)*TBLOCK;
1839 next_header = 1; /* Force read of next header */
1844 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1846 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1848 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1852 if (finfo.mode & aDIR)
1854 else if ((fsize=finfo.size) % TBLOCK) {
1855 fsize+=TBLOCK-(fsize%TBLOCK);
1857 if (fsize<endofbuffer-buffer_p) {
1862 fsize-=endofbuffer-buffer_p;
1867 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
1869 if (finfo.mode & aDIR)
1872 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1874 if (!ensurepath(finfo.name, inbuf, outbuf))
1876 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
1877 free(inbuf); free(outbuf);
1882 /* Now we update the creation date ... */
1884 DEBUG(0, ("Updating creation date on %s\n", finfo.name));
1886 if (!do_setrtime(finfo.name, finfo.mtime)) {
1888 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1901 if (ensurepath(finfo.name, inbuf, outbuf)
1902 && !smbcreat(finfo, &fnum, inbuf, outbuf))
1904 DEBUG(0, ("abandoning restore\n"));
1905 free(inbuf);free(outbuf);
1909 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
1910 finfo.name,finfo.size));
1912 /* if (!finfo.size) {
1913 if (!smbshut(finfo, fnum, inbuf, outbuf)){
1914 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
1915 free(inbuf);free(outbuf);
1921 if ((buffer_p+=TBLOCK) >= endofbuffer) break;
1924 /* write out the file in chunk sized chunks - don't
1925 * go past end of buffer though */
1926 chunk=(fsize-nread < endofbuffer - buffer_p)
1927 ? fsize - nread : endofbuffer - buffer_p;
1930 int minichunk=MIN(chunk, max_xmit-200);
1932 if (!smbwrite(fnum, /* file descriptor */
1934 nread, /* offset low */
1935 0, /* offset high - not implemented */
1936 fsize-nread, /* left - only hint to server */
1941 DEBUG(0, ("Error writing remote file\n"));
1942 free(inbuf); free(outbuf);
1945 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
1947 buffer_p+=minichunk; nread+=minichunk;
1953 if (!smbshut(finfo, fnum, inbuf, outbuf))
1955 DEBUG(0, ("Error closing remote file\n"));
1956 free(inbuf);free(outbuf);
1959 if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
1960 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
1961 (long) buffer_p, (long)(buffer_p - tarbuf)));
1966 } while (buffer_p < endofbuffer);
1969 DEBUG(0, ("premature eof on tar file ?\n"));
1970 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
1972 free(inbuf); free(outbuf);
1976 * samba interactive commands
1979 /****************************************************************************
1981 ***************************************************************************/
1982 void cmd_block(char *dum_in, char *dum_out)
1987 if (!next_token(NULL,buf,NULL))
1989 DEBUG(0, ("blocksize <n>\n"));
1994 if (block < 0 || block > 65535)
1996 DEBUG(0, ("blocksize out of range"));
2001 DEBUG(2,("blocksize is now %d\n", blocksize));
2004 /****************************************************************************
2005 command to set incremental / reset mode
2006 ***************************************************************************/
2007 void cmd_tarmode(char *dum_in, char *dum_out)
2011 while (next_token(NULL,buf,NULL)) {
2012 if (strequal(buf, "full"))
2014 else if (strequal(buf, "inc"))
2016 else if (strequal(buf, "reset"))
2018 else if (strequal(buf, "noreset"))
2020 else if (strequal(buf, "system"))
2022 else if (strequal(buf, "nosystem"))
2024 else if (strequal(buf, "hidden"))
2026 else if (strequal(buf, "nohidden"))
2028 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2030 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2032 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2035 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2036 tar_inc ? "incremental" : "full",
2037 tar_system ? "system" : "nosystem",
2038 tar_hidden ? "hidden" : "nohidden",
2039 tar_reset ? "reset" : "noreset",
2040 tar_noisy ? "verbose" : "quiet"));
2044 /****************************************************************************
2045 Feeble attrib command
2046 ***************************************************************************/
2047 void cmd_setmode(char *dum_in, char *dum_out)
2055 attra[0] = attra[1] = 0;
2057 if (!next_token(NULL,buf,NULL))
2059 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2063 strcpy(fname, cur_dir);
2066 while (next_token(NULL,buf,NULL)) {
2075 case 'r': attra[direct]|=aRONLY;
2077 case 'h': attra[direct]|=aHIDDEN;
2079 case 's': attra[direct]|=aSYSTEM;
2081 case 'a': attra[direct]|=aARCH;
2083 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2088 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2090 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2094 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2095 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2096 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2099 /****************************************************************************
2100 Principal command for creating / extracting
2101 ***************************************************************************/
2102 void cmd_tar(char *inbuf, char *outbuf)
2108 if (!next_token(NULL,buf,NULL))
2110 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
2114 argl=toktocliplist(&argcl, NULL);
2115 if (!tar_parseargs(argcl, argl, buf, 0))
2118 process_tar(inbuf, outbuf);
2123 /****************************************************************************
2124 Command line (option) version
2125 ***************************************************************************/
2126 int process_tar(char *inbuf, char *outbuf)
2142 if (clipn && tar_excl) {
2146 for (i=0; i<clipn; i++) {
2147 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2149 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2150 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2153 if (strrchr(cliplist[i], '\\')) {
2156 strcpy(saved_dir, cur_dir);
2158 if (*cliplist[i]=='\\') {
2159 strcpy(tarmac, cliplist[i]);
2161 strcpy(tarmac, cur_dir);
2162 strcat(tarmac, cliplist[i]);
2164 strcpy(cur_dir, tarmac);
2165 *(strrchr(cur_dir, '\\')+1)='\0';
2167 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2168 strcpy(cur_dir,saved_dir);
2170 strcpy(tarmac, cur_dir);
2171 strcat(tarmac, cliplist[i]);
2172 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2177 strcpy(mask,cur_dir);
2179 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2182 if (ntarf) dotareof(tarhandle);
2186 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2187 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2194 /****************************************************************************
2195 Find a token (filename) in a clip list
2196 ***************************************************************************/
2197 int clipfind(char **aret, int ret, char *tok)
2199 if (aret==NULL) return 0;
2201 /* ignore leading slashes or dots in token */
2202 while(strchr("/\\.", *tok)) tok++;
2207 /* ignore leading slashes or dots in list */
2208 while(strchr("/\\.", *pkey)) pkey++;
2210 if (!strslashcmp(pkey, tok)) return 1;
2216 /****************************************************************************
2217 Parse tar arguments. Sets tar_type, tar_excl, etc.
2218 ***************************************************************************/
2219 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2221 char tar_clipfl='\0';
2223 /* Reset back to defaults - could be from interactive version
2224 * reset mode and archive mode left as they are though
2235 if (tar_type=='c') {
2236 printf("Tar must be followed by only one of c or x.\n");
2242 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2243 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2254 DEBUG(0,("Option N must be followed by valid file name\n"));
2258 extern time_t newer_than;
2260 if (sys_stat(argv[Optind], &stbuf) == 0) {
2261 newer_than = stbuf.st_mtime;
2262 DEBUG(1,("Getting files newer than %s",
2263 asctime(LocalTime(&newer_than))));
2266 DEBUG(0,("Error setting newer-than time\n"));
2276 DEBUG(0,("Only one of I,X must be specified\n"));
2283 DEBUG(0,("Only one of I,X must be specified\n"));
2289 DEBUG(0, ("tar_re_search set\n"));
2290 tar_re_search = True;
2293 DEBUG(0,("Unknown tar option\n"));
2298 printf("Option T must be followed by one of c or x.\n");
2302 tar_excl=tar_clipfl!='X';
2304 if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2309 cliplist=argv+Optind+1;
2310 clipn=argc-Optind-1;
2313 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2314 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2320 for (clipcount = 0; clipcount < clipn; clipcount++) {
2322 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2324 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2325 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2330 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1);
2331 tmplist[clipcount] = tmpstr;
2332 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2334 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2339 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2343 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2345 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2350 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2354 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2356 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2362 clipn=argc-Optind-1;
2363 cliplist=argv+Optind+1;
2367 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2368 /* Sets tar handle to either 0 or 1, as appropriate */
2369 tarhandle=(tar_type=='c');
2371 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2372 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2374 DEBUG(0,("Error opening local file %s - %s\n",
2375 argv[Optind], strerror(errno)));