2 Unix SMB/Netbios implementation.
5 Copyright (C) Ricky Poulten 1995-1998
6 Copyright (C) Richard Sharpe 1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* The following changes developed by Richard Sharpe for Canon Information
23 Systems Research Australia (CISRA)
25 1. Restore can now restore files with long file names
26 2. Save now saves directory information so that we can restore
27 directory creation times
28 3. tar now accepts both UNIX path names and DOS path names. I prefer
29 those lovely /'s to those UGLY \'s :-)
30 4. the files to exclude can be specified as a regular expression by adding
31 an r flag to the other tar flags. Eg:
33 -TcrX file.tar "*.(obj|exe)"
35 will skip all .obj and .exe files
42 static int clipfind(char **aret, int ret, char *tok);
44 typedef struct file_info_struct file_info2;
46 struct file_info_struct
52 /* These times are normally kept in GMT */
56 char *name; /* This is dynamically allocate */
58 file_info2 *next, *prev; /* Used in the stack ... */
69 stack dir_stack = {NULL, 0}; /* Want an empty stack */
73 #define SEPARATORS " \t\n\r"
74 extern int DEBUGLEVEL;
77 /* These defines are for the do_setrattr routine, to indicate
78 * setting and reseting of file attributes in the function call */
82 static int attribute = aDIR | aSYSTEM | aHIDDEN;
84 #ifndef CLIENT_TIMEOUT
85 #define CLIENT_TIMEOUT (30*1000)
88 static char *tarbuf, *buffer_p;
89 static int tp, ntarf, tbufsiz, ttarf;
90 /* Incremental mode */
92 /* Reset archive bit */
94 /* Include / exclude mode (true=include, false=exclude) */
96 /* use regular expressions for search on file names */
97 BOOL tar_re_search=False;
101 /* Do not dump anything, just calculate sizes */
103 /* Dump files with System attribute */
104 BOOL tar_system=True;
105 /* Dump files with Hidden attribute */
106 BOOL tar_hidden=True;
107 /* Be noisy - make a catalogue */
109 BOOL tar_real_noisy=True;
112 static char **cliplist=NULL;
114 static BOOL must_free_cliplist = False;
116 extern file_info def_finfo;
117 extern BOOL lowercase;
119 extern BOOL readbraw_supported;
121 extern pstring cur_dir;
122 extern int get_total_time_ms;
123 extern int get_total_size;
129 static void writetarheader(int f, char *aname, int size, time_t mtime,
130 char *amode, unsigned char ftype);
131 static void do_atar(char *rname,char *lname,file_info *finfo1);
132 static void do_tar(file_info *finfo);
133 static void oct_it(long value, int ndgs, char *p);
134 static void fixtarname(char *tptr, char *fp, int l);
135 static int dotarbuf(int f, char *b, int n);
136 static void dozerobuf(int f, int n);
137 static void dotareof(int f);
138 static void initarbuf(void);
139 static int do_setrattr(char *fname, int attr, int setit);
141 /* restore functions */
142 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix);
143 static long unoct(char *p, int ndgs);
144 static void do_tarput(void);
145 static void unfixtarname(char *tptr, char *fp, int l, BOOL first);
148 * tar specific utitlities
151 #if 0 /* Removed to get around gcc 'defined but not used' error. */
154 * Stack routines, push_dir, pop_dir, top_dir_name
157 static BOOL push_dir(stack *tar_dir_stack, file_info2 *dir)
159 dir -> next = tar_dir_stack -> top;
161 tar_dir_stack -> items++;
162 tar_dir_stack -> top = dir;
167 static file_info2 *pop_dir(stack *tar_dir_stack)
171 ptr = tar_dir_stack -> top;
172 if (tar_dir_stack -> top != NULL) {
174 tar_dir_stack -> top = tar_dir_stack -> top -> next;
175 tar_dir_stack -> items--;
183 static char *top_dir_name(stack *tar_dir_stack)
186 return(tar_dir_stack -> top != NULL?tar_dir_stack -> top -> name:NULL);
190 static BOOL sub_dir(char *dir1, char *dir2)
197 #endif /* Removed to get around gcc 'defined but not used' error. */
199 /*******************************************************************
200 Create a string of size size+1 (for the null)
201 *******************************************************************/
202 static char *string_create_s(int size)
206 tmp = (char *)malloc(size+1);
210 DEBUG(0, ("Out of memory in string_create_s\n"));
218 /****************************************************************************
219 Write a tar header to buffer
220 ****************************************************************************/
221 static void writetarheader(int f, char *aname, int size, time_t mtime,
222 char *amode, unsigned char ftype)
228 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
230 memset(hb.dummy, 0, sizeof(hb.dummy));
234 /* write a GNU tar style long header */
236 b = (char *)malloc(l+TBLOCK+100);
238 DEBUG(0,("out of memory\n"));
241 writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L');
242 memset(b, 0, l+TBLOCK+100);
243 fixtarname(b, aname, l);
245 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
246 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
250 /* use l + 1 to do the null too */
251 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
254 strlower(hb.dbuf.name);
256 /* write out a "standard" tar format header */
258 hb.dbuf.name[NAMSIZ-1]='\0';
259 safe_strcpy(hb.dbuf.mode, amode, strlen(amode));
260 oct_it(0L, 8, hb.dbuf.uid);
261 oct_it(0L, 8, hb.dbuf.gid);
262 oct_it((long) size, 13, hb.dbuf.size);
263 oct_it((long) mtime, 13, hb.dbuf.mtime);
264 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
265 memset(hb.dbuf.linkname, 0, NAMSIZ);
266 hb.dbuf.linkflag=ftype;
268 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
270 oct_it((long) chk, 8, hb.dbuf.chksum);
271 hb.dbuf.chksum[6] = '\0';
273 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
276 /****************************************************************************
277 Read a tar header into a hblock structure, and validate
278 ***************************************************************************/
279 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
286 * read in a "standard" tar format header - we're not that interested
287 * in that many fields, though
290 /* check the checksum */
291 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
296 /* compensate for blanks in chksum header */
297 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
300 chk += ' ' * sizeof(hb->dbuf.chksum);
302 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
304 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
305 chk, fchk, hb->dbuf.chksum));
309 DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk));
310 /* for (i = 0; i < sizeof(hb -> dummy); i++) {
311 fprintf(stdout, "%2X ", hb -> dummy[i]);
313 fprintf(stdout, "\n");
314 fprintf(stdout, "%s\n", hb -> dummy);
315 fprintf(stdout, "Tarbuf = %X, hb = %X\n", (int)tarbuf, (int)hb);*/
319 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
321 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
326 safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3);
328 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
329 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
330 strlen(hb->dbuf.name) + 1, True);
332 /* can't handle some links at present */
333 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
334 if (hb->dbuf.linkflag == 0) {
335 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
338 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
339 /* Do nothing here at the moment. do_tarput will handle this
340 as long as the longlink gets back to it, as it has to advance
341 the buffer pointer, etc */
344 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
350 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
351 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
356 finfo->mode=0; /* we don't care about mode at the moment, we'll
357 * just make it a regular file */
359 * Bug fix by richard@sj.co.uk
361 * REC: restore times correctly (as does tar)
362 * We only get the modification time of the file; set the creation time
363 * from the mod. time, and the access time to current time
365 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
366 finfo->atime = time(NULL);
367 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
372 /****************************************************************************
373 Write out the tar buffer to tape or wherever
374 ****************************************************************************/
375 static int dotarbuf(int f, char *b, int n)
382 /* This routine and the next one should be the only ones that do write()s */
383 if (tp + n >= tbufsiz)
388 memcpy(tarbuf + tp, b, diff);
389 fail=fail && (1+write(f, tarbuf, tbufsiz));
396 fail=fail && (1 + write(f, b, tbufsiz));
402 memcpy(tarbuf+tp, b, n);
406 return(fail ? writ : 0);
409 /****************************************************************************
410 Write zeros to buffer / tape
411 ****************************************************************************/
412 static void dozerobuf(int f, int n)
414 /* short routine just to write out n zeros to buffer -
415 * used to round files to nearest block
416 * and to do tar EOFs */
423 memset(tarbuf+tp, 0, tbufsiz-tp);
425 write(f, tarbuf, tbufsiz);
426 memset(tarbuf, 0, (tp+=n-tbufsiz));
430 memset(tarbuf+tp, 0, n);
435 /****************************************************************************
437 ****************************************************************************/
438 static void initarbuf()
440 /* initialize tar buffer */
441 tbufsiz=blocksize*TBLOCK;
442 tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */
444 /* reset tar buffer pointer and tar file counter and total dumped */
445 tp=0; ntarf=0; ttarf=0;
448 /****************************************************************************
449 Write two zero blocks at end of file
450 ****************************************************************************/
451 static void dotareof(int f)
453 SMB_STRUCT_STAT stbuf;
454 /* Two zero blocks at end of file, write out full buffer */
459 (void) dozerobuf(f, TBLOCK);
460 (void) dozerobuf(f, TBLOCK);
462 if (sys_fstat(f, &stbuf) == -1)
464 DEBUG(0, ("Couldn't stat file handle\n"));
468 /* Could be a pipe, in which case S_ISREG should fail,
469 * and we should write out at full size */
470 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
473 /****************************************************************************
474 (Un)mangle DOS pathname, make nonabsolute
475 ****************************************************************************/
476 static void fixtarname(char *tptr, char *fp, int l)
478 /* add a '.' to start of file name, convert from ugly dos \'s in path
479 * to lovely unix /'s :-} */
485 if((skip = skip_multibyte_char( *fp)) != 0) {
490 } else if (skip == 1) {
494 } else if (*fp == '\\') {
505 /****************************************************************************
506 Convert from decimal to octal string
507 ****************************************************************************/
508 static void oct_it (long value, int ndgs, char *p)
510 /* Converts long to octal string, pads with leading zeros */
512 /* skip final null, but do final space */
516 /* Loop does at least one digit */
518 p[--ndgs] = '0' + (char) (value & 7);
521 while (ndgs > 0 && value != 0);
523 /* Do leading zeros */
528 /****************************************************************************
529 Convert from octal string to long
530 ***************************************************************************/
531 static long unoct(char *p, int ndgs)
534 /* Converts octal string to long, ignoring any non-digit */
538 if (isdigit((int)*p))
539 value = (value << 3) | (long) (*p - '0');
547 /****************************************************************************
548 Compare two strings in a slash insensitive way, allowing s1 to match s2
549 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
550 a file in any subdirectory of s1, declare a match.
551 ***************************************************************************/
552 static int strslashcmp(char *s1, char *s2)
558 || tolower(*s1) == tolower(*s2)
559 || (*s1 == '\\' && *s2=='/')
560 || (*s1 == '/' && *s2=='\\'))) {
564 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
567 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
569 /* ignore trailing slash on s1 */
570 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
572 /* check for s1 is an "initial" string of s2 */
573 if (*s2 == '/' || *s2 == '\\') return 0;
579 * general smb utility functions
581 /**********************************************************************
582 do_setrtime, set time on a file or dir ...
583 **********************************************************************/
585 static int do_setrtime(char *fname, int mtime, BOOL err_silent)
587 char *inbuf, *outbuf, *p;
590 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
592 name = (char *)malloc(strlen(fname) + 1 + 1);
595 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
601 safe_strcpy(name, "\\", strlen(fname) + 1);
603 safe_strcpy(name, "", strlen(fname) + 1);
604 safe_strcat(name, fname, strlen(fname) + 1);
606 if (fname[strlen(name) - 1] == '\\')
607 name[strlen(name) - 1] = '\0';
609 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
610 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
612 if (!inbuf || !outbuf) {
614 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
620 memset(outbuf, 0, smb_size);
621 set_message(outbuf, 8, 4 + strlen(name), True);
622 CVAL(outbuf, smb_com) = SMBsetatr;
623 SSVAL(outbuf, smb_tid, cnum);
624 cli_setup_pkt(outbuf);
626 SSVAL(outbuf, smb_vwv0, 0);
627 put_dos_date3(outbuf, smb_vwv1, mtime);
631 safe_strcpy(p, name, strlen(name));
632 p+= (strlen(fname)+1);
637 send_smb(Client, outbuf);
638 client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
640 if (CVAL(inbuf,smb_rcls) != 0)
643 DEBUG(0,("%s setting attributes on file %s\n",
644 smb_errstr(inbuf), fname));
646 free(name);free(inbuf);free(outbuf);
651 free(inbuf);free(outbuf);
656 /****************************************************************************
657 Set DOS file attributes
658 ***************************************************************************/
659 static int do_setrattr(char *fname, int attr, int setit)
662 * First get the existing attribs from existing file
669 name = (char *)malloc(strlen(fname) + 1 + 1);
672 DEBUG(0, ("Failed to allocate space in do_setrattr while setting time on file: %s", fname));
677 safe_strcpy(name, "\\", strlen(fname) + 1);
678 safe_strcat(name, fname, strlen(fname) + 1);
680 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
681 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
683 if (!inbuf || !outbuf)
685 DEBUG(0,("out of memory\n"));
690 /* send an smb getatr message */
692 memset(outbuf,0,smb_size);
693 set_message(outbuf,0,2 + strlen(fname),True);
694 CVAL(outbuf,smb_com) = SMBgetatr;
695 SSVAL(outbuf,smb_tid,cnum);
696 cli_setup_pkt(outbuf);
700 safe_strcpy(p,name, strlen(name));
701 p += (strlen(name)+1);
706 send_smb(Client,outbuf);
707 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
709 if (CVAL(inbuf,smb_rcls) != 0)
710 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
713 DEBUG(5,("\nattr 0x%X time %d size %d\n",
714 (int)CVAL(inbuf,smb_vwv0),
715 SVAL(inbuf,smb_vwv1),
716 SVAL(inbuf,smb_vwv3)));
719 fattr=CVAL(inbuf,smb_vwv0);
721 /* combine found attributes with bits to be set or reset */
723 attr=setit ? (fattr | attr) : (fattr & ~attr);
725 /* now try and set attributes by sending smb reset message */
727 /* clear out buffer and start again */
728 memset(outbuf,0,smb_size);
729 set_message(outbuf,8,4 + strlen(name),True);
730 CVAL(outbuf,smb_com) = SMBsetatr;
731 SSVAL(outbuf,smb_tid,cnum);
732 cli_setup_pkt(outbuf);
734 SSVAL(outbuf,smb_vwv0,attr);
738 safe_strcpy(p,name, strlen(name));
739 p += (strlen(name)+1);
744 send_smb(Client,outbuf);
745 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
747 if (CVAL(inbuf,smb_rcls) != 0)
749 DEBUG(0,("%s setting attributes on file %s\n",
750 smb_errstr(inbuf), name));
751 free(name);free(inbuf);free(outbuf);
756 free(inbuf);free(outbuf);
760 /****************************************************************************
761 Create a file on a share
762 ***************************************************************************/
763 static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
766 /* *must* be called with buffer ready malloc'ed */
767 /* open remote file */
769 memset(outbuf,0,smb_size);
770 set_message(outbuf,3,2 + strlen(finfo.name),True);
771 CVAL(outbuf,smb_com) = SMBcreate;
772 SSVAL(outbuf,smb_tid,cnum);
773 cli_setup_pkt(outbuf);
775 SSVAL(outbuf,smb_vwv0,finfo.mode);
776 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
780 safe_strcpy(p,finfo.name, strlen(finfo.name));
782 send_smb(Client,outbuf);
783 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
785 if (CVAL(inbuf,smb_rcls) != 0)
787 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
792 *fnum = SVAL(inbuf,smb_vwv0);
796 /****************************************************************************
797 Write a file to a share
798 ***************************************************************************/
799 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
800 char *bufferp, char *inbuf, char *outbuf)
802 /* *must* be called with buffer ready malloc'ed */
804 memset(outbuf,0,smb_size);
805 set_message(outbuf,5,n + 3,True);
807 memcpy(smb_buf(outbuf)+3, bufferp, n);
809 set_message(outbuf,5,n + 3, False);
810 CVAL(outbuf,smb_com) = SMBwrite;
811 SSVAL(outbuf,smb_tid,cnum);
812 cli_setup_pkt(outbuf);
814 SSVAL(outbuf,smb_vwv0,fnum);
815 SSVAL(outbuf,smb_vwv1,n);
816 SIVAL(outbuf,smb_vwv2,low);
817 SSVAL(outbuf,smb_vwv4,left);
818 CVAL(smb_buf(outbuf),0) = 1;
819 SSVAL(smb_buf(outbuf),1,n);
821 send_smb(Client,outbuf);
822 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
824 if (CVAL(inbuf,smb_rcls) != 0)
826 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
830 if (n != SVAL(inbuf,smb_vwv0))
832 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
833 SVAL(inbuf,smb_vwv0), n));
840 /****************************************************************************
841 Close a file on a share
842 ***************************************************************************/
843 static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
845 /* *must* be called with buffer ready malloc'ed */
847 memset(outbuf,0,smb_size);
848 set_message(outbuf,3,0,True);
849 CVAL(outbuf,smb_com) = SMBclose;
850 SSVAL(outbuf,smb_tid,cnum);
851 cli_setup_pkt(outbuf);
853 SSVAL(outbuf,smb_vwv0,fnum);
854 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
856 DEBUG(3,("Setting date to %s (0x%lX)",
857 asctime(LocalTime(&finfo.mtime)),
860 send_smb(Client,outbuf);
861 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
863 if (CVAL(inbuf,smb_rcls) != 0)
865 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
873 /****************************************************************************
874 Verify existence of path on share
875 ***************************************************************************/
876 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
880 memset(outbuf,0,smb_size);
881 set_message(outbuf,0,4 + strlen(fname),True);
882 CVAL(outbuf,smb_com) = SMBchkpth;
883 SSVAL(outbuf,smb_tid,cnum);
884 cli_setup_pkt(outbuf);
888 safe_strcpy(p,fname, strlen(fname));
890 send_smb(Client,outbuf);
891 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
893 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
895 return(CVAL(inbuf,smb_rcls) == 0);
898 /****************************************************************************
899 Make a directory on share
900 ***************************************************************************/
901 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
903 /* *must* be called with buffer ready malloc'ed */
906 memset(outbuf,0,smb_size);
907 set_message(outbuf,0,2 + strlen(fname),True);
909 CVAL(outbuf,smb_com) = SMBmkdir;
910 SSVAL(outbuf,smb_tid,cnum);
911 cli_setup_pkt(outbuf);
915 safe_strcpy(p,fname, strlen(fname));
917 send_smb(Client,outbuf);
918 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
920 if (CVAL(inbuf,smb_rcls) != 0)
922 DEBUG(0,("%s making remote directory %s\n",
923 smb_errstr(inbuf),fname));
930 /****************************************************************************
931 Ensure a remote path exists (make if necessary)
932 ***************************************************************************/
933 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
935 /* *must* be called with buffer ready malloc'ed */
936 /* ensures path exists */
938 char *partpath, *ffname;
939 char *p=fname, *basehack;
941 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
943 partpath = string_create_s(strlen(fname));
944 ffname = string_create_s(strlen(fname));
946 if ((partpath == NULL) || (ffname == NULL)){
948 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
955 /* fname copied to ffname so can strtok */
957 safe_strcpy(ffname, fname, strlen(fname));
959 /* do a `basename' on ffname, so don't try and make file name directory */
960 if ((basehack=strrchr(ffname, '\\')) == NULL)
965 p=strtok(ffname, "\\");
969 safe_strcat(partpath, p, strlen(fname) + 1);
971 if (!smbchkpath(partpath, inbuf, outbuf)) {
972 if (!smbmkdir(partpath, inbuf, outbuf))
974 DEBUG(0, ("Error mkdirhiering\n"));
978 DEBUG(3, ("mkdirhiering %s\n", partpath));
982 safe_strcat(partpath, "\\", strlen(fname) + 1);
983 p = strtok(NULL,"/\\");
989 static int padit(char *buf, int bufsize, int padsize)
994 DEBUG(5, ("Padding with %d zeros\n", padsize));
995 memset(buf, 0, bufsize);
996 while( !berr && padsize > 0 ) {
997 bytestowrite= MIN(bufsize, padsize);
998 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
999 padsize -= bytestowrite;
1006 * smbclient functions
1008 /****************************************************************************
1009 append one remote file to the tar file
1010 ***************************************************************************/
1011 static void do_atar(char *rname,char *lname,file_info *finfo1)
1016 char *inbuf,*outbuf;
1018 BOOL close_done = False;
1019 BOOL shallitime=True;
1020 BOOL ignore_close_error = False;
1024 struct timeval tp_start;
1025 GetTimeOfDay(&tp_start);
1027 ftype = '0'; /* An ordinary file ... */
1030 finfo.size = finfo1 -> size;
1031 finfo.mode = finfo1 -> mode;
1032 finfo.uid = finfo1 -> uid;
1033 finfo.gid = finfo1 -> gid;
1034 finfo.mtime = finfo1 -> mtime;
1035 finfo.atime = finfo1 -> atime;
1036 finfo.ctime = finfo1 -> ctime;
1039 finfo.size = def_finfo.size;
1040 finfo.mode = def_finfo.mode;
1041 finfo.uid = def_finfo.uid;
1042 finfo.gid = def_finfo.gid;
1043 finfo.mtime = def_finfo.mtime;
1044 finfo.atime = def_finfo.atime;
1045 finfo.ctime = def_finfo.ctime;
1050 DEBUG(3,("skipping file %s of size %d bytes\n",
1054 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1059 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1060 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1062 if (!inbuf || !outbuf)
1064 DEBUG(0,("out of memory\n"));
1068 memset(outbuf,0,smb_size);
1069 set_message(outbuf,15,1 + strlen(rname),True);
1071 CVAL(outbuf,smb_com) = SMBopenX;
1072 SSVAL(outbuf,smb_tid,cnum);
1073 cli_setup_pkt(outbuf);
1075 SSVAL(outbuf,smb_vwv0,0xFF);
1076 SSVAL(outbuf,smb_vwv2,1);
1077 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1078 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1079 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1080 SSVAL(outbuf,smb_vwv8,1);
1082 p = smb_buf(outbuf);
1083 safe_strcpy(p, rname, strlen(rname));
1084 p = skip_string(p,1);
1086 dos_clean_name(rname);
1088 /* do a chained openX with a readX? */
1091 SSVAL(outbuf,smb_vwv0,SMBreadX);
1092 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
1095 SCVAL(p,smb_wct,10);
1096 SSVAL(p,smb_vwv0,0xFF);
1097 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1098 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
1099 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1102 send_smb(Client,outbuf);
1103 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1105 if (CVAL(inbuf,smb_rcls) != 0)
1107 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1108 SVAL(inbuf,smb_err) == ERRnoresource &&
1109 cli_reopen_connection(inbuf,outbuf))
1111 do_atar(rname,lname,finfo1);
1112 free(inbuf);free(outbuf);
1116 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
1117 free(inbuf);free(outbuf);
1121 finfo.name = string_create_s(strlen(rname));
1122 if (finfo.name == NULL) {
1124 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
1125 free(inbuf); free(outbuf);
1130 safe_strcpy(finfo.name,rname, strlen(rname));
1133 finfo.mode = SVAL(inbuf,smb_vwv3);
1134 finfo.size = IVAL(inbuf,smb_vwv4);
1135 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
1136 finfo.atime = finfo.ctime = finfo.mtime;
1139 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
1141 fnum = SVAL(inbuf,smb_vwv2);
1143 if (tar_inc && !(finfo.mode & aARCH))
1145 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
1148 else if (!tar_system && (finfo.mode & aSYSTEM))
1150 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
1153 else if (!tar_hidden && (finfo.mode & aHIDDEN))
1155 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
1160 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1162 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
1163 datalen = SVAL(p,smb_vwv5);
1164 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
1172 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1177 /* write a tar header, don't bother with mode - just set to 100644 */
1178 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
1180 while (nread < finfo.size && !close_done)
1183 static BOOL can_chain_close=True;
1187 DEBUG(3,("nread=%d\n",nread));
1189 /* 3 possible read types. readbraw if a large block is required.
1190 readX + close if not much left and read if neither is supported */
1192 /* we might have already read some data from a chained readX */
1193 if (dataptr && datalen>0)
1196 /* if we can finish now then readX+close */
1197 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1198 ((finfo.size - nread) <
1199 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1202 /* if we support readraw then use that */
1203 if (method<0 && readbraw_supported)
1206 /* if we can then use readX */
1207 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1219 /* use readX + close */
1220 memset(outbuf,0,smb_size);
1221 set_message(outbuf,10,0,True);
1222 CVAL(outbuf,smb_com) = SMBreadX;
1223 SSVAL(outbuf,smb_tid,cnum);
1224 cli_setup_pkt(outbuf);
1228 CVAL(outbuf,smb_vwv0) = SMBclose;
1229 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
1232 CVAL(outbuf,smb_vwv0) = 0xFF;
1235 SSVAL(outbuf,smb_vwv2,fnum);
1236 SIVAL(outbuf,smb_vwv3,nread);
1237 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1238 SSVAL(outbuf,smb_vwv6,0);
1239 SIVAL(outbuf,smb_vwv7,0);
1240 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
1244 p = smb_buf(outbuf);
1251 /* now set the total packet length */
1252 smb_setlen(outbuf,smb_len(outbuf)+9);
1255 send_smb(Client,outbuf);
1256 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1258 if (CVAL(inbuf,smb_rcls) != 0)
1260 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1265 SVAL(inbuf,smb_vwv0) != SMBclose)
1267 /* NOTE: WfWg sometimes just ignores the chained
1268 command! This seems to break the spec? */
1269 DEBUG(3,("Rejected chained close?\n"));
1271 can_chain_close = False;
1272 ignore_close_error = True;
1275 datalen = SVAL(inbuf,smb_vwv5);
1276 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
1283 static int readbraw_size = 0xFFFF;
1286 memset(outbuf,0,smb_size);
1287 set_message(outbuf,8,0,True);
1288 CVAL(outbuf,smb_com) = SMBreadbraw;
1289 SSVAL(outbuf,smb_tid,cnum);
1290 cli_setup_pkt(outbuf);
1291 SSVAL(outbuf,smb_vwv0,fnum);
1292 SIVAL(outbuf,smb_vwv1,nread);
1293 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1294 SSVAL(outbuf,smb_vwv4,0);
1295 SIVALS(outbuf,smb_vwv5,-1);
1296 send_smb(Client,outbuf);
1298 /* Now read the raw data into the buffer and write it */
1299 if(read_smb_length(Client,inbuf,0) == -1) {
1300 DEBUG(0,("Failed to read length in readbraw\n"));
1304 /* Even though this is not an smb message, smb_len
1305 returns the generic length of an smb message */
1306 datalen = smb_len(inbuf);
1310 /* we got a readbraw error */
1311 DEBUG(4,("readbraw error - reducing size\n"));
1312 readbraw_size = (readbraw_size * 9) / 10;
1314 if (readbraw_size < max_xmit)
1316 DEBUG(0,("disabling readbraw\n"));
1317 readbraw_supported = False;
1324 if(read_data(Client,inbuf,datalen) != datalen) {
1325 DEBUG(0,("Failed to read data in readbraw\n"));
1333 /* we've already read some data with a chained readX */
1337 /* use plain read */
1338 memset(outbuf,0,smb_size);
1339 set_message(outbuf,5,0,True);
1340 CVAL(outbuf,smb_com) = SMBread;
1341 SSVAL(outbuf,smb_tid,cnum);
1342 cli_setup_pkt(outbuf);
1344 SSVAL(outbuf,smb_vwv0,fnum);
1345 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1346 SIVAL(outbuf,smb_vwv2,nread);
1347 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1349 send_smb(Client,outbuf);
1350 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1352 if (CVAL(inbuf,smb_rcls) != 0)
1354 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1358 datalen = SVAL(inbuf,smb_vwv0);
1359 dataptr = smb_buf(inbuf) + 3;
1364 /* add received bits of file to buffer - dotarbuf will
1365 * write out in 512 byte intervals */
1366 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1368 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
1375 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1383 /* pad tar file with zero's if we couldn't get entire file */
1384 if (nread < finfo.size)
1386 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
1387 if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
1388 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
1391 /* round tar file to nearest block */
1392 if (finfo.size % TBLOCK)
1393 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1395 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1401 memset(outbuf,0,smb_size);
1402 set_message(outbuf,3,0,True);
1403 CVAL(outbuf,smb_com) = SMBclose;
1404 SSVAL(outbuf,smb_tid,cnum);
1405 cli_setup_pkt(outbuf);
1407 SSVAL(outbuf,smb_vwv0,fnum);
1408 SIVALS(outbuf,smb_vwv1,-1);
1410 send_smb(Client,outbuf);
1411 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1413 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1415 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1416 free(inbuf);free(outbuf);
1423 struct timeval tp_end;
1426 /* if shallitime is true then we didn't skip */
1427 if (tar_reset && !dry_run)
1428 (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1430 GetTimeOfDay(&tp_end);
1432 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1433 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1434 get_total_time_ms += this_time;
1435 get_total_size += finfo.size;
1439 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
1440 finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
1444 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1445 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1446 finfo.size / MAX(0.001, (1.024*this_time)),
1447 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1450 free(inbuf);free(outbuf);
1453 /****************************************************************************
1454 Append single file to tar file (or not)
1455 ***************************************************************************/
1456 static void do_tar(file_info *finfo)
1460 if (strequal(finfo->name,".."))
1463 /* Is it on the exclude list ? */
1464 if (!tar_excl && clipn) {
1467 DEBUG(5, ("Excl: strlen(cur_dir) = %i\n", strlen(cur_dir)));
1469 safe_strcpy(exclaim, cur_dir, sizeof(pstring));
1470 *(exclaim+strlen(exclaim)-1)='\0';
1472 safe_strcat(exclaim, "\\", sizeof(pstring));
1473 safe_strcat(exclaim, finfo->name, sizeof(exclaim));
1475 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
1477 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
1479 (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
1481 (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
1483 DEBUG(3,("Skipping file %s\n", exclaim));
1488 if (finfo->mode & aDIR)
1490 pstring saved_curdir;
1492 char *inbuf,*outbuf;
1494 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1495 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1497 if (!inbuf || !outbuf)
1499 DEBUG(0,("out of memory\n"));
1503 safe_strcpy(saved_curdir, cur_dir, sizeof(saved_curdir));
1505 DEBUG(5, ("Sizeof(cur_dir)=%i, strlen(cur_dir)=%i, strlen(finfo->name)=%i\nname=%s,cur_dir=%s\n", sizeof(cur_dir), strlen(cur_dir), strlen(finfo->name), finfo->name, cur_dir));
1507 safe_strcat(cur_dir,finfo->name, sizeof(cur_dir));
1508 safe_strcat(cur_dir,"\\", sizeof(cur_dir));
1510 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
1512 /* write a tar directory, don't bother with mode - just set it to
1514 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
1517 DEBUG(0, (" directory %s\n", cur_dir));
1520 ntarf++; /* Make sure we have a file on there */
1521 safe_strcpy(mtar_mask,cur_dir, sizeof(pstring));
1522 safe_strcat(mtar_mask,"*", sizeof(pstring));
1523 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1524 safe_strcpy(cur_dir,saved_curdir, sizeof(pstring));
1525 free(inbuf);free(outbuf);
1529 safe_strcpy(rname,cur_dir, sizeof(pstring));
1530 safe_strcat(rname,finfo->name, sizeof(pstring));
1531 do_atar(rname,finfo->name,finfo);
1535 /****************************************************************************
1536 Convert from UNIX to DOS file names
1537 ***************************************************************************/
1538 static void unfixtarname(char *tptr, char *fp, int l, BOOL first)
1540 /* remove '.' from start of file name, convert from unix /'s to
1541 * dos \'s in path. Kill any absolute path names. But only if first!
1544 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
1551 if (*fp == '\\' || *fp == '/') {
1559 if(( skip = skip_multibyte_char( *fp )) != 0) {
1564 } else if (skip == 1) {
1568 } else if (*fp == '/') {
1579 #ifndef OLD_DOTARPUT
1581 /****************************************************************************
1582 Move to the next block in the buffer, which may mean read in another set of
1583 blocks. FIXME, we should allow more than one block to be skipped.
1584 ****************************************************************************/
1585 static int next_block(char *ltarbuf, char **bufferp, int bufsiz)
1587 int bufread, total = 0;
1589 DEBUG(5, ("Advancing to next block: %0x\n", (unsigned int)*bufferp));
1593 if (*bufferp >= (ltarbuf + bufsiz)) {
1595 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
1599 for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
1601 if (bufread <= 0) { /* An error, return false */
1602 return (total > 0 ? -2 : bufread);
1607 DEBUG(5, ("Total bytes read ... %i\n", total));
1617 /* Skip a file, even if it includes a long file name? */
1618 static int skip_file(int skipsize)
1620 int dsize = skipsize;
1622 DEBUG(5, ("Skiping file. Size = %i\n", skipsize));
1624 /* FIXME, we should skip more than one block at a time */
1628 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1630 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1642 /* We get a file from the tar file and store it */
1643 static int get_file(file_info2 finfo, char * inbuf, char * outbuf)
1645 int fsize = finfo.size;
1646 int fnum, pos = 0, dsize = 0, rsize = 0;
1648 DEBUG(5, ("get_file: file: %s, size %i\n", finfo.name, fsize));
1650 if (ensurepath(finfo.name, inbuf, outbuf) &&
1651 !smbcreat(finfo, &fnum, inbuf, outbuf))
1653 DEBUG(0, ("abandoning restore\n"));
1657 DEBUG(0, ("restore tar file %s of size %d bytes\n",
1658 finfo.name, finfo.size));
1660 /* read the blocks from the tar file and write to the remote file */
1666 dsize = MIN(tbufsiz - (buffer_p - tarbuf), rsize); /* Calculate the size to write */
1668 DEBUG(5, ("writing %i bytes ...\n", dsize));
1670 if (!smbwrite(fnum, dsize, pos, 0, fsize - pos, buffer_p, inbuf, outbuf)) {
1672 DEBUG(0, ("Error writing remote file\n"));
1679 /* Now figure out how much to move in the buffer */
1681 /* FIXME, we should skip more than one block at a time */
1685 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
1687 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1698 /* Now close the file ... */
1700 if (!smbshut(finfo, fnum, inbuf, outbuf)) {
1702 DEBUG(0, ("Error closing remote file\n"));
1707 /* Now we update the creation date ... */
1709 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
1711 if (!do_setrtime(finfo.name, finfo.mtime, True)) {
1713 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1714 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1723 /* Create a directory. We just ensure that the path exists and return as there
1724 is no file associated with a directory
1726 static int get_dir(file_info2 finfo, char * inbuf, char * outbuf)
1729 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1731 if (!ensurepath(finfo.name, inbuf, outbuf)) {
1733 DEBUG(0, ("Problems creating directory\n"));
1740 /* Get a file with a long file name ... first file has file name, next file
1741 has the data. We only want the long file name, as the loop in do_tarput
1742 will deal with the rest.
1744 static char * get_longfilename(file_info2 finfo)
1746 int namesize = finfo.size + strlen(cur_dir) + 2;
1747 char *longname = malloc(namesize);
1748 int offset = 0, left = finfo.size;
1751 DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
1752 DEBUG(5, ("Len = %i\n", finfo.size));
1755 if (longname == NULL) {
1757 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1758 finfo.size + strlen(cur_dir) + 2));
1762 /* First, add cur_dir to the long file name */
1764 if (strlen(cur_dir) > 0) {
1765 strncpy(longname, cur_dir, namesize);
1766 offset = strlen(cur_dir);
1769 /* Loop through the blocks picking up the name */
1773 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1775 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1780 unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
1781 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
1792 static void do_tarput(void)
1795 struct timeval tp_start;
1796 char *inbuf, *outbuf, *longfilename = NULL;
1799 GetTimeOfDay(&tp_start);
1801 DEBUG(5, ("RJS do_tarput called ...\n"));
1803 buffer_p = tarbuf + tbufsiz; /* init this to force first read */
1805 #if 0 /* Fix later ... */
1806 if (push_dir(&dir_stack, &finfo)) {
1809 finfo2 = pop_dir(&dir_stack);
1810 inbuf = top_dir_name(&dir_stack); /* FIXME */
1811 if (sub_dir(inbuf, finfo2 -> name)){
1819 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1820 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1822 if (!inbuf || !outbuf) {
1824 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1829 /* Now read through those files ... */
1833 /* Get us to the next block, or the first block first time around */
1835 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1837 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1843 DEBUG(5, ("Reading the next header ...\n"));
1845 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir)) {
1847 case -2: /* Hmm, not good, but not fatal */
1848 DEBUG(0, ("Skipping %s...\n", finfo.name));
1849 if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) &&
1850 !skip_file(finfo.size)) {
1852 DEBUG(0, ("Short file, bailing out...\n"));
1853 free(inbuf); free(outbuf);
1861 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1862 free(inbuf); free(outbuf);
1865 case 0: /* chksum is zero - looks like an EOF */
1866 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1867 free(inbuf); free(outbuf);
1868 return; /* Hmmm, bad here ... */
1875 /* Now, do we have a long file name? */
1877 if (longfilename != NULL) {
1879 free(finfo.name); /* Free the space already allocated */
1880 finfo.name = longfilename;
1881 longfilename = NULL;
1885 /* Well, now we have a header, process the file ... */
1887 /* Should we skip the file? We have the long name as well here */
1890 ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1892 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1894 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1897 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, cliplist[0], finfo.name));
1901 skip_file(finfo.size);
1906 /* We only get this far if we should process the file */
1908 switch (((union hblock *)buffer_p) -> dbuf.linkflag) {
1910 case '0': /* Should use symbolic names--FIXME */
1911 if (!get_file(finfo, inbuf, outbuf)) {
1913 free(inbuf); free(outbuf);
1914 DEBUG(0, ("Abandoning restore\n"));
1921 if (!get_dir(finfo, inbuf, outbuf)) {
1922 free(inbuf); free(outbuf);
1923 DEBUG(0, ("Abandoning restore \n"));
1929 longfilename = get_longfilename(finfo);
1930 if (!longfilename) {
1931 free(inbuf); free(outbuf);
1932 DEBUG(0, ("abandoning restore\n"));
1936 DEBUG(5, ("Long file name: %s\n", longfilename));
1940 skip_file(finfo.size); /* Don't handle these yet */
1952 static void do_tarput()
1955 int nread=0, bufread;
1956 char *inbuf,*outbuf, *longname = NULL;
1959 struct timeval tp_start;
1960 BOOL tskip=False; /* We'll take each file as it comes */
1962 finfo.name = NULL; /* No name in here ... */
1964 GetTimeOfDay(&tp_start);
1966 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1967 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1969 if (!inbuf || !outbuf)
1971 DEBUG(0,("out of memory\n"));
1976 * Must read in tbufsiz dollops
1979 /* These should be the only reads in clitar.c */
1980 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1984 /* Code to handle a short read.
1985 * We always need a TBLOCK full of stuff
1987 if (bufread % TBLOCK) {
1988 int lchunk=TBLOCK-(bufread % TBLOCK);
1991 /* It's a shorty - a short read that is */
1992 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1994 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1996 if (!(lchunk-=lread)) break;
1999 /* If we've reached EOF then that must be a short file */
2000 if (lread<=0) break;
2004 endofbuffer=tarbuf+bufread;
2007 if (fsize<bufread) {
2012 if (fsize==bufread) tskip=False;
2021 int next_header = 1; /* Want at least one header */
2024 if (buffer_p >= endofbuffer) {
2026 bufread = read(tarhandle, tarbuf, tbufsiz);
2030 next_header = 0; /* Don't want the next one ... */
2032 if (finfo.name != NULL) { /* Free the space */
2038 DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n",
2039 (int)tarbuf, (int)buffer_p, (int)endofbuffer));
2040 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
2042 case -2: /* something dodgy but not fatal about this */
2043 DEBUG(0, ("skipping %s...\n", finfo.name));
2044 buffer_p+=TBLOCK; /* header - like a link */
2047 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
2048 free(inbuf); free(outbuf);
2050 case 0: /* chksum is zero - we assume that one all zero
2051 *header block will do for eof */
2053 ("total of %d tar files restored to share\n", ntarf));
2054 free(inbuf); free(outbuf);
2060 /* If we have a longname left from the last time through,
2061 copy it into finfo.name and free it.
2063 The size of a pstring is the limiting factor on filenames
2064 and directory names now. The total pathname length must be
2065 less than sizeof(pstring) - 1, which is currently 1023. */
2067 if (longname != NULL) {
2069 free(finfo.name); /* Free the name in the finfo */
2070 finfo.name = string_create_s(strlen(longname) + 2);
2071 strncpy(finfo.name, longname, strlen(longname) + 1);
2072 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
2078 /* Check if a long-link. We do this before the clip checking
2079 because clip-checking should clip on real name - RJS */
2081 if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
2082 int file_len, first = 0; char *cp;
2084 /* Skip this header, but pick up length, get the name and
2085 fix the name and skip the name. Hmmm, what about end of
2088 longname = malloc(finfo.size + strlen(cur_dir) + 1);
2089 if (longname == NULL) {
2091 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
2092 finfo.size + strlen(cur_dir) + 1)
2094 free(inbuf); free(outbuf);
2099 bzero(longname, finfo.size + strlen(cur_dir) +1);
2101 buffer_p += TBLOCK; /* Skip that longlink header */
2103 /* This needs restructuring ... */
2105 safe_strcpy(longname, cur_dir, strlen(cur_dir) + 1);
2106 cp = longname + strlen(cur_dir);
2107 file_len = finfo.size;
2109 DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n",
2110 (int)longname, (int)cp, file_len));
2112 while (file_len > 0) {
2114 if (buffer_p >= endofbuffer) {
2116 bufread = read(tarhandle, tarbuf, tbufsiz);
2122 unfixtarname(cp, buffer_p, file_len >= TBLOCK?TBLOCK:file_len, first == 0);
2124 first++; /* Not the first anymore */
2125 cp = cp + strlen(cp); /* Move to end of string */
2128 DEBUG(5, ("cp=%0X, file_len=%i\n", (int)cp, file_len));
2129 next_header = 1; /* Force read of next header */
2135 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
2137 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
2139 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
2143 if (finfo.mode & aDIR)
2145 else if ((fsize=finfo.size) % TBLOCK) {
2146 fsize+=TBLOCK-(fsize%TBLOCK);
2148 if (fsize<endofbuffer-buffer_p) {
2153 fsize-=endofbuffer-buffer_p;
2158 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
2160 if (finfo.mode & aDIR)
2163 DEBUG(5, ("Creating directory: %s\n", finfo.name));
2164 DEBUG(0, ("restore tar dir %s of size %d bytes\n",
2165 finfo.name, finfo.size));
2167 if (!ensurepath(finfo.name, inbuf, outbuf))
2169 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
2170 free(inbuf); free(outbuf);
2175 /* Now we update the creation date ... */
2177 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
2179 if (!do_setrtime(finfo.name, finfo.mtime, True)) {
2181 if (tar_real_noisy) {
2182 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
2184 /*return; - Win 95 does not like setting time on dirs */
2196 if (ensurepath(finfo.name, inbuf, outbuf)
2197 && !smbcreat(finfo, &fnum, inbuf, outbuf))
2199 DEBUG(0, ("abandoning restore\n"));
2200 free(inbuf);free(outbuf);
2204 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
2205 finfo.name, finfo.size));
2207 /* if (!finfo.size) {
2208 if (!smbshut(finfo, fnum, inbuf, outbuf)){
2209 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
2210 free(inbuf);free(outbuf);
2216 if ((buffer_p+=TBLOCK) >= endofbuffer) break;
2219 /* write out the file in chunk sized chunks - don't
2220 * go past end of buffer though */
2221 chunk=(fsize-nread < endofbuffer - buffer_p)
2222 ? fsize - nread : endofbuffer - buffer_p;
2225 int minichunk=MIN(chunk, max_xmit-200);
2227 if (!smbwrite(fnum, /* file descriptor */
2229 nread, /* offset low */
2230 0, /* offset high - not implemented */
2231 fsize-nread, /* left - only hint to server */
2236 DEBUG(0, ("Error writing remote file\n"));
2237 free(inbuf); free(outbuf);
2240 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
2242 buffer_p+=minichunk; nread+=minichunk;
2248 if (!smbshut(finfo, fnum, inbuf, outbuf))
2250 DEBUG(0, ("Error closing remote file\n"));
2251 free(inbuf);free(outbuf);
2254 if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
2255 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
2256 (int) buffer_p, (int)(buffer_p - tarbuf)));
2261 } while (buffer_p < endofbuffer);
2264 DEBUG(0, ("premature eof on tar file ?\n"));
2265 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
2267 free(inbuf); free(outbuf);
2272 * samba interactive commands
2275 /****************************************************************************
2277 ***************************************************************************/
2278 void cmd_block(char *dum_in, char *dum_out)
2283 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2285 DEBUG(0, ("blocksize <n>\n"));
2290 if (block < 0 || block > 65535)
2292 DEBUG(0, ("blocksize out of range"));
2297 DEBUG(2,("blocksize is now %d\n", blocksize));
2300 /****************************************************************************
2301 command to set incremental / reset mode
2302 ***************************************************************************/
2303 void cmd_tarmode(char *dum_in, char *dum_out)
2307 while (next_token(NULL,buf,NULL,sizeof(buf))) {
2308 if (strequal(buf, "full"))
2310 else if (strequal(buf, "inc"))
2312 else if (strequal(buf, "reset"))
2314 else if (strequal(buf, "noreset"))
2316 else if (strequal(buf, "system"))
2318 else if (strequal(buf, "nosystem"))
2320 else if (strequal(buf, "hidden"))
2322 else if (strequal(buf, "nohidden"))
2324 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2326 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2328 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2331 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2332 tar_inc ? "incremental" : "full",
2333 tar_system ? "system" : "nosystem",
2334 tar_hidden ? "hidden" : "nohidden",
2335 tar_reset ? "reset" : "noreset",
2336 tar_noisy ? "verbose" : "quiet"));
2340 /****************************************************************************
2341 Feeble attrib command
2342 ***************************************************************************/
2343 void cmd_setmode(char *dum_in, char *dum_out)
2351 attra[0] = attra[1] = 0;
2353 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2355 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2359 safe_strcpy(fname, cur_dir, sizeof(pstring));
2360 safe_strcat(fname, buf, sizeof(pstring));
2362 while (next_token(NULL,buf,NULL,sizeof(buf))) {
2371 case 'r': attra[direct]|=aRONLY;
2373 case 'h': attra[direct]|=aHIDDEN;
2375 case 's': attra[direct]|=aSYSTEM;
2377 case 'a': attra[direct]|=aARCH;
2379 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2384 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2386 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2390 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2391 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2392 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2395 /****************************************************************************
2396 Principal command for creating / extracting
2397 ***************************************************************************/
2398 void cmd_tar(char *inbuf, char *outbuf)
2404 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2406 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
2410 argl=toktocliplist(&argcl, NULL);
2411 if (!tar_parseargs(argcl, argl, buf, 0))
2414 process_tar(inbuf, outbuf);
2419 /****************************************************************************
2420 Command line (option) version
2421 ***************************************************************************/
2422 int process_tar(char *inbuf, char *outbuf)
2438 if (clipn && tar_excl) {
2442 for (i=0; i<clipn; i++) {
2443 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2445 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2446 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2449 if (strrchr(cliplist[i], '\\')) {
2452 safe_strcpy(saved_dir, cur_dir, sizeof(pstring));
2454 if (*cliplist[i]=='\\') {
2455 safe_strcpy(tarmac, cliplist[i], sizeof(pstring));
2457 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2458 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2460 safe_strcpy(cur_dir, tarmac, sizeof(pstring));
2461 *(strrchr(cur_dir, '\\')+1)='\0';
2463 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2464 safe_strcpy(cur_dir,saved_dir, sizeof(pstring));
2466 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2467 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2468 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2473 safe_strcpy(mask,cur_dir, sizeof(pstring));
2474 safe_strcat(mask,"\\*", sizeof(pstring));
2475 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2478 if (ntarf) dotareof(tarhandle);
2482 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2483 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2487 if (must_free_cliplist) {
2489 for (i = 0; i < clipn; ++i) {
2495 must_free_cliplist = False;
2501 /****************************************************************************
2502 Find a token (filename) in a clip list
2503 ***************************************************************************/
2504 static int clipfind(char **aret, int ret, char *tok)
2506 if (aret==NULL) return 0;
2508 /* ignore leading slashes or dots in token */
2509 while(strchr("/\\.", *tok)) tok++;
2514 /* ignore leading slashes or dots in list */
2515 while(strchr("/\\.", *pkey)) pkey++;
2517 if (!strslashcmp(pkey, tok)) return 1;
2523 /****************************************************************************
2524 Read list of files to include from the file and initialize cliplist
2526 ***************************************************************************/
2527 static int read_inclusion_file(char *filename)
2529 FILE *inclusion = NULL;
2530 char buf[MAXPATHLEN + 1];
2531 char *inclusion_buffer = NULL;
2532 int inclusion_buffer_size = 0;
2533 int inclusion_buffer_sofar = 0;
2540 buf[MAXPATHLEN] = '\0'; /* guarantee null-termination */
2541 if ((inclusion = fopen(filename, "r")) == NULL) {
2542 /* XXX It would be better to include a reason for failure, but without
2543 * autoconf, it's hard to use strerror, sys_errlist, etc.
2545 DEBUG(0,("Unable to open inclusion file %s\n", filename));
2549 while ((! error) && (fgets(buf, sizeof(buf)-1, inclusion))) {
2550 if (inclusion_buffer == NULL) {
2551 inclusion_buffer_size = 1024;
2552 if ((inclusion_buffer = malloc(inclusion_buffer_size)) == NULL) {
2553 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
2559 if (buf[strlen(buf)-1] == '\n') {
2560 buf[strlen(buf)-1] = '\0';
2563 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
2564 inclusion_buffer_size *= 2;
2565 inclusion_buffer = Realloc(inclusion_buffer,inclusion_buffer_size);
2566 if (! inclusion_buffer) {
2567 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
2568 inclusion_buffer_size));
2574 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
2575 inclusion_buffer_sofar += strlen(buf) + 1;
2581 /* Allocate an array of clipn + 1 char*'s for cliplist */
2582 cliplist = malloc((clipn + 1) * sizeof(char *));
2583 if (cliplist == NULL) {
2584 DEBUG(0,("failure allocating memory for cliplist\n"));
2587 cliplist[clipn] = NULL;
2588 p = inclusion_buffer;
2589 for (i = 0; (! error) && (i < clipn); i++) {
2590 /* set current item to NULL so array will be null-terminated even if
2591 * malloc fails below. */
2593 if ((tmpstr = (char *)malloc(strlen(p)+1)) == NULL) {
2594 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));
2597 unfixtarname(tmpstr, p, strlen(p) + 1, True);
2598 cliplist[i] = tmpstr;
2599 if ((p = strchr(p, '\000')) == NULL) {
2600 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
2606 must_free_cliplist = True;
2610 if (inclusion_buffer) {
2611 free(inclusion_buffer);
2616 /* We know cliplist is always null-terminated */
2617 for (pp = cliplist; *pp; ++pp) {
2622 must_free_cliplist = False;
2627 /* cliplist and its elements are freed at the end of process_tar. */
2631 /****************************************************************************
2632 Parse tar arguments. Sets tar_type, tar_excl, etc.
2633 ***************************************************************************/
2634 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2636 char tar_clipfl='\0';
2638 /* Reset back to defaults - could be from interactive version
2639 * reset mode and archive mode left as they are though
2651 if (tar_type=='c') {
2652 printf("Tar must be followed by only one of c or x.\n");
2658 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2659 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2670 DEBUG(0,("Option N must be followed by valid file name\n"));
2673 SMB_STRUCT_STAT stbuf;
2674 extern time_t newer_than;
2676 if (dos_stat(argv[Optind], &stbuf) == 0) {
2677 newer_than = stbuf.st_mtime;
2678 DEBUG(1,("Getting files newer than %s",
2679 asctime(LocalTime(&newer_than))));
2682 DEBUG(0,("Error setting newer-than time\n"));
2692 DEBUG(0,("Only one of I,X,F must be specified\n"));
2699 DEBUG(0,("Only one of I,X,F must be specified\n"));
2706 DEBUG(0,("Only one of I,X,F must be specified\n"));
2712 DEBUG(0, ("tar_re_search set\n"));
2713 tar_re_search = True;
2716 if (tar_type == 'c') {
2717 DEBUG(0, ("dry_run set\n"));
2720 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
2725 DEBUG(0,("Unknown tar option\n"));
2730 printf("Option T must be followed by one of c or x.\n");
2734 /* tar_excl is true if cliplist lists files to be included.
2735 * Both 'I' and 'F' mean include. */
2736 tar_excl=tar_clipfl!='X';
2738 if (tar_clipfl=='F') {
2739 if (argc-Optind-1 != 1) {
2740 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
2743 if (! read_inclusion_file(argv[Optind+1])) {
2746 } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2751 cliplist=argv+Optind+1;
2752 clipn=argc-Optind-1;
2755 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2756 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2762 for (clipcount = 0; clipcount < clipn; clipcount++) {
2764 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2766 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2767 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2772 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);
2773 tmplist[clipcount] = tmpstr;
2774 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2776 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2779 must_free_cliplist = True;
2782 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2786 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2788 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2793 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2797 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2799 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2805 clipn=argc-Optind-1;
2806 cliplist=argv+Optind+1;
2810 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2811 /* Sets tar handle to either 0 or 1, as appropriate */
2812 tarhandle=(tar_type=='c');
2814 if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0))
2817 DEBUG(0,("Output is /dev/null, assuming dry_run"));
2822 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2823 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2825 DEBUG(0,("Error opening local file %s - %s\n",
2826 argv[Optind], strerror(errno)));