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
45 typedef struct file_info_struct file_info2;
47 struct file_info_struct
53 /* These times are normally kept in GMT */
57 char *name; /* This is dynamically allocate */
59 file_info2 *next, *prev; /* Used in the stack ... */
70 stack dir_stack = {NULL, 0}; /* Want an empty stack */
74 #define SEPARATORS " \t\n\r"
75 extern int DEBUGLEVEL;
78 /* These defines are for the do_setrattr routine, to indicate
79 * setting and reseting of file attributes in the function call */
83 static int attribute = aDIR | aSYSTEM | aHIDDEN;
85 #ifndef CLIENT_TIMEOUT
86 #define CLIENT_TIMEOUT (30*1000)
90 static int tp, ntarf, tbufsiz, ttarf;
91 /* Incremental mode */
93 /* Reset archive bit */
95 /* Include / exclude mode (true=include, false=exclude) */
97 /* use regular expressions for search on file names */
98 BOOL tar_re_search=False;
102 /* Dump files with System attribute */
103 BOOL tar_system=False;
104 /* Dump files with Hidden attribute */
105 BOOL tar_hidden=True;
106 /* Be noisy - make a catalogue */
110 static char **cliplist=NULL;
113 extern file_info def_finfo;
114 extern BOOL lowercase;
116 extern BOOL readbraw_supported;
118 extern pstring cur_dir;
119 extern int get_total_time_ms;
120 extern int get_total_size;
126 static void writetarheader(int f, char *aname, int size, time_t mtime,
127 char *amode, unsigned char ftype);
128 static void do_atar();
129 static void do_tar();
130 static void oct_it(long value, int ndgs, char *p);
131 static void fixtarname(char *tptr, char *fp, int l);
132 static int dotarbuf(int f, char *b, int n);
133 static void dozerobuf();
134 static void dotareof();
135 static void initarbuf();
136 static int do_setrattr();
138 /* restore functions */
139 static long readtarheader();
140 static long unoct(char *p, int ndgs);
141 static void do_tarput();
142 static void unfixtarname(char *tptr, char *fp, int l);
145 * tar specific utitlities
149 * Stack routines, push_dir, pop_dir, top_dir_name
152 static BOOL push_dir(stack *dir_stack, file_info2 *dir)
154 dir -> next = dir_stack -> top;
156 dir_stack -> items++;
157 dir_stack -> top = dir;
162 static file_info2 *pop_dir(stack *dir_stack)
166 ptr = dir_stack -> top;
167 if (dir_stack -> top != NULL) {
169 dir_stack -> top = dir_stack -> top -> next;
170 dir_stack -> items--;
178 static char *top_dir_name(stack *dir_stack)
181 return(dir_stack -> top != NULL?dir_stack -> top -> name:NULL);
185 static BOOL sub_dir(char *dir1, char *dir2)
190 /* Create a string of size size+1 (for the null) */
191 static char * string_create_s(int size)
195 tmp = (char *)malloc(size+1);
199 DEBUG(0, ("Out of memory in string_create_s\n"));
207 /****************************************************************************
208 Write a tar header to buffer
209 ****************************************************************************/
210 static void writetarheader(int f, char *aname, int size, time_t mtime,
211 char *amode, unsigned char ftype)
217 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
219 memset(hb.dummy, 0, sizeof(hb.dummy));
223 /* write a GNU tar style long header */
225 b = (char *)malloc(l+TBLOCK+100);
227 DEBUG(0,("out of memory\n"));
230 writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L');
231 memset(b, 0, l+TBLOCK+100);
232 fixtarname(b, aname, l+1);
234 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
235 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
239 /* use l + 1 to do the null too */
240 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
243 strlower(hb.dbuf.name);
245 /* write out a "standard" tar format header */
247 hb.dbuf.name[NAMSIZ-1]='\0';
248 strcpy(hb.dbuf.mode, amode);
249 oct_it(0L, 8, hb.dbuf.uid);
250 oct_it(0L, 8, hb.dbuf.gid);
251 oct_it((long) size, 13, hb.dbuf.size);
252 oct_it((long) mtime, 13, hb.dbuf.mtime);
253 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
254 memset(hb.dbuf.linkname, 0, NAMSIZ);
255 hb.dbuf.linkflag=ftype;
257 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
259 oct_it((long) chk, 8, hb.dbuf.chksum);
260 hb.dbuf.chksum[6] = '\0';
262 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
265 /****************************************************************************
266 Read a tar header into a hblock structure, and validate
267 ***************************************************************************/
268 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
275 * read in a "standard" tar format header - we're not that interested
276 * in that many fields, though
279 /* check the checksum */
280 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
285 /* compensate for blanks in chksum header */
286 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
289 chk += ' ' * sizeof(hb->dbuf.chksum);
291 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
293 DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
294 chk, fchk, hb->dbuf.chksum));
298 DEBUG(0, ("checksums don't match %d %d\n", fchk, chk));
302 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
304 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
309 strcpy(finfo->name, prefix);
311 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
312 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
313 strlen(hb->dbuf.name) + 1);
315 /* can't handle some links at present */
316 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
317 if (hb->dbuf.linkflag == 0) {
318 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
321 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
322 /* Do nothing here at the moment. do_tarput will handle this
323 as long as the longlink gets back to it, as it has to advance
324 the buffer pointer, etc */
327 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
333 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
334 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
339 finfo->mode=0; /* we don't care about mode at the moment, we'll
340 * just make it a regular file */
342 * Bug fix by richard@sj.co.uk
344 * REC: restore times correctly (as does tar)
345 * We only get the modification time of the file; set the creation time
346 * from the mod. time, and the access time to current time
348 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
349 finfo->atime = time(NULL);
350 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
355 /****************************************************************************
356 Write out the tar buffer to tape or wherever
357 ****************************************************************************/
358 static int dotarbuf(int f, char *b, int n)
362 /* This routine and the next one should be the only ones that do write()s */
363 if (tp + n >= tbufsiz)
368 memcpy(tarbuf + tp, b, diff);
369 fail=fail && (1+write(f, tarbuf, tbufsiz));
376 fail=fail && (1 + write(f, b, tbufsiz));
382 memcpy(tarbuf+tp, b, n);
386 return(fail ? writ : 0);
389 /****************************************************************************
390 Write zeros to buffer / tape
391 ****************************************************************************/
392 static void dozerobuf(int f, int n)
394 /* short routine just to write out n zeros to buffer -
395 * used to round files to nearest block
396 * and to do tar EOFs */
400 memset(tarbuf+tp, 0, tbufsiz-tp);
402 write(f, tarbuf, tbufsiz);
403 memset(tarbuf, 0, (tp+=n-tbufsiz));
407 memset(tarbuf+tp, 0, n);
412 /****************************************************************************
414 ****************************************************************************/
415 static void initarbuf()
417 /* initialize tar buffer */
418 tbufsiz=blocksize*TBLOCK;
419 tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */
421 /* reset tar buffer pointer and tar file counter and total dumped */
422 tp=0; ntarf=0; ttarf=0;
425 /****************************************************************************
426 Write two zero blocks at end of file
427 ****************************************************************************/
428 static void dotareof(int f)
431 /* Two zero blocks at end of file, write out full buffer */
433 (void) dozerobuf(f, TBLOCK);
434 (void) dozerobuf(f, TBLOCK);
436 if (fstat(f, &stbuf) == -1)
438 DEBUG(0, ("Couldn't stat file handle\n"));
442 /* Could be a pipe, in which case S_ISREG should fail,
443 * and we should write out at full size */
444 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
447 /****************************************************************************
448 (Un)mangle DOS pathname, make nonabsolute
449 ****************************************************************************/
450 static void fixtarname(char *tptr, char *fp, int l)
452 /* add a '.' to start of file name, convert from ugly dos \'s in path
453 * to lovely unix /'s :-} */
459 if((skip = skip_multibyte_char( *fp)) != 0) {
464 } else if (skip == 1) {
468 } else if (*fp == '\\') {
479 /****************************************************************************
480 Convert from decimal to octal string
481 ****************************************************************************/
482 static void oct_it (long value, int ndgs, char *p)
484 /* Converts long to octal string, pads with leading zeros */
486 /* skip final null, but do final space */
490 /* Loop does at least one digit */
492 p[--ndgs] = '0' + (char) (value & 7);
495 while (ndgs > 0 && value != 0);
497 /* Do leading zeros */
502 /****************************************************************************
503 Convert from octal string to long
504 ***************************************************************************/
505 static long unoct(char *p, int ndgs)
508 /* Converts octal string to long, ignoring any non-digit */
513 value = (value << 3) | (long) (*p - '0');
521 /****************************************************************************
522 Compare two strings in a slash insensitive way, allowing s1 to match s2
523 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
524 a file in any subdirectory of s1, declare a match.
525 ***************************************************************************/
526 static int strslashcmp(char *s1, char *s2)
532 || tolower(*s1) == tolower(*s2)
533 || (*s1 == '\\' && *s2=='/')
534 || (*s1 == '/' && *s2=='\\'))) {
538 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
541 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
543 /* ignore trailing slash on s1 */
544 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
546 /* check for s1 is an "initial" string of s2 */
547 if (*s2 == '/' || *s2 == '\\') return 0;
553 * general smb utility functions
555 /**********************************************************************
556 do_setrtime, set time on a file or dir ...
557 **********************************************************************/
559 static int do_setrtime(char *fname, int mtime)
561 char *inbuf, *outbuf, *p;
564 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
566 name = (char *)malloc(strlen(fname) + 1 + 1);
569 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
578 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
579 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
581 if (!inbuf || !outbuf) {
583 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
588 memset(outbuf, 0, smb_size);
589 set_message(outbuf, 8, 4 + strlen(fname), True);
590 CVAL(outbuf, smb_com) = SMBsetatr;
591 SSVAL(outbuf, smb_tid, cnum);
592 cli_setup_pkt(outbuf);
594 SSVAL(outbuf, smb_vwv0, 0);
595 put_dos_date3(outbuf, smb_vwv1, mtime);
600 p+= (strlen(fname)+1);
605 send_smb(Client, outbuf);
606 client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
608 if (CVAL(inbuf,smb_rcls) != 0)
610 DEBUG(0,("%s setting attributes on file %s\n",
611 smb_errstr(inbuf), fname));
612 free(inbuf);free(outbuf);
616 free(inbuf);free(outbuf);
621 /****************************************************************************
622 Set DOS file attributes
623 ***************************************************************************/
624 static int do_setrattr(char *fname, int attr, int setit)
627 * First get the existing attribs from existing file
638 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
639 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
641 if (!inbuf || !outbuf)
643 DEBUG(0,("out of memory\n"));
647 /* send an smb getatr message */
649 memset(outbuf,0,smb_size);
650 set_message(outbuf,0,2 + strlen(fname),True);
651 CVAL(outbuf,smb_com) = SMBgetatr;
652 SSVAL(outbuf,smb_tid,cnum);
653 cli_setup_pkt(outbuf);
658 p += (strlen(fname)+1);
663 send_smb(Client,outbuf);
664 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
666 if (CVAL(inbuf,smb_rcls) != 0)
667 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
670 DEBUG(5,("\nattr 0x%X time %d size %d\n",
671 (int)CVAL(inbuf,smb_vwv0),
672 SVAL(inbuf,smb_vwv1),
673 SVAL(inbuf,smb_vwv3)));
676 fattr=CVAL(inbuf,smb_vwv0);
678 /* combine found attributes with bits to be set or reset */
680 attr=setit ? (fattr | attr) : (fattr & ~attr);
682 /* now try and set attributes by sending smb reset message */
684 /* clear out buffer and start again */
685 memset(outbuf,0,smb_size);
686 set_message(outbuf,8,4 + strlen(fname),True);
687 CVAL(outbuf,smb_com) = SMBsetatr;
688 SSVAL(outbuf,smb_tid,cnum);
689 cli_setup_pkt(outbuf);
691 SSVAL(outbuf,smb_vwv0,attr);
696 p += (strlen(fname)+1);
701 send_smb(Client,outbuf);
702 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
704 if (CVAL(inbuf,smb_rcls) != 0)
706 DEBUG(0,("%s setting attributes on file %s\n",
707 smb_errstr(inbuf), fname));
708 free(inbuf);free(outbuf);
712 free(inbuf);free(outbuf);
716 /****************************************************************************
717 Create a file on a share
718 ***************************************************************************/
719 static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
722 /* *must* be called with buffer ready malloc'ed */
723 /* open remote file */
725 memset(outbuf,0,smb_size);
726 set_message(outbuf,3,2 + strlen(finfo.name),True);
727 CVAL(outbuf,smb_com) = SMBcreate;
728 SSVAL(outbuf,smb_tid,cnum);
729 cli_setup_pkt(outbuf);
731 SSVAL(outbuf,smb_vwv0,finfo.mode);
732 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
736 strcpy(p,finfo.name);
738 send_smb(Client,outbuf);
739 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
741 if (CVAL(inbuf,smb_rcls) != 0)
743 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
748 *fnum = SVAL(inbuf,smb_vwv0);
752 /****************************************************************************
753 Write a file to a share
754 ***************************************************************************/
755 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
756 char *bufferp, char *inbuf, char *outbuf)
758 /* *must* be called with buffer ready malloc'ed */
760 memset(outbuf,0,smb_size);
761 set_message(outbuf,5,n + 3,True);
763 memcpy(smb_buf(outbuf)+3, bufferp, n);
765 set_message(outbuf,5,n + 3, False);
766 CVAL(outbuf,smb_com) = SMBwrite;
767 SSVAL(outbuf,smb_tid,cnum);
768 cli_setup_pkt(outbuf);
770 SSVAL(outbuf,smb_vwv0,fnum);
771 SSVAL(outbuf,smb_vwv1,n);
772 SIVAL(outbuf,smb_vwv2,low);
773 SSVAL(outbuf,smb_vwv4,left);
774 CVAL(smb_buf(outbuf),0) = 1;
775 SSVAL(smb_buf(outbuf),1,n);
777 send_smb(Client,outbuf);
778 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
780 if (CVAL(inbuf,smb_rcls) != 0)
782 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
786 if (n != SVAL(inbuf,smb_vwv0))
788 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
789 SVAL(inbuf,smb_vwv0), n));
796 /****************************************************************************
797 Close a file on a share
798 ***************************************************************************/
799 static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
801 /* *must* be called with buffer ready malloc'ed */
803 memset(outbuf,0,smb_size);
804 set_message(outbuf,3,0,True);
805 CVAL(outbuf,smb_com) = SMBclose;
806 SSVAL(outbuf,smb_tid,cnum);
807 cli_setup_pkt(outbuf);
809 SSVAL(outbuf,smb_vwv0,fnum);
810 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
812 DEBUG(3,("Setting date to %s (0x%X)",
813 asctime(LocalTime(&finfo.mtime)),
816 send_smb(Client,outbuf);
817 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
819 if (CVAL(inbuf,smb_rcls) != 0)
821 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
829 /****************************************************************************
830 Verify existence of path on share
831 ***************************************************************************/
832 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
836 memset(outbuf,0,smb_size);
837 set_message(outbuf,0,4 + strlen(fname),True);
838 CVAL(outbuf,smb_com) = SMBchkpth;
839 SSVAL(outbuf,smb_tid,cnum);
840 cli_setup_pkt(outbuf);
846 send_smb(Client,outbuf);
847 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
849 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
851 return(CVAL(inbuf,smb_rcls) == 0);
854 /****************************************************************************
855 Make a directory on share
856 ***************************************************************************/
857 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
859 /* *must* be called with buffer ready malloc'ed */
862 memset(outbuf,0,smb_size);
863 set_message(outbuf,0,2 + strlen(fname),True);
865 CVAL(outbuf,smb_com) = SMBmkdir;
866 SSVAL(outbuf,smb_tid,cnum);
867 cli_setup_pkt(outbuf);
873 send_smb(Client,outbuf);
874 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
876 if (CVAL(inbuf,smb_rcls) != 0)
878 DEBUG(0,("%s making remote directory %s\n",
879 smb_errstr(inbuf),fname));
886 /****************************************************************************
887 Ensure a remote path exists (make if necessary)
888 ***************************************************************************/
889 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
891 /* *must* be called with buffer ready malloc'ed */
892 /* ensures path exists */
894 char *partpath, *ffname;
895 char *p=fname, *basehack;
897 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
899 partpath = string_create_s(strlen(fname));
900 ffname = string_create_s(strlen(fname));
902 if ((partpath == NULL) || (ffname == NULL)){
904 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
911 /* fname copied to ffname so can strtok */
913 strcpy(ffname, fname);
915 /* do a `basename' on ffname, so don't try and make file name directory */
916 if ((basehack=strrchr(ffname, '\\')) == NULL)
921 p=strtok(ffname, "\\");
927 if (!smbchkpath(partpath, inbuf, outbuf)) {
928 if (!smbmkdir(partpath, inbuf, outbuf))
930 DEBUG(0, ("Error mkdirhiering\n"));
934 DEBUG(3, ("mkdirhiering %s\n", partpath));
938 strcat(partpath, "\\");
939 p = strtok(NULL,"/\\");
945 int padit(char *buf, int bufsize, int padsize)
950 DEBUG(5, ("Padding with %d zeros\n", padsize));
951 memset(buf, 0, bufsize);
952 while( !berr && padsize > 0 ) {
953 bytestowrite= MIN(bufsize, padsize);
954 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
955 padsize -= bytestowrite;
962 * smbclient functions
964 /****************************************************************************
965 append one remote file to the tar file
966 ***************************************************************************/
967 static void do_atar(char *rname,char *lname,file_info *finfo1)
974 BOOL close_done = False;
975 BOOL shallitime=True;
976 BOOL ignore_close_error = False;
980 struct timeval tp_start;
981 GetTimeOfDay(&tp_start);
983 ftype = '0'; /* An ordinary file ... */
990 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
991 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
993 if (!inbuf || !outbuf)
995 DEBUG(0,("out of memory\n"));
999 memset(outbuf,0,smb_size);
1000 set_message(outbuf,15,1 + strlen(rname),True);
1002 CVAL(outbuf,smb_com) = SMBopenX;
1003 SSVAL(outbuf,smb_tid,cnum);
1004 cli_setup_pkt(outbuf);
1006 SSVAL(outbuf,smb_vwv0,0xFF);
1007 SSVAL(outbuf,smb_vwv2,1);
1008 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1009 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1010 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1011 SSVAL(outbuf,smb_vwv8,1);
1013 p = smb_buf(outbuf);
1015 p = skip_string(p,1);
1017 dos_clean_name(rname);
1019 /* do a chained openX with a readX? */
1022 SSVAL(outbuf,smb_vwv0,SMBreadX);
1023 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
1026 SSVAL(p,smb_wct,10);
1027 SSVAL(p,smb_vwv0,0xFF);
1028 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1029 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
1030 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1033 send_smb(Client,outbuf);
1034 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1036 if (CVAL(inbuf,smb_rcls) != 0)
1038 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1039 SVAL(inbuf,smb_err) == ERRnoresource &&
1040 cli_reopen_connection(inbuf,outbuf))
1042 do_atar(rname,lname,finfo1);
1043 free(inbuf);free(outbuf);
1047 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
1048 free(inbuf);free(outbuf);
1052 strcpy(finfo.name,rname);
1055 finfo.mode = SVAL(inbuf,smb_vwv3);
1056 finfo.size = IVAL(inbuf,smb_vwv4);
1057 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
1058 finfo.atime = finfo.ctime = finfo.mtime;
1061 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
1063 fnum = SVAL(inbuf,smb_vwv2);
1065 if (tar_inc && !(finfo.mode & aARCH))
1067 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
1070 else if (!tar_system && (finfo.mode & aSYSTEM))
1072 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
1075 else if (!tar_hidden && (finfo.mode & aHIDDEN))
1077 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
1082 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1084 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
1085 datalen = SVAL(p,smb_vwv5);
1086 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
1094 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1099 /* write a tar header, don't bother with mode - just set to 100644 */
1100 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
1102 while (nread < finfo.size && !close_done)
1105 static BOOL can_chain_close=True;
1109 DEBUG(3,("nread=%d\n",nread));
1111 /* 3 possible read types. readbraw if a large block is required.
1112 readX + close if not much left and read if neither is supported */
1114 /* we might have already read some data from a chained readX */
1115 if (dataptr && datalen>0)
1118 /* if we can finish now then readX+close */
1119 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1120 ((finfo.size - nread) <
1121 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1124 /* if we support readraw then use that */
1125 if (method<0 && readbraw_supported)
1128 /* if we can then use readX */
1129 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1141 /* use readX + close */
1142 memset(outbuf,0,smb_size);
1143 set_message(outbuf,10,0,True);
1144 CVAL(outbuf,smb_com) = SMBreadX;
1145 SSVAL(outbuf,smb_tid,cnum);
1146 cli_setup_pkt(outbuf);
1150 CVAL(outbuf,smb_vwv0) = SMBclose;
1151 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
1154 CVAL(outbuf,smb_vwv0) = 0xFF;
1157 SSVAL(outbuf,smb_vwv2,fnum);
1158 SIVAL(outbuf,smb_vwv3,nread);
1159 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1160 SSVAL(outbuf,smb_vwv6,0);
1161 SIVAL(outbuf,smb_vwv7,0);
1162 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
1166 p = smb_buf(outbuf);
1173 /* now set the total packet length */
1174 smb_setlen(outbuf,smb_len(outbuf)+9);
1177 send_smb(Client,outbuf);
1178 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1180 if (CVAL(inbuf,smb_rcls) != 0)
1182 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1187 SVAL(inbuf,smb_vwv0) != SMBclose)
1189 /* NOTE: WfWg sometimes just ignores the chained
1190 command! This seems to break the spec? */
1191 DEBUG(3,("Rejected chained close?\n"));
1193 can_chain_close = False;
1194 ignore_close_error = True;
1197 datalen = SVAL(inbuf,smb_vwv5);
1198 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
1205 static int readbraw_size = 0xFFFF;
1208 memset(outbuf,0,smb_size);
1209 set_message(outbuf,8,0,True);
1210 CVAL(outbuf,smb_com) = SMBreadbraw;
1211 SSVAL(outbuf,smb_tid,cnum);
1212 cli_setup_pkt(outbuf);
1213 SSVAL(outbuf,smb_vwv0,fnum);
1214 SIVAL(outbuf,smb_vwv1,nread);
1215 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1216 SSVAL(outbuf,smb_vwv4,0);
1217 SIVALS(outbuf,smb_vwv5,-1);
1218 send_smb(Client,outbuf);
1220 /* Now read the raw data into the buffer and write it */
1221 if(read_smb_length(Client,inbuf,0) == -1) {
1222 DEBUG(0,("Failed to read length in readbraw\n"));
1226 /* Even though this is not an smb message, smb_len
1227 returns the generic length of an smb message */
1228 datalen = smb_len(inbuf);
1232 /* we got a readbraw error */
1233 DEBUG(4,("readbraw error - reducing size\n"));
1234 readbraw_size = (readbraw_size * 9) / 10;
1236 if (readbraw_size < max_xmit)
1238 DEBUG(0,("disabling readbraw\n"));
1239 readbraw_supported = False;
1246 if(read_data(Client,inbuf,datalen) != datalen) {
1247 DEBUG(0,("Failed to read data in readbraw\n"));
1255 /* we've already read some data with a chained readX */
1259 /* use plain read */
1260 memset(outbuf,0,smb_size);
1261 set_message(outbuf,5,0,True);
1262 CVAL(outbuf,smb_com) = SMBread;
1263 SSVAL(outbuf,smb_tid,cnum);
1264 cli_setup_pkt(outbuf);
1266 SSVAL(outbuf,smb_vwv0,fnum);
1267 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1268 SIVAL(outbuf,smb_vwv2,nread);
1269 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1271 send_smb(Client,outbuf);
1272 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1274 if (CVAL(inbuf,smb_rcls) != 0)
1276 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1280 datalen = SVAL(inbuf,smb_vwv0);
1281 dataptr = smb_buf(inbuf) + 3;
1286 /* add received bits of file to buffer - dotarbuf will
1287 * write out in 512 byte intervals */
1288 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1290 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
1297 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1305 /* pad tar file with zero's if we couldn't get entire file */
1306 if (nread < finfo.size)
1308 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
1309 if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
1310 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
1313 /* round tar file to nearest block */
1314 if (finfo.size % TBLOCK)
1315 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1317 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1323 memset(outbuf,0,smb_size);
1324 set_message(outbuf,3,0,True);
1325 CVAL(outbuf,smb_com) = SMBclose;
1326 SSVAL(outbuf,smb_tid,cnum);
1327 cli_setup_pkt(outbuf);
1329 SSVAL(outbuf,smb_vwv0,fnum);
1330 SIVALS(outbuf,smb_vwv1,-1);
1332 send_smb(Client,outbuf);
1333 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1335 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1337 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1338 free(inbuf);free(outbuf);
1345 struct timeval tp_end;
1348 /* if shallitime is true then we didn't skip */
1349 if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1351 GetTimeOfDay(&tp_end);
1353 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1354 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1355 get_total_time_ms += this_time;
1356 get_total_size += finfo.size;
1358 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1359 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1360 finfo.size / MAX(0.001, (1.024*this_time)),
1361 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1364 printf("%10d (%7.1f kb/s) %s\n",
1365 finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
1371 free(inbuf);free(outbuf);
1374 /****************************************************************************
1375 Append single file to tar file (or not)
1376 ***************************************************************************/
1377 static void do_tar(file_info *finfo)
1381 if (strequal(finfo->name,".."))
1384 /* Is it on the exclude list ? */
1385 if (!tar_excl && clipn) {
1388 strcpy(exclaim, cur_dir);
1389 *(exclaim+strlen(exclaim)-1)='\0';
1391 strcat(exclaim, "\\");
1392 strcat(exclaim, finfo->name);
1394 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
1396 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
1398 (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
1400 (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
1402 DEBUG(3,("Skipping file %s\n", exclaim));
1407 if (finfo->mode & aDIR)
1409 pstring saved_curdir;
1411 char *inbuf,*outbuf;
1413 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1414 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1416 if (!inbuf || !outbuf)
1418 DEBUG(0,("out of memory\n"));
1422 strcpy(saved_curdir,cur_dir);
1424 strcat(cur_dir,finfo->name);
1425 strcat(cur_dir,"\\");
1427 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
1429 /* write a tar directory, don't bother with mode - just set it to
1431 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
1432 ntarf++; /* Make sure we have a file on there */
1433 strcpy(mtar_mask,cur_dir);
1434 strcat(mtar_mask,"*");
1435 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1436 strcpy(cur_dir,saved_curdir);
1437 free(inbuf);free(outbuf);
1441 strcpy(rname,cur_dir);
1442 strcat(rname,finfo->name);
1443 do_atar(rname,finfo->name,finfo);
1447 /****************************************************************************
1448 Convert from UNIX to DOS file names
1449 ***************************************************************************/
1450 static void unfixtarname(char *tptr, char *fp, int l)
1452 /* remove '.' from start of file name, convert from unix /'s to
1453 * dos \'s in path. Kill any absolute path names.
1456 if (*fp == '.') fp++;
1457 if (*fp == '\\' || *fp == '/') fp++;
1461 if(( skip = skip_multibyte_char( *fp )) != 0) {
1466 } else if (skip == 1) {
1470 } else if (*fp == '/') {
1481 /****************************************************************************
1482 Move to the next block in the buffer, which may mean read in another set of
1484 ****************************************************************************/
1485 static int next_block(char *tarbuf, char *bufferp, int bufsiz)
1487 int bufread, total = 0;
1489 if (bufferp >= (tarbuf + bufsiz)) {
1491 for (bufread = read(tarhandle, tarbuf, bufsiz); total += bufread; total < bufsiz) {
1493 if (bufread <= 0) { /* An error, return false */
1494 return (total > 0 ? -2 : bufread);
1510 static int skip_file()
1515 static int get_file(file_info2 finfo)
1521 static int get_dir(file_info2 finfo)
1526 static char * get_longfilename(file_info2 finfo)
1531 static char * bufferp;
1533 static void do_tarput2()
1536 struct timeval tp_start;
1537 char *inbuf, *outbuf, *longfilename = NULL;
1540 GetTimeOfDay(&tp_start);
1542 bufferp = tarbuf + tbufsiz; /* init this to force first read */
1544 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1545 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1547 if (!inbuf || !outbuf) {
1549 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1554 if (next_block(tarbuf, bufferp, tbufsiz) <= 0) {
1556 DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno)));
1560 /* Now read through those files ... */
1564 switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) {
1566 case -2: /* Hmm, not good, but not fatal */
1567 DEBUG(0, ("Skipping %s...\n", finfo.name));
1568 if ((next_block(tarbuf, bufferp, tbufsiz) <= 0) &&
1569 !skip_file(finfo.size)) {
1571 DEBUG(0, ("Short file, bailing out...\n"));
1572 free(inbuf); free(outbuf);
1580 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1581 free(inbuf); free(outbuf);
1584 case 0: /* chksum is zero - looks like an EOF */
1585 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1586 free(inbuf); free(outbuf);
1587 return; /* Hmmm, bad here ... */
1594 /* Now, do we have a long file name? */
1596 if (longfilename != NULL) {
1597 if (strlen(longfilename) < sizeof(finfo.name)) { /* if we have space */
1599 strncpy(finfo.name, longfilename, sizeof(finfo.name) - 1);
1601 longfilename = NULL;
1606 DEBUG(0, ("filename: %s too long, skipping\n", strlen(longfilename)));
1612 /* Well, now we have a header, process the file ... */
1614 /* Should we skip the file? */
1623 /* We only get this far if we should process the file */
1625 switch (((union hblock *)bufferp) -> dbuf.linkflag) {
1627 case '0': /* Should use symbolic names--FIXME */
1636 longfilename = get_longfilename(finfo);
1640 skip_file(finfo); /* Don't handle these yet */
1650 static void do_tarput()
1653 int nread=0, bufread;
1654 char *inbuf,*outbuf, *longname = NULL;
1657 struct timeval tp_start;
1658 BOOL tskip=False; /* We'll take each file as it comes */
1660 finfo.name = NULL; /* No name in here ... */
1662 GetTimeOfDay(&tp_start);
1664 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1665 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1667 if (!inbuf || !outbuf)
1669 DEBUG(0,("out of memory\n"));
1674 * Must read in tbufsiz dollops
1677 /* These should be the only reads in clitar.c */
1678 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1679 char *bufferp, *endofbuffer;
1682 /* Code to handle a short read.
1683 * We always need a TBLOCK full of stuff
1685 if (bufread % TBLOCK) {
1686 int lchunk=TBLOCK-(bufread % TBLOCK);
1689 /* It's a shorty - a short read that is */
1690 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1692 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1694 if (!(lchunk-=lread)) break;
1697 /* If we've reached EOF then that must be a short file */
1698 if (lread<=0) break;
1702 endofbuffer=tarbuf+bufread;
1705 if (fsize<bufread) {
1710 if (fsize==bufread) tskip=False;
1719 int next_header = 1; /* Want at least one header */
1722 if (bufferp >= endofbuffer) {
1724 bufread = read(tarhandle, tarbuf, tbufsiz);
1728 next_header = 0; /* Don't want the next one ... */
1730 if (finfo.name != NULL) { /* Free the space */
1736 switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir))
1738 case -2: /* something dodgy but not fatal about this */
1739 DEBUG(0, ("skipping %s...\n", finfo.name));
1740 bufferp+=TBLOCK; /* header - like a link */
1743 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
1744 free(inbuf); free(outbuf);
1746 case 0: /* chksum is zero - we assume that one all zero
1747 *header block will do for eof */
1749 ("total of %d tar files restored to share\n", ntarf));
1750 free(inbuf); free(outbuf);
1756 /* If we have a longname left from the last time through,
1757 copy it into finfo.name and free it.
1759 The size of a pstring is the limiting factor on filenames
1760 and directory names now. The total pathname length must be
1761 less than sizeof(pstring) - 1, which is currently 1023. */
1763 if (longname != NULL) {
1765 free(finfo.name); /* Free the name in the finfo */
1766 finfo.name = string_create_s(strlen(longname) + 2);
1767 strncpy(finfo.name, longname, strlen(longname) + 1);
1768 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
1774 /* Check if a long-link. We do this before the clip checking
1775 because clip-checking should clip on real name - RJS */
1777 if (((union hblock *)bufferp) -> dbuf.linkflag == 'L') {
1779 /* Skip this header, but pick up length, get the name and
1780 fix the name and skip the name. Hmmm, what about end of
1783 DEBUG(5, ("Buffer size = %i\n", finfo.size + strlen(cur_dir) +1));
1784 longname = malloc(finfo.size + strlen(cur_dir) + 1);
1785 if (longname == NULL) {
1787 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1788 finfo.size + strlen(cur_dir) + 1)
1790 free(inbuf); free(outbuf);
1794 bufferp += TBLOCK; /* Skip that longlink header */
1796 /* This needs restructuring ... */
1798 if (bufferp >= endofbuffer) {
1800 bufread = read(tarhandle, tarbuf, tbufsiz);
1806 strncpy(longname, cur_dir, strlen(cur_dir) + 1);
1807 unfixtarname(longname+strlen(cur_dir), bufferp, finfo.size);
1808 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, bufferp));
1810 /* Next rounds up to next TBLOCK and takes care of us being right
1811 on a TBLOCK boundary */
1813 bufferp += (((finfo.size - 1)/TBLOCK)+1)*TBLOCK;
1814 next_header = 1; /* Force read of next header */
1819 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1821 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1823 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1827 if (finfo.mode & aDIR)
1829 else if ((fsize=finfo.size) % TBLOCK) {
1830 fsize+=TBLOCK-(fsize%TBLOCK);
1832 if (fsize<endofbuffer-bufferp) {
1837 fsize-=endofbuffer-bufferp;
1842 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
1844 if (finfo.mode & aDIR)
1847 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1849 if (!ensurepath(finfo.name, inbuf, outbuf))
1851 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
1852 free(inbuf); free(outbuf);
1857 /* Now we update the creation date ... */
1859 DEBUG(0, ("Updating creation date on %s\n", finfo.name));
1861 if (!do_setrtime(finfo.name, finfo.mtime)) {
1863 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1876 if (ensurepath(finfo.name, inbuf, outbuf)
1877 && !smbcreat(finfo, &fnum, inbuf, outbuf))
1879 DEBUG(0, ("abandoning restore\n"));
1880 free(inbuf);free(outbuf);
1884 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
1885 finfo.name,finfo.size));
1887 /* if (!finfo.size) {
1888 if (!smbshut(finfo, fnum, inbuf, outbuf)){
1889 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
1890 free(inbuf);free(outbuf);
1896 if ((bufferp+=TBLOCK) >= endofbuffer) break;
1899 /* write out the file in chunk sized chunks - don't
1900 * go past end of buffer though */
1901 chunk=(fsize-nread < endofbuffer - bufferp)
1902 ? fsize - nread : endofbuffer - bufferp;
1905 int minichunk=MIN(chunk, max_xmit-200);
1907 if (!smbwrite(fnum, /* file descriptor */
1909 nread, /* offset low */
1910 0, /* offset high - not implemented */
1911 fsize-nread, /* left - only hint to server */
1916 DEBUG(0, ("Error writing remote file\n"));
1917 free(inbuf); free(outbuf);
1920 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
1922 bufferp+=minichunk; nread+=minichunk;
1928 if (!smbshut(finfo, fnum, inbuf, outbuf))
1930 DEBUG(0, ("Error closing remote file\n"));
1931 free(inbuf);free(outbuf);
1934 if (fsize % TBLOCK) bufferp+=TBLOCK - (fsize % TBLOCK);
1935 DEBUG(5, ("bufferp is now %d (psn=%d)\n",
1936 (long) bufferp, (long)(bufferp - tarbuf)));
1941 } while (bufferp < endofbuffer);
1944 DEBUG(0, ("premature eof on tar file ?\n"));
1945 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
1947 free(inbuf); free(outbuf);
1951 * samba interactive commands
1954 /****************************************************************************
1956 ***************************************************************************/
1957 void cmd_block(char *dum_in, char *dum_out)
1962 if (!next_token(NULL,buf,NULL))
1964 DEBUG(0, ("blocksize <n>\n"));
1969 if (block < 0 || block > 65535)
1971 DEBUG(0, ("blocksize out of range"));
1976 DEBUG(2,("blocksize is now %d\n", blocksize));
1979 /****************************************************************************
1980 command to set incremental / reset mode
1981 ***************************************************************************/
1982 void cmd_tarmode(char *dum_in, char *dum_out)
1986 while (next_token(NULL,buf,NULL)) {
1987 if (strequal(buf, "full"))
1989 else if (strequal(buf, "inc"))
1991 else if (strequal(buf, "reset"))
1993 else if (strequal(buf, "noreset"))
1995 else if (strequal(buf, "system"))
1997 else if (strequal(buf, "nosystem"))
1999 else if (strequal(buf, "hidden"))
2001 else if (strequal(buf, "nohidden"))
2003 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2005 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2007 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2010 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2011 tar_inc ? "incremental" : "full",
2012 tar_system ? "system" : "nosystem",
2013 tar_hidden ? "hidden" : "nohidden",
2014 tar_reset ? "reset" : "noreset",
2015 tar_noisy ? "verbose" : "quiet"));
2019 /****************************************************************************
2020 Feeble attrib command
2021 ***************************************************************************/
2022 void cmd_setmode(char *dum_in, char *dum_out)
2030 attra[0] = attra[1] = 0;
2032 if (!next_token(NULL,buf,NULL))
2034 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2038 strcpy(fname, cur_dir);
2041 while (next_token(NULL,buf,NULL)) {
2050 case 'r': attra[direct]|=aRONLY;
2052 case 'h': attra[direct]|=aHIDDEN;
2054 case 's': attra[direct]|=aSYSTEM;
2056 case 'a': attra[direct]|=aARCH;
2058 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2063 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2065 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2069 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2070 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2071 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2074 /****************************************************************************
2075 Principal command for creating / extracting
2076 ***************************************************************************/
2077 void cmd_tar(char *inbuf, char *outbuf)
2083 if (!next_token(NULL,buf,NULL))
2085 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
2089 argl=toktocliplist(&argcl, NULL);
2090 if (!tar_parseargs(argcl, argl, buf, 0))
2093 process_tar(inbuf, outbuf);
2098 /****************************************************************************
2099 Command line (option) version
2100 ***************************************************************************/
2101 int process_tar(char *inbuf, char *outbuf)
2112 if (clipn && tar_excl) {
2116 for (i=0; i<clipn; i++) {
2117 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2119 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2120 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2123 if (strrchr(cliplist[i], '\\')) {
2126 strcpy(saved_dir, cur_dir);
2128 if (*cliplist[i]=='\\') {
2129 strcpy(tarmac, cliplist[i]);
2131 strcpy(tarmac, cur_dir);
2132 strcat(tarmac, cliplist[i]);
2134 strcpy(cur_dir, tarmac);
2135 *(strrchr(cur_dir, '\\')+1)='\0';
2137 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2138 strcpy(cur_dir,saved_dir);
2140 strcpy(tarmac, cur_dir);
2141 strcat(tarmac, cliplist[i]);
2142 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2147 strcpy(mask,cur_dir);
2149 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2152 if (ntarf) dotareof(tarhandle);
2156 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2157 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2164 /****************************************************************************
2165 Find a token (filename) in a clip list
2166 ***************************************************************************/
2167 int clipfind(char **aret, int ret, char *tok)
2169 if (aret==NULL) return 0;
2171 /* ignore leading slashes or dots in token */
2172 while(strchr("/\\.", *tok)) tok++;
2177 /* ignore leading slashes or dots in list */
2178 while(strchr("/\\.", *pkey)) pkey++;
2180 if (!strslashcmp(pkey, tok)) return 1;
2186 /****************************************************************************
2187 Parse tar arguments. Sets tar_type, tar_excl, etc.
2188 ***************************************************************************/
2189 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2191 char tar_clipfl='\0';
2193 /* Reset back to defaults - could be from interactive version
2194 * reset mode and archive mode left as they are though
2205 if (tar_type=='c') {
2206 printf("Tar must be followed by only one of c or x.\n");
2212 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2213 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2224 DEBUG(0,("Option N must be followed by valid file name\n"));
2228 extern time_t newer_than;
2230 if (sys_stat(argv[Optind], &stbuf) == 0) {
2231 newer_than = stbuf.st_mtime;
2232 DEBUG(1,("Getting files newer than %s",
2233 asctime(LocalTime(&newer_than))));
2236 DEBUG(0,("Error setting newer-than time\n"));
2246 DEBUG(0,("Only one of I,X must be specified\n"));
2253 DEBUG(0,("Only one of I,X must be specified\n"));
2259 DEBUG(0, ("tar_re_search set\n"));
2260 tar_re_search = True;
2263 DEBUG(0,("Unknown tar option\n"));
2268 printf("Option T must be followed by one of c or x.\n");
2272 tar_excl=tar_clipfl!='X';
2274 if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2279 cliplist=argv+Optind+1;
2280 clipn=argc-Optind-1;
2283 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2284 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2290 for (clipcount = 0; clipcount < clipn; clipcount++) {
2292 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2294 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2295 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2300 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1);
2301 tmplist[clipcount] = tmpstr;
2302 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2304 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2309 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2313 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2315 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2320 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2324 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2326 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2332 clipn=argc-Optind-1;
2333 cliplist=argv+Optind+1;
2337 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2338 /* Sets tar handle to either 0 or 1, as appropriate */
2339 tarhandle=(tar_type=='c');
2341 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2342 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2344 DEBUG(0,("Error opening local file %s - %s\n",
2345 argv[Optind], strerror(errno)));