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 /*******************************************************************
194 Create a string of size size+1 (for the null)
195 *******************************************************************/
196 static char * string_create_s(int size)
200 tmp = (char *)malloc(size+1);
204 DEBUG(0, ("Out of memory in string_create_s\n"));
212 /****************************************************************************
213 Write a tar header to buffer
214 ****************************************************************************/
215 static void writetarheader(int f, char *aname, int size, time_t mtime,
216 char *amode, unsigned char ftype)
222 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
224 memset(hb.dummy, 0, sizeof(hb.dummy));
228 /* write a GNU tar style long header */
230 b = (char *)malloc(l+TBLOCK+100);
232 DEBUG(0,("out of memory\n"));
235 writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L');
236 memset(b, 0, l+TBLOCK+100);
237 fixtarname(b, aname, l+1);
239 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
240 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
244 /* use l + 1 to do the null too */
245 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
248 strlower(hb.dbuf.name);
250 /* write out a "standard" tar format header */
252 hb.dbuf.name[NAMSIZ-1]='\0';
253 fstrcpy(hb.dbuf.mode, amode);
254 oct_it(0L, 8, hb.dbuf.uid);
255 oct_it(0L, 8, hb.dbuf.gid);
256 oct_it((long) size, 13, hb.dbuf.size);
257 oct_it((long) mtime, 13, hb.dbuf.mtime);
258 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
259 memset(hb.dbuf.linkname, 0, NAMSIZ);
260 hb.dbuf.linkflag=ftype;
262 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
264 oct_it((long) chk, 8, hb.dbuf.chksum);
265 hb.dbuf.chksum[6] = '\0';
267 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
270 /****************************************************************************
271 Read a tar header into a hblock structure, and validate
272 ***************************************************************************/
273 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
280 * read in a "standard" tar format header - we're not that interested
281 * in that many fields, though
284 /* check the checksum */
285 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
290 /* compensate for blanks in chksum header */
291 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
294 chk += ' ' * sizeof(hb->dbuf.chksum);
296 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
298 DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
299 chk, fchk, hb->dbuf.chksum));
303 DEBUG(0, ("checksums don't match %d %d\n", fchk, chk));
307 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
309 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
314 pstrcpy(finfo->name, prefix);
316 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
317 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
318 strlen(hb->dbuf.name) + 1);
320 /* can't handle some links at present */
321 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
322 if (hb->dbuf.linkflag == 0) {
323 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
326 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
327 /* Do nothing here at the moment. do_tarput will handle this
328 as long as the longlink gets back to it, as it has to advance
329 the buffer pointer, etc */
332 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
338 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
339 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
344 finfo->mode=0; /* we don't care about mode at the moment, we'll
345 * just make it a regular file */
347 * Bug fix by richard@sj.co.uk
349 * REC: restore times correctly (as does tar)
350 * We only get the modification time of the file; set the creation time
351 * from the mod. time, and the access time to current time
353 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
354 finfo->atime = time(NULL);
355 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
360 /****************************************************************************
361 Write out the tar buffer to tape or wherever
362 ****************************************************************************/
363 static int dotarbuf(int f, char *b, int n)
367 /* This routine and the next one should be the only ones that do write()s */
368 if (tp + n >= tbufsiz)
373 memcpy(tarbuf + tp, b, diff);
374 fail=fail && (1+write(f, tarbuf, tbufsiz));
381 fail=fail && (1 + write(f, b, tbufsiz));
387 memcpy(tarbuf+tp, b, n);
391 return(fail ? writ : 0);
394 /****************************************************************************
395 Write zeros to buffer / tape
396 ****************************************************************************/
397 static void dozerobuf(int f, int n)
399 /* short routine just to write out n zeros to buffer -
400 * used to round files to nearest block
401 * and to do tar EOFs */
405 memset(tarbuf+tp, 0, tbufsiz-tp);
407 write(f, tarbuf, tbufsiz);
408 memset(tarbuf, 0, (tp+=n-tbufsiz));
412 memset(tarbuf+tp, 0, n);
417 /****************************************************************************
419 ****************************************************************************/
420 static void initarbuf()
422 /* initialize tar buffer */
423 tbufsiz=blocksize*TBLOCK;
424 tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */
426 /* reset tar buffer pointer and tar file counter and total dumped */
427 tp=0; ntarf=0; ttarf=0;
430 /****************************************************************************
431 Write two zero blocks at end of file
432 ****************************************************************************/
433 static void dotareof(int f)
436 /* Two zero blocks at end of file, write out full buffer */
438 (void) dozerobuf(f, TBLOCK);
439 (void) dozerobuf(f, TBLOCK);
441 if (fstat(f, &stbuf) == -1)
443 DEBUG(0, ("Couldn't stat file handle\n"));
447 /* Could be a pipe, in which case S_ISREG should fail,
448 * and we should write out at full size */
449 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
452 /****************************************************************************
453 (Un)mangle DOS pathname, make nonabsolute
454 ****************************************************************************/
455 static void fixtarname(char *tptr, char *fp, int l)
457 /* add a '.' to start of file name, convert from ugly dos \'s in path
458 * to lovely unix /'s :-} */
464 if((skip = skip_multibyte_char( *fp)) != 0) {
469 } else if (skip == 1) {
473 } else if (*fp == '\\') {
484 /****************************************************************************
485 Convert from decimal to octal string
486 ****************************************************************************/
487 static void oct_it (long value, int ndgs, char *p)
489 /* Converts long to octal string, pads with leading zeros */
491 /* skip final null, but do final space */
495 /* Loop does at least one digit */
497 p[--ndgs] = '0' + (char) (value & 7);
500 while (ndgs > 0 && value != 0);
502 /* Do leading zeros */
507 /****************************************************************************
508 Convert from octal string to long
509 ***************************************************************************/
510 static long unoct(char *p, int ndgs)
513 /* Converts octal string to long, ignoring any non-digit */
518 value = (value << 3) | (long) (*p - '0');
526 /****************************************************************************
527 Compare two strings in a slash insensitive way, allowing s1 to match s2
528 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
529 a file in any subdirectory of s1, declare a match.
530 ***************************************************************************/
531 static int strslashcmp(char *s1, char *s2)
537 || tolower(*s1) == tolower(*s2)
538 || (*s1 == '\\' && *s2=='/')
539 || (*s1 == '/' && *s2=='\\'))) {
543 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
546 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
548 /* ignore trailing slash on s1 */
549 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
551 /* check for s1 is an "initial" string of s2 */
552 if (*s2 == '/' || *s2 == '\\') return 0;
558 * general smb utility functions
560 /**********************************************************************
561 do_setrtime, set time on a file or dir ...
562 **********************************************************************/
564 static int do_setrtime(char *fname, int mtime)
566 char *inbuf, *outbuf, *p;
569 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
571 name = (char *)malloc(strlen(fname) + 1 + 1);
574 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
579 pstrcpy(name, fname);
580 pstrcpy(fname, "\\");
581 pstrcat(fname, name);
583 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
584 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
586 if (!inbuf || !outbuf) {
588 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
593 memset(outbuf, 0, smb_size);
594 set_message(outbuf, 8, 4 + strlen(fname), True);
595 CVAL(outbuf, smb_com) = SMBsetatr;
596 SSVAL(outbuf, smb_tid, cnum);
597 cli_setup_pkt(outbuf);
599 SSVAL(outbuf, smb_vwv0, 0);
600 put_dos_date3(outbuf, smb_vwv1, mtime);
605 p+= (strlen(fname)+1);
610 send_smb(Client, outbuf);
611 client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
613 if (CVAL(inbuf,smb_rcls) != 0)
615 DEBUG(0,("%s setting attributes on file %s\n",
616 smb_errstr(inbuf), fname));
617 free(inbuf);free(outbuf);
621 free(inbuf);free(outbuf);
626 /****************************************************************************
627 Set DOS file attributes
628 ***************************************************************************/
629 static int do_setrattr(char *fname, int attr, int setit)
632 * First get the existing attribs from existing file
643 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
644 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
646 if (!inbuf || !outbuf)
648 DEBUG(0,("out of memory\n"));
652 /* send an smb getatr message */
654 memset(outbuf,0,smb_size);
655 set_message(outbuf,0,2 + strlen(fname),True);
656 CVAL(outbuf,smb_com) = SMBgetatr;
657 SSVAL(outbuf,smb_tid,cnum);
658 cli_setup_pkt(outbuf);
663 p += (strlen(fname)+1);
668 send_smb(Client,outbuf);
669 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
671 if (CVAL(inbuf,smb_rcls) != 0)
672 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
675 DEBUG(5,("\nattr 0x%X time %d size %d\n",
676 (int)CVAL(inbuf,smb_vwv0),
677 SVAL(inbuf,smb_vwv1),
678 SVAL(inbuf,smb_vwv3)));
681 fattr=CVAL(inbuf,smb_vwv0);
683 /* combine found attributes with bits to be set or reset */
685 attr=setit ? (fattr | attr) : (fattr & ~attr);
687 /* now try and set attributes by sending smb reset message */
689 /* clear out buffer and start again */
690 memset(outbuf,0,smb_size);
691 set_message(outbuf,8,4 + strlen(fname),True);
692 CVAL(outbuf,smb_com) = SMBsetatr;
693 SSVAL(outbuf,smb_tid,cnum);
694 cli_setup_pkt(outbuf);
696 SSVAL(outbuf,smb_vwv0,attr);
701 p += (strlen(fname)+1);
706 send_smb(Client,outbuf);
707 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
709 if (CVAL(inbuf,smb_rcls) != 0)
711 DEBUG(0,("%s setting attributes on file %s\n",
712 smb_errstr(inbuf), fname));
713 free(inbuf);free(outbuf);
717 free(inbuf);free(outbuf);
721 /****************************************************************************
722 Create a file on a share
723 ***************************************************************************/
724 static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
727 /* *must* be called with buffer ready malloc'ed */
728 /* open remote file */
730 memset(outbuf,0,smb_size);
731 set_message(outbuf,3,2 + strlen(finfo.name),True);
732 CVAL(outbuf,smb_com) = SMBcreate;
733 SSVAL(outbuf,smb_tid,cnum);
734 cli_setup_pkt(outbuf);
736 SSVAL(outbuf,smb_vwv0,finfo.mode);
737 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
741 pstrcpy(p,finfo.name);
743 send_smb(Client,outbuf);
744 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
746 if (CVAL(inbuf,smb_rcls) != 0)
748 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
753 *fnum = SVAL(inbuf,smb_vwv0);
757 /****************************************************************************
758 Write a file to a share
759 ***************************************************************************/
760 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
761 char *bufferp, char *inbuf, char *outbuf)
763 /* *must* be called with buffer ready malloc'ed */
765 memset(outbuf,0,smb_size);
766 set_message(outbuf,5,n + 3,True);
768 memcpy(smb_buf(outbuf)+3, bufferp, n);
770 set_message(outbuf,5,n + 3, False);
771 CVAL(outbuf,smb_com) = SMBwrite;
772 SSVAL(outbuf,smb_tid,cnum);
773 cli_setup_pkt(outbuf);
775 SSVAL(outbuf,smb_vwv0,fnum);
776 SSVAL(outbuf,smb_vwv1,n);
777 SIVAL(outbuf,smb_vwv2,low);
778 SSVAL(outbuf,smb_vwv4,left);
779 CVAL(smb_buf(outbuf),0) = 1;
780 SSVAL(smb_buf(outbuf),1,n);
782 send_smb(Client,outbuf);
783 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
785 if (CVAL(inbuf,smb_rcls) != 0)
787 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
791 if (n != SVAL(inbuf,smb_vwv0))
793 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
794 SVAL(inbuf,smb_vwv0), n));
801 /****************************************************************************
802 Close a file on a share
803 ***************************************************************************/
804 static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
806 /* *must* be called with buffer ready malloc'ed */
808 memset(outbuf,0,smb_size);
809 set_message(outbuf,3,0,True);
810 CVAL(outbuf,smb_com) = SMBclose;
811 SSVAL(outbuf,smb_tid,cnum);
812 cli_setup_pkt(outbuf);
814 SSVAL(outbuf,smb_vwv0,fnum);
815 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
817 DEBUG(3,("Setting date to %s (0x%X)",
818 asctime(LocalTime(&finfo.mtime)),
821 send_smb(Client,outbuf);
822 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
824 if (CVAL(inbuf,smb_rcls) != 0)
826 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
834 /****************************************************************************
835 Verify existence of path on share
836 ***************************************************************************/
837 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
841 memset(outbuf,0,smb_size);
842 set_message(outbuf,0,4 + strlen(fname),True);
843 CVAL(outbuf,smb_com) = SMBchkpth;
844 SSVAL(outbuf,smb_tid,cnum);
845 cli_setup_pkt(outbuf);
851 send_smb(Client,outbuf);
852 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
854 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
856 return(CVAL(inbuf,smb_rcls) == 0);
859 /****************************************************************************
860 Make a directory on share
861 ***************************************************************************/
862 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
864 /* *must* be called with buffer ready malloc'ed */
867 memset(outbuf,0,smb_size);
868 set_message(outbuf,0,2 + strlen(fname),True);
870 CVAL(outbuf,smb_com) = SMBmkdir;
871 SSVAL(outbuf,smb_tid,cnum);
872 cli_setup_pkt(outbuf);
878 send_smb(Client,outbuf);
879 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
881 if (CVAL(inbuf,smb_rcls) != 0)
883 DEBUG(0,("%s making remote directory %s\n",
884 smb_errstr(inbuf),fname));
891 /****************************************************************************
892 Ensure a remote path exists (make if necessary)
893 ***************************************************************************/
894 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
896 /* *must* be called with buffer ready malloc'ed */
897 /* ensures path exists */
899 char *partpath, *ffname;
900 char *p=fname, *basehack;
902 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
904 partpath = string_create_s(strlen(fname));
905 ffname = string_create_s(strlen(fname));
907 if ((partpath == NULL) || (ffname == NULL)){
909 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
916 /* fname copied to ffname so can strtok */
918 pstrcpy(ffname, fname);
920 /* do a `basename' on ffname, so don't try and make file name directory */
921 if ((basehack=strrchr(ffname, '\\')) == NULL)
926 p=strtok(ffname, "\\");
930 pstrcat(partpath, p);
932 if (!smbchkpath(partpath, inbuf, outbuf)) {
933 if (!smbmkdir(partpath, inbuf, outbuf))
935 DEBUG(0, ("Error mkdirhiering\n"));
939 DEBUG(3, ("mkdirhiering %s\n", partpath));
943 pstrcat(partpath, "\\");
944 p = strtok(NULL,"/\\");
950 int padit(char *buf, int bufsize, int padsize)
955 DEBUG(5, ("Padding with %d zeros\n", padsize));
956 memset(buf, 0, bufsize);
957 while( !berr && padsize > 0 ) {
958 bytestowrite= MIN(bufsize, padsize);
959 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
960 padsize -= bytestowrite;
967 * smbclient functions
969 /****************************************************************************
970 append one remote file to the tar file
971 ***************************************************************************/
972 static void do_atar(char *rname,char *lname,file_info *finfo1)
979 BOOL close_done = False;
980 BOOL shallitime=True;
981 BOOL ignore_close_error = False;
985 struct timeval tp_start;
986 GetTimeOfDay(&tp_start);
988 ftype = '0'; /* An ordinary file ... */
995 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
996 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
998 if (!inbuf || !outbuf)
1000 DEBUG(0,("out of memory\n"));
1004 memset(outbuf,0,smb_size);
1005 set_message(outbuf,15,1 + strlen(rname),True);
1007 CVAL(outbuf,smb_com) = SMBopenX;
1008 SSVAL(outbuf,smb_tid,cnum);
1009 cli_setup_pkt(outbuf);
1011 SSVAL(outbuf,smb_vwv0,0xFF);
1012 SSVAL(outbuf,smb_vwv2,1);
1013 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1014 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1015 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1016 SSVAL(outbuf,smb_vwv8,1);
1018 p = smb_buf(outbuf);
1020 p = skip_string(p,1);
1022 dos_clean_name(rname);
1024 /* do a chained openX with a readX? */
1027 SSVAL(outbuf,smb_vwv0,SMBreadX);
1028 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
1031 SSVAL(p,smb_wct,10);
1032 SSVAL(p,smb_vwv0,0xFF);
1033 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1034 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
1035 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1038 send_smb(Client,outbuf);
1039 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1041 if (CVAL(inbuf,smb_rcls) != 0)
1043 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1044 SVAL(inbuf,smb_err) == ERRnoresource &&
1045 cli_reopen_connection(inbuf,outbuf))
1047 do_atar(rname,lname,finfo1);
1048 free(inbuf);free(outbuf);
1052 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
1053 free(inbuf);free(outbuf);
1057 pstrcpy(finfo.name,rname);
1060 finfo.mode = SVAL(inbuf,smb_vwv3);
1061 finfo.size = IVAL(inbuf,smb_vwv4);
1062 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
1063 finfo.atime = finfo.ctime = finfo.mtime;
1066 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
1068 fnum = SVAL(inbuf,smb_vwv2);
1070 if (tar_inc && !(finfo.mode & aARCH))
1072 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
1075 else if (!tar_system && (finfo.mode & aSYSTEM))
1077 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
1080 else if (!tar_hidden && (finfo.mode & aHIDDEN))
1082 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
1087 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1089 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
1090 datalen = SVAL(p,smb_vwv5);
1091 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
1099 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1104 /* write a tar header, don't bother with mode - just set to 100644 */
1105 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
1107 while (nread < finfo.size && !close_done)
1110 static BOOL can_chain_close=True;
1114 DEBUG(3,("nread=%d\n",nread));
1116 /* 3 possible read types. readbraw if a large block is required.
1117 readX + close if not much left and read if neither is supported */
1119 /* we might have already read some data from a chained readX */
1120 if (dataptr && datalen>0)
1123 /* if we can finish now then readX+close */
1124 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1125 ((finfo.size - nread) <
1126 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1129 /* if we support readraw then use that */
1130 if (method<0 && readbraw_supported)
1133 /* if we can then use readX */
1134 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1146 /* use readX + close */
1147 memset(outbuf,0,smb_size);
1148 set_message(outbuf,10,0,True);
1149 CVAL(outbuf,smb_com) = SMBreadX;
1150 SSVAL(outbuf,smb_tid,cnum);
1151 cli_setup_pkt(outbuf);
1155 CVAL(outbuf,smb_vwv0) = SMBclose;
1156 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
1159 CVAL(outbuf,smb_vwv0) = 0xFF;
1162 SSVAL(outbuf,smb_vwv2,fnum);
1163 SIVAL(outbuf,smb_vwv3,nread);
1164 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1165 SSVAL(outbuf,smb_vwv6,0);
1166 SIVAL(outbuf,smb_vwv7,0);
1167 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
1171 p = smb_buf(outbuf);
1178 /* now set the total packet length */
1179 smb_setlen(outbuf,smb_len(outbuf)+9);
1182 send_smb(Client,outbuf);
1183 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1185 if (CVAL(inbuf,smb_rcls) != 0)
1187 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1192 SVAL(inbuf,smb_vwv0) != SMBclose)
1194 /* NOTE: WfWg sometimes just ignores the chained
1195 command! This seems to break the spec? */
1196 DEBUG(3,("Rejected chained close?\n"));
1198 can_chain_close = False;
1199 ignore_close_error = True;
1202 datalen = SVAL(inbuf,smb_vwv5);
1203 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
1210 static int readbraw_size = 0xFFFF;
1213 memset(outbuf,0,smb_size);
1214 set_message(outbuf,8,0,True);
1215 CVAL(outbuf,smb_com) = SMBreadbraw;
1216 SSVAL(outbuf,smb_tid,cnum);
1217 cli_setup_pkt(outbuf);
1218 SSVAL(outbuf,smb_vwv0,fnum);
1219 SIVAL(outbuf,smb_vwv1,nread);
1220 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1221 SSVAL(outbuf,smb_vwv4,0);
1222 SIVALS(outbuf,smb_vwv5,-1);
1223 send_smb(Client,outbuf);
1225 /* Now read the raw data into the buffer and write it */
1226 if(read_smb_length(Client,inbuf,0) == -1) {
1227 DEBUG(0,("Failed to read length in readbraw\n"));
1231 /* Even though this is not an smb message, smb_len
1232 returns the generic length of an smb message */
1233 datalen = smb_len(inbuf);
1237 /* we got a readbraw error */
1238 DEBUG(4,("readbraw error - reducing size\n"));
1239 readbraw_size = (readbraw_size * 9) / 10;
1241 if (readbraw_size < max_xmit)
1243 DEBUG(0,("disabling readbraw\n"));
1244 readbraw_supported = False;
1251 if(read_data(Client,inbuf,datalen) != datalen) {
1252 DEBUG(0,("Failed to read data in readbraw\n"));
1260 /* we've already read some data with a chained readX */
1264 /* use plain read */
1265 memset(outbuf,0,smb_size);
1266 set_message(outbuf,5,0,True);
1267 CVAL(outbuf,smb_com) = SMBread;
1268 SSVAL(outbuf,smb_tid,cnum);
1269 cli_setup_pkt(outbuf);
1271 SSVAL(outbuf,smb_vwv0,fnum);
1272 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1273 SIVAL(outbuf,smb_vwv2,nread);
1274 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1276 send_smb(Client,outbuf);
1277 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1279 if (CVAL(inbuf,smb_rcls) != 0)
1281 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1285 datalen = SVAL(inbuf,smb_vwv0);
1286 dataptr = smb_buf(inbuf) + 3;
1291 /* add received bits of file to buffer - dotarbuf will
1292 * write out in 512 byte intervals */
1293 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1295 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
1302 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1310 /* pad tar file with zero's if we couldn't get entire file */
1311 if (nread < finfo.size)
1313 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
1314 if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
1315 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
1318 /* round tar file to nearest block */
1319 if (finfo.size % TBLOCK)
1320 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1322 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1328 memset(outbuf,0,smb_size);
1329 set_message(outbuf,3,0,True);
1330 CVAL(outbuf,smb_com) = SMBclose;
1331 SSVAL(outbuf,smb_tid,cnum);
1332 cli_setup_pkt(outbuf);
1334 SSVAL(outbuf,smb_vwv0,fnum);
1335 SIVALS(outbuf,smb_vwv1,-1);
1337 send_smb(Client,outbuf);
1338 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1340 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1342 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1343 free(inbuf);free(outbuf);
1350 struct timeval tp_end;
1353 /* if shallitime is true then we didn't skip */
1354 if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1356 GetTimeOfDay(&tp_end);
1358 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1359 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1360 get_total_time_ms += this_time;
1361 get_total_size += finfo.size;
1363 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1364 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1365 finfo.size / MAX(0.001, (1.024*this_time)),
1366 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1369 printf("%10d (%7.1f kb/s) %s\n",
1370 finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
1376 free(inbuf);free(outbuf);
1379 /****************************************************************************
1380 Append single file to tar file (or not)
1381 ***************************************************************************/
1382 static void do_tar(file_info *finfo)
1386 if (strequal(finfo->name,".."))
1389 /* Is it on the exclude list ? */
1390 if (!tar_excl && clipn) {
1393 pstrcpy(exclaim, cur_dir);
1394 *(exclaim+strlen(exclaim)-1)='\0';
1396 pstrcat(exclaim, "\\");
1397 pstrcat(exclaim, finfo->name);
1399 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
1401 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
1403 (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
1405 (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
1407 DEBUG(3,("Skipping file %s\n", exclaim));
1412 if (finfo->mode & aDIR)
1414 pstring saved_curdir;
1416 char *inbuf,*outbuf;
1418 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1419 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1421 if (!inbuf || !outbuf)
1423 DEBUG(0,("out of memory\n"));
1427 pstrcpy(saved_curdir,cur_dir);
1429 pstrcat(cur_dir,finfo->name);
1430 pstrcat(cur_dir,"\\");
1432 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
1434 /* write a tar directory, don't bother with mode - just set it to
1436 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
1437 ntarf++; /* Make sure we have a file on there */
1438 pstrcpy(mtar_mask,cur_dir);
1439 pstrcat(mtar_mask,"*");
1440 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1441 pstrcpy(cur_dir,saved_curdir);
1442 free(inbuf);free(outbuf);
1446 pstrcpy(rname,cur_dir);
1447 pstrcat(rname,finfo->name);
1448 do_atar(rname,finfo->name,finfo);
1452 /****************************************************************************
1453 Convert from UNIX to DOS file names
1454 ***************************************************************************/
1455 static void unfixtarname(char *tptr, char *fp, int l)
1457 /* remove '.' from start of file name, convert from unix /'s to
1458 * dos \'s in path. Kill any absolute path names.
1461 if (*fp == '.') fp++;
1462 if (*fp == '\\' || *fp == '/') fp++;
1466 if(( skip = skip_multibyte_char( *fp )) != 0) {
1471 } else if (skip == 1) {
1475 } else if (*fp == '/') {
1486 #if 0 /* Removed to get around gcc 'defined but not used' error. */
1488 /****************************************************************************
1489 Move to the next block in the buffer, which may mean read in another set of
1491 ****************************************************************************/
1492 static int next_block(char *ltarbuf, char *bufferp, int bufsiz)
1494 int bufread, total = 0;
1496 if (bufferp >= (ltarbuf + bufsiz)) {
1498 for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
1500 if (bufread <= 0) { /* An error, return false */
1501 return (total > 0 ? -2 : bufread);
1519 static int skip_file(int skip)
1525 static int get_file(file_info2 finfo)
1532 static int get_dir(file_info2 finfo)
1539 static char * get_longfilename(file_info2 finfo)
1546 static char * bufferp;
1548 static void do_tarput2(void)
1550 file_info2 finfo, *finfo2;
1551 struct timeval tp_start;
1552 char *inbuf, *outbuf, *longfilename = NULL;
1555 GetTimeOfDay(&tp_start);
1557 bufferp = tarbuf + tbufsiz; /* init this to force first read */
1559 if (push_dir(&dir_stack, &finfo)) {
1561 finfo2 = pop_dir(&dir_stack);
1562 inbuf = top_dir_name(&dir_stack); /* FIXME */
1563 if (sub_dir(inbuf, finfo2 -> name)){
1570 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1571 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1573 if (!inbuf || !outbuf) {
1575 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1580 if (next_block(tarbuf, bufferp, tbufsiz) <= 0) {
1582 DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno)));
1586 /* Now read through those files ... */
1590 switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) {
1592 case -2: /* Hmm, not good, but not fatal */
1593 DEBUG(0, ("Skipping %s...\n", finfo.name));
1594 if ((next_block(tarbuf, bufferp, tbufsiz) <= 0) &&
1595 !skip_file(finfo.size)) {
1597 DEBUG(0, ("Short file, bailing out...\n"));
1598 free(inbuf); free(outbuf);
1606 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1607 free(inbuf); free(outbuf);
1610 case 0: /* chksum is zero - looks like an EOF */
1611 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1612 free(inbuf); free(outbuf);
1613 return; /* Hmmm, bad here ... */
1620 /* Now, do we have a long file name? */
1622 if (longfilename != NULL) {
1623 if (strlen(longfilename) < sizeof(finfo.name)) { /* if we have space */
1625 strncpy(finfo.name, longfilename, sizeof(finfo.name) - 1);
1627 longfilename = NULL;
1632 DEBUG(0, ("filename: %s too long, skipping\n", strlen(longfilename)));
1638 /* Well, now we have a header, process the file ... */
1640 /* Should we skip the file? */
1644 skip_file(finfo.size);
1649 /* We only get this far if we should process the file */
1651 switch (((union hblock *)bufferp) -> dbuf.linkflag) {
1653 case '0': /* Should use symbolic names--FIXME */
1662 longfilename = get_longfilename(finfo);
1666 skip_file(finfo.size); /* Don't handle these yet */
1675 #endif /* Removed to get around gcc 'defined but not used' error. */
1677 static void do_tarput()
1680 int nread=0, bufread;
1681 char *inbuf,*outbuf, *longname = NULL;
1684 struct timeval tp_start;
1685 BOOL tskip=False; /* We'll take each file as it comes */
1687 finfo.name = NULL; /* No name in here ... */
1689 GetTimeOfDay(&tp_start);
1691 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1692 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1694 if (!inbuf || !outbuf)
1696 DEBUG(0,("out of memory\n"));
1701 * Must read in tbufsiz dollops
1704 /* These should be the only reads in clitar.c */
1705 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1706 char *buffer_p, *endofbuffer;
1709 /* Code to handle a short read.
1710 * We always need a TBLOCK full of stuff
1712 if (bufread % TBLOCK) {
1713 int lchunk=TBLOCK-(bufread % TBLOCK);
1716 /* It's a shorty - a short read that is */
1717 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1719 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1721 if (!(lchunk-=lread)) break;
1724 /* If we've reached EOF then that must be a short file */
1725 if (lread<=0) break;
1729 endofbuffer=tarbuf+bufread;
1732 if (fsize<bufread) {
1737 if (fsize==bufread) tskip=False;
1746 int next_header = 1; /* Want at least one header */
1749 if (buffer_p >= endofbuffer) {
1751 bufread = read(tarhandle, tarbuf, tbufsiz);
1755 next_header = 0; /* Don't want the next one ... */
1757 if (finfo.name != NULL) { /* Free the space */
1763 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
1765 case -2: /* something dodgy but not fatal about this */
1766 DEBUG(0, ("skipping %s...\n", finfo.name));
1767 buffer_p+=TBLOCK; /* header - like a link */
1770 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
1771 free(inbuf); free(outbuf);
1773 case 0: /* chksum is zero - we assume that one all zero
1774 *header block will do for eof */
1776 ("total of %d tar files restored to share\n", ntarf));
1777 free(inbuf); free(outbuf);
1783 /* If we have a longname left from the last time through,
1784 copy it into finfo.name and free it.
1786 The size of a pstring is the limiting factor on filenames
1787 and directory names now. The total pathname length must be
1788 less than sizeof(pstring) - 1, which is currently 1023. */
1790 if (longname != NULL) {
1792 free(finfo.name); /* Free the name in the finfo */
1793 finfo.name = string_create_s(strlen(longname) + 2);
1794 strncpy(finfo.name, longname, strlen(longname) + 1);
1795 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
1801 /* Check if a long-link. We do this before the clip checking
1802 because clip-checking should clip on real name - RJS */
1804 if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
1806 /* Skip this header, but pick up length, get the name and
1807 fix the name and skip the name. Hmmm, what about end of
1810 DEBUG(5, ("Buffer size = %i\n", finfo.size + strlen(cur_dir) +1));
1811 longname = malloc(finfo.size + strlen(cur_dir) + 1);
1812 if (longname == NULL) {
1814 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1815 finfo.size + strlen(cur_dir) + 1)
1817 free(inbuf); free(outbuf);
1821 buffer_p += TBLOCK; /* Skip that longlink header */
1823 /* This needs restructuring ... */
1825 if (buffer_p >= endofbuffer) {
1827 bufread = read(tarhandle, tarbuf, tbufsiz);
1833 strncpy(longname, cur_dir, strlen(cur_dir) + 1);
1834 unfixtarname(longname+strlen(cur_dir), buffer_p, finfo.size);
1835 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
1837 /* Next rounds up to next TBLOCK and takes care of us being right
1838 on a TBLOCK boundary */
1840 buffer_p += (((finfo.size - 1)/TBLOCK)+1)*TBLOCK;
1841 next_header = 1; /* Force read of next header */
1846 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1848 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1850 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1854 if (finfo.mode & aDIR)
1856 else if ((fsize=finfo.size) % TBLOCK) {
1857 fsize+=TBLOCK-(fsize%TBLOCK);
1859 if (fsize<endofbuffer-buffer_p) {
1864 fsize-=endofbuffer-buffer_p;
1869 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
1871 if (finfo.mode & aDIR)
1874 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1876 if (!ensurepath(finfo.name, inbuf, outbuf))
1878 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
1879 free(inbuf); free(outbuf);
1884 /* Now we update the creation date ... */
1886 DEBUG(0, ("Updating creation date on %s\n", finfo.name));
1888 if (!do_setrtime(finfo.name, finfo.mtime)) {
1890 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1903 if (ensurepath(finfo.name, inbuf, outbuf)
1904 && !smbcreat(finfo, &fnum, inbuf, outbuf))
1906 DEBUG(0, ("abandoning restore\n"));
1907 free(inbuf);free(outbuf);
1911 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
1912 finfo.name,finfo.size));
1914 /* if (!finfo.size) {
1915 if (!smbshut(finfo, fnum, inbuf, outbuf)){
1916 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
1917 free(inbuf);free(outbuf);
1923 if ((buffer_p+=TBLOCK) >= endofbuffer) break;
1926 /* write out the file in chunk sized chunks - don't
1927 * go past end of buffer though */
1928 chunk=(fsize-nread < endofbuffer - buffer_p)
1929 ? fsize - nread : endofbuffer - buffer_p;
1932 int minichunk=MIN(chunk, max_xmit-200);
1934 if (!smbwrite(fnum, /* file descriptor */
1936 nread, /* offset low */
1937 0, /* offset high - not implemented */
1938 fsize-nread, /* left - only hint to server */
1943 DEBUG(0, ("Error writing remote file\n"));
1944 free(inbuf); free(outbuf);
1947 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
1949 buffer_p+=minichunk; nread+=minichunk;
1955 if (!smbshut(finfo, fnum, inbuf, outbuf))
1957 DEBUG(0, ("Error closing remote file\n"));
1958 free(inbuf);free(outbuf);
1961 if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
1962 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
1963 (long) buffer_p, (long)(buffer_p - tarbuf)));
1968 } while (buffer_p < endofbuffer);
1971 DEBUG(0, ("premature eof on tar file ?\n"));
1972 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
1974 free(inbuf); free(outbuf);
1978 * samba interactive commands
1981 /****************************************************************************
1983 ***************************************************************************/
1984 void cmd_block(char *dum_in, char *dum_out)
1989 if (!next_token(NULL,buf,NULL))
1991 DEBUG(0, ("blocksize <n>\n"));
1996 if (block < 0 || block > 65535)
1998 DEBUG(0, ("blocksize out of range"));
2003 DEBUG(2,("blocksize is now %d\n", blocksize));
2006 /****************************************************************************
2007 command to set incremental / reset mode
2008 ***************************************************************************/
2009 void cmd_tarmode(char *dum_in, char *dum_out)
2013 while (next_token(NULL,buf,NULL)) {
2014 if (strequal(buf, "full"))
2016 else if (strequal(buf, "inc"))
2018 else if (strequal(buf, "reset"))
2020 else if (strequal(buf, "noreset"))
2022 else if (strequal(buf, "system"))
2024 else if (strequal(buf, "nosystem"))
2026 else if (strequal(buf, "hidden"))
2028 else if (strequal(buf, "nohidden"))
2030 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2032 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2034 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2037 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2038 tar_inc ? "incremental" : "full",
2039 tar_system ? "system" : "nosystem",
2040 tar_hidden ? "hidden" : "nohidden",
2041 tar_reset ? "reset" : "noreset",
2042 tar_noisy ? "verbose" : "quiet"));
2046 /****************************************************************************
2047 Feeble attrib command
2048 ***************************************************************************/
2049 void cmd_setmode(char *dum_in, char *dum_out)
2057 attra[0] = attra[1] = 0;
2059 if (!next_token(NULL,buf,NULL))
2061 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2065 pstrcpy(fname, cur_dir);
2066 pstrcat(fname, buf);
2068 while (next_token(NULL,buf,NULL)) {
2077 case 'r': attra[direct]|=aRONLY;
2079 case 'h': attra[direct]|=aHIDDEN;
2081 case 's': attra[direct]|=aSYSTEM;
2083 case 'a': attra[direct]|=aARCH;
2085 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2090 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2092 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2096 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2097 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2098 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2101 /****************************************************************************
2102 Principal command for creating / extracting
2103 ***************************************************************************/
2104 void cmd_tar(char *inbuf, char *outbuf)
2110 if (!next_token(NULL,buf,NULL))
2112 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
2116 argl=toktocliplist(&argcl, NULL);
2117 if (!tar_parseargs(argcl, argl, buf, 0))
2120 process_tar(inbuf, outbuf);
2125 /****************************************************************************
2126 Command line (option) version
2127 ***************************************************************************/
2128 int process_tar(char *inbuf, char *outbuf)
2144 if (clipn && tar_excl) {
2148 for (i=0; i<clipn; i++) {
2149 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2151 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2152 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2155 if (strrchr(cliplist[i], '\\')) {
2158 pstrcpy(saved_dir, cur_dir);
2160 if (*cliplist[i]=='\\') {
2161 pstrcpy(tarmac, cliplist[i]);
2163 pstrcpy(tarmac, cur_dir);
2164 pstrcat(tarmac, cliplist[i]);
2166 pstrcpy(cur_dir, tarmac);
2167 *(strrchr(cur_dir, '\\')+1)='\0';
2169 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2170 pstrcpy(cur_dir,saved_dir);
2172 pstrcpy(tarmac, cur_dir);
2173 pstrcat(tarmac, cliplist[i]);
2174 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2179 pstrcpy(mask,cur_dir);
2180 pstrcat(mask,"\\*");
2181 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2184 if (ntarf) dotareof(tarhandle);
2188 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2189 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2196 /****************************************************************************
2197 Find a token (filename) in a clip list
2198 ***************************************************************************/
2199 int clipfind(char **aret, int ret, char *tok)
2201 if (aret==NULL) return 0;
2203 /* ignore leading slashes or dots in token */
2204 while(strchr("/\\.", *tok)) tok++;
2209 /* ignore leading slashes or dots in list */
2210 while(strchr("/\\.", *pkey)) pkey++;
2212 if (!strslashcmp(pkey, tok)) return 1;
2218 /****************************************************************************
2219 Parse tar arguments. Sets tar_type, tar_excl, etc.
2220 ***************************************************************************/
2221 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2223 char tar_clipfl='\0';
2225 /* Reset back to defaults - could be from interactive version
2226 * reset mode and archive mode left as they are though
2237 if (tar_type=='c') {
2238 printf("Tar must be followed by only one of c or x.\n");
2244 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2245 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2256 DEBUG(0,("Option N must be followed by valid file name\n"));
2260 extern time_t newer_than;
2262 if (sys_stat(argv[Optind], &stbuf) == 0) {
2263 newer_than = stbuf.st_mtime;
2264 DEBUG(1,("Getting files newer than %s",
2265 asctime(LocalTime(&newer_than))));
2268 DEBUG(0,("Error setting newer-than time\n"));
2278 DEBUG(0,("Only one of I,X must be specified\n"));
2285 DEBUG(0,("Only one of I,X must be specified\n"));
2291 DEBUG(0, ("tar_re_search set\n"));
2292 tar_re_search = True;
2295 DEBUG(0,("Unknown tar option\n"));
2300 printf("Option T must be followed by one of c or x.\n");
2304 tar_excl=tar_clipfl!='X';
2306 if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2311 cliplist=argv+Optind+1;
2312 clipn=argc-Optind-1;
2315 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2316 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2322 for (clipcount = 0; clipcount < clipn; clipcount++) {
2324 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2326 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2327 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2332 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1);
2333 tmplist[clipcount] = tmpstr;
2334 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2336 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2341 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2345 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2347 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2352 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2356 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2358 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2364 clipn=argc-Optind-1;
2365 cliplist=argv+Optind+1;
2369 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2370 /* Sets tar handle to either 0 or 1, as appropriate */
2371 tarhandle=(tar_type=='c');
2373 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2374 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2376 DEBUG(0,("Error opening local file %s - %s\n",
2377 argv[Optind], strerror(errno)));