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 /* Dump files with System attribute */
102 BOOL tar_system=True;
103 /* Dump files with Hidden attribute */
104 BOOL tar_hidden=True;
105 /* Be noisy - make a catalogue */
107 BOOL tar_real_noisy=True;
110 static char **cliplist=NULL;
112 static BOOL must_free_cliplist = False;
114 extern file_info def_finfo;
115 extern BOOL lowercase;
117 extern BOOL readbraw_supported;
119 extern pstring cur_dir;
120 extern int get_total_time_ms;
121 extern int get_total_size;
127 static void writetarheader(int f, char *aname, int size, time_t mtime,
128 char *amode, unsigned char ftype);
129 static void do_atar(char *rname,char *lname,file_info *finfo1);
130 static void do_tar(file_info *finfo);
131 static void oct_it(long value, int ndgs, char *p);
132 static void fixtarname(char *tptr, char *fp, int l);
133 static int dotarbuf(int f, char *b, int n);
134 static void dozerobuf(int f, int n);
135 static void dotareof(int f);
136 static void initarbuf(void);
137 static int do_setrattr(char *fname, int attr, int setit);
139 /* restore functions */
140 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix);
141 static long unoct(char *p, int ndgs);
142 static void do_tarput(void);
143 static void unfixtarname(char *tptr, char *fp, int l, BOOL first);
146 * tar specific utitlities
149 #if 0 /* Removed to get around gcc 'defined but not used' error. */
152 * Stack routines, push_dir, pop_dir, top_dir_name
155 static BOOL push_dir(stack *tar_dir_stack, file_info2 *dir)
157 dir -> next = tar_dir_stack -> top;
159 tar_dir_stack -> items++;
160 tar_dir_stack -> top = dir;
165 static file_info2 *pop_dir(stack *tar_dir_stack)
169 ptr = tar_dir_stack -> top;
170 if (tar_dir_stack -> top != NULL) {
172 tar_dir_stack -> top = tar_dir_stack -> top -> next;
173 tar_dir_stack -> items--;
181 static char *top_dir_name(stack *tar_dir_stack)
184 return(tar_dir_stack -> top != NULL?tar_dir_stack -> top -> name:NULL);
188 static BOOL sub_dir(char *dir1, char *dir2)
195 #endif /* Removed to get around gcc 'defined but not used' error. */
197 /*******************************************************************
198 Create a string of size size+1 (for the null)
199 *******************************************************************/
200 static char *string_create_s(int size)
204 tmp = (char *)malloc(size+1);
208 DEBUG(0, ("Out of memory in string_create_s\n"));
216 /****************************************************************************
217 Write a tar header to buffer
218 ****************************************************************************/
219 static void writetarheader(int f, char *aname, int size, time_t mtime,
220 char *amode, unsigned char ftype)
226 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
228 memset(hb.dummy, 0, sizeof(hb.dummy));
232 /* write a GNU tar style long header */
234 b = (char *)malloc(l+TBLOCK+100);
236 DEBUG(0,("out of memory\n"));
239 writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L');
240 memset(b, 0, l+TBLOCK+100);
241 fixtarname(b, aname, l);
243 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
244 dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
248 /* use l + 1 to do the null too */
249 fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
252 strlower(hb.dbuf.name);
254 /* write out a "standard" tar format header */
256 hb.dbuf.name[NAMSIZ-1]='\0';
257 safe_strcpy(hb.dbuf.mode, amode, strlen(amode));
258 oct_it(0L, 8, hb.dbuf.uid);
259 oct_it(0L, 8, hb.dbuf.gid);
260 oct_it((long) size, 13, hb.dbuf.size);
261 oct_it((long) mtime, 13, hb.dbuf.mtime);
262 memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
263 memset(hb.dbuf.linkname, 0, NAMSIZ);
264 hb.dbuf.linkflag=ftype;
266 for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
268 oct_it((long) chk, 8, hb.dbuf.chksum);
269 hb.dbuf.chksum[6] = '\0';
271 (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
274 /****************************************************************************
275 Read a tar header into a hblock structure, and validate
276 ***************************************************************************/
277 static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
284 * read in a "standard" tar format header - we're not that interested
285 * in that many fields, though
288 /* check the checksum */
289 for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
294 /* compensate for blanks in chksum header */
295 for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
298 chk += ' ' * sizeof(hb->dbuf.chksum);
300 fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
302 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
303 chk, fchk, hb->dbuf.chksum));
307 DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk));
308 /* for (i = 0; i < sizeof(hb -> dummy); i++) {
309 fprintf(stdout, "%2X ", hb -> dummy[i]);
311 fprintf(stdout, "\n");
312 fprintf(stdout, "%s\n", hb -> dummy);
313 fprintf(stdout, "Tarbuf = %X, hb = %X\n", (int)tarbuf, (int)hb);*/
317 if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
319 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
324 safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3);
326 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
327 unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
328 strlen(hb->dbuf.name) + 1, True);
330 /* can't handle some links at present */
331 if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
332 if (hb->dbuf.linkflag == 0) {
333 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
336 if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
337 /* Do nothing here at the moment. do_tarput will handle this
338 as long as the longlink gets back to it, as it has to advance
339 the buffer pointer, etc */
342 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
348 if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
349 || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
354 finfo->mode=0; /* we don't care about mode at the moment, we'll
355 * just make it a regular file */
357 * Bug fix by richard@sj.co.uk
359 * REC: restore times correctly (as does tar)
360 * We only get the modification time of the file; set the creation time
361 * from the mod. time, and the access time to current time
363 finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
364 finfo->atime = time(NULL);
365 finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
370 /****************************************************************************
371 Write out the tar buffer to tape or wherever
372 ****************************************************************************/
373 static int dotarbuf(int f, char *b, int n)
377 /* This routine and the next one should be the only ones that do write()s */
378 if (tp + n >= tbufsiz)
383 memcpy(tarbuf + tp, b, diff);
384 fail=fail && (1+write(f, tarbuf, tbufsiz));
391 fail=fail && (1 + write(f, b, tbufsiz));
397 memcpy(tarbuf+tp, b, n);
401 return(fail ? writ : 0);
404 /****************************************************************************
405 Write zeros to buffer / tape
406 ****************************************************************************/
407 static void dozerobuf(int f, int n)
409 /* short routine just to write out n zeros to buffer -
410 * used to round files to nearest block
411 * and to do tar EOFs */
415 memset(tarbuf+tp, 0, tbufsiz-tp);
417 write(f, tarbuf, tbufsiz);
418 memset(tarbuf, 0, (tp+=n-tbufsiz));
422 memset(tarbuf+tp, 0, n);
427 /****************************************************************************
429 ****************************************************************************/
430 static void initarbuf()
432 /* initialize tar buffer */
433 tbufsiz=blocksize*TBLOCK;
434 tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */
436 /* reset tar buffer pointer and tar file counter and total dumped */
437 tp=0; ntarf=0; ttarf=0;
440 /****************************************************************************
441 Write two zero blocks at end of file
442 ****************************************************************************/
443 static void dotareof(int f)
445 SMB_STRUCT_STAT stbuf;
446 /* Two zero blocks at end of file, write out full buffer */
448 (void) dozerobuf(f, TBLOCK);
449 (void) dozerobuf(f, TBLOCK);
451 if (sys_fstat(f, &stbuf) == -1)
453 DEBUG(0, ("Couldn't stat file handle\n"));
457 /* Could be a pipe, in which case S_ISREG should fail,
458 * and we should write out at full size */
459 if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
462 /****************************************************************************
463 (Un)mangle DOS pathname, make nonabsolute
464 ****************************************************************************/
465 static void fixtarname(char *tptr, char *fp, int l)
467 /* add a '.' to start of file name, convert from ugly dos \'s in path
468 * to lovely unix /'s :-} */
474 if((skip = skip_multibyte_char( *fp)) != 0) {
479 } else if (skip == 1) {
483 } else if (*fp == '\\') {
494 /****************************************************************************
495 Convert from decimal to octal string
496 ****************************************************************************/
497 static void oct_it (long value, int ndgs, char *p)
499 /* Converts long to octal string, pads with leading zeros */
501 /* skip final null, but do final space */
505 /* Loop does at least one digit */
507 p[--ndgs] = '0' + (char) (value & 7);
510 while (ndgs > 0 && value != 0);
512 /* Do leading zeros */
517 /****************************************************************************
518 Convert from octal string to long
519 ***************************************************************************/
520 static long unoct(char *p, int ndgs)
523 /* Converts octal string to long, ignoring any non-digit */
527 if (isdigit((int)*p))
528 value = (value << 3) | (long) (*p - '0');
536 /****************************************************************************
537 Compare two strings in a slash insensitive way, allowing s1 to match s2
538 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
539 a file in any subdirectory of s1, declare a match.
540 ***************************************************************************/
541 static int strslashcmp(char *s1, char *s2)
547 || tolower(*s1) == tolower(*s2)
548 || (*s1 == '\\' && *s2=='/')
549 || (*s1 == '/' && *s2=='\\'))) {
553 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
556 if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
558 /* ignore trailing slash on s1 */
559 if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
561 /* check for s1 is an "initial" string of s2 */
562 if (*s2 == '/' || *s2 == '\\') return 0;
568 * general smb utility functions
570 /**********************************************************************
571 do_setrtime, set time on a file or dir ...
572 **********************************************************************/
574 static int do_setrtime(char *fname, int mtime, BOOL err_silent)
576 char *inbuf, *outbuf, *p;
579 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
581 name = (char *)malloc(strlen(fname) + 1 + 1);
584 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
590 safe_strcpy(name, "\\", strlen(fname) + 1);
592 safe_strcpy(name, "", strlen(fname) + 1);
593 safe_strcat(name, fname, strlen(fname) + 1);
595 if (fname[strlen(name) - 1] == '\\')
596 name[strlen(name) - 1] = '\0';
598 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
599 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
601 if (!inbuf || !outbuf) {
603 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
609 memset(outbuf, 0, smb_size);
610 set_message(outbuf, 8, 4 + strlen(name), True);
611 CVAL(outbuf, smb_com) = SMBsetatr;
612 SSVAL(outbuf, smb_tid, cnum);
613 cli_setup_pkt(outbuf);
615 SSVAL(outbuf, smb_vwv0, 0);
616 put_dos_date3(outbuf, smb_vwv1, mtime);
620 safe_strcpy(p, name, strlen(name));
621 p+= (strlen(fname)+1);
626 send_smb(Client, outbuf);
627 client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
629 if (CVAL(inbuf,smb_rcls) != 0)
632 DEBUG(0,("%s setting attributes on file %s\n",
633 smb_errstr(inbuf), fname));
635 free(name);free(inbuf);free(outbuf);
640 free(inbuf);free(outbuf);
645 /****************************************************************************
646 Set DOS file attributes
647 ***************************************************************************/
648 static int do_setrattr(char *fname, int attr, int setit)
651 * First get the existing attribs from existing file
658 name = (char *)malloc(strlen(fname) + 1 + 1);
661 DEBUG(0, ("Failed to allocate space in do_setrattr while setting time on file: %s", fname));
666 safe_strcpy(name, "\\", strlen(fname) + 1);
667 safe_strcat(name, fname, strlen(fname) + 1);
669 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
670 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
672 if (!inbuf || !outbuf)
674 DEBUG(0,("out of memory\n"));
679 /* send an smb getatr message */
681 memset(outbuf,0,smb_size);
682 set_message(outbuf,0,2 + strlen(fname),True);
683 CVAL(outbuf,smb_com) = SMBgetatr;
684 SSVAL(outbuf,smb_tid,cnum);
685 cli_setup_pkt(outbuf);
689 safe_strcpy(p,name, strlen(name));
690 p += (strlen(name)+1);
695 send_smb(Client,outbuf);
696 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
698 if (CVAL(inbuf,smb_rcls) != 0)
699 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
702 DEBUG(5,("\nattr 0x%X time %d size %d\n",
703 (int)CVAL(inbuf,smb_vwv0),
704 SVAL(inbuf,smb_vwv1),
705 SVAL(inbuf,smb_vwv3)));
708 fattr=CVAL(inbuf,smb_vwv0);
710 /* combine found attributes with bits to be set or reset */
712 attr=setit ? (fattr | attr) : (fattr & ~attr);
714 /* now try and set attributes by sending smb reset message */
716 /* clear out buffer and start again */
717 memset(outbuf,0,smb_size);
718 set_message(outbuf,8,4 + strlen(name),True);
719 CVAL(outbuf,smb_com) = SMBsetatr;
720 SSVAL(outbuf,smb_tid,cnum);
721 cli_setup_pkt(outbuf);
723 SSVAL(outbuf,smb_vwv0,attr);
727 safe_strcpy(p,name, strlen(name));
728 p += (strlen(name)+1);
733 send_smb(Client,outbuf);
734 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
736 if (CVAL(inbuf,smb_rcls) != 0)
738 DEBUG(0,("%s setting attributes on file %s\n",
739 smb_errstr(inbuf), name));
740 free(name);free(inbuf);free(outbuf);
745 free(inbuf);free(outbuf);
749 /****************************************************************************
750 Create a file on a share
751 ***************************************************************************/
752 static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
755 /* *must* be called with buffer ready malloc'ed */
756 /* open remote file */
758 memset(outbuf,0,smb_size);
759 set_message(outbuf,3,2 + strlen(finfo.name),True);
760 CVAL(outbuf,smb_com) = SMBcreate;
761 SSVAL(outbuf,smb_tid,cnum);
762 cli_setup_pkt(outbuf);
764 SSVAL(outbuf,smb_vwv0,finfo.mode);
765 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
769 safe_strcpy(p,finfo.name, strlen(finfo.name));
771 send_smb(Client,outbuf);
772 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
774 if (CVAL(inbuf,smb_rcls) != 0)
776 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
781 *fnum = SVAL(inbuf,smb_vwv0);
785 /****************************************************************************
786 Write a file to a share
787 ***************************************************************************/
788 static BOOL smbwrite(int fnum, int n, int low, int high, int left,
789 char *bufferp, char *inbuf, char *outbuf)
791 /* *must* be called with buffer ready malloc'ed */
793 memset(outbuf,0,smb_size);
794 set_message(outbuf,5,n + 3,True);
796 memcpy(smb_buf(outbuf)+3, bufferp, n);
798 set_message(outbuf,5,n + 3, False);
799 CVAL(outbuf,smb_com) = SMBwrite;
800 SSVAL(outbuf,smb_tid,cnum);
801 cli_setup_pkt(outbuf);
803 SSVAL(outbuf,smb_vwv0,fnum);
804 SSVAL(outbuf,smb_vwv1,n);
805 SIVAL(outbuf,smb_vwv2,low);
806 SSVAL(outbuf,smb_vwv4,left);
807 CVAL(smb_buf(outbuf),0) = 1;
808 SSVAL(smb_buf(outbuf),1,n);
810 send_smb(Client,outbuf);
811 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
813 if (CVAL(inbuf,smb_rcls) != 0)
815 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
819 if (n != SVAL(inbuf,smb_vwv0))
821 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
822 SVAL(inbuf,smb_vwv0), n));
829 /****************************************************************************
830 Close a file on a share
831 ***************************************************************************/
832 static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
834 /* *must* be called with buffer ready malloc'ed */
836 memset(outbuf,0,smb_size);
837 set_message(outbuf,3,0,True);
838 CVAL(outbuf,smb_com) = SMBclose;
839 SSVAL(outbuf,smb_tid,cnum);
840 cli_setup_pkt(outbuf);
842 SSVAL(outbuf,smb_vwv0,fnum);
843 put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
845 DEBUG(3,("Setting date to %s (0x%lX)",
846 asctime(LocalTime(&finfo.mtime)),
849 send_smb(Client,outbuf);
850 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
852 if (CVAL(inbuf,smb_rcls) != 0)
854 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
862 /****************************************************************************
863 Verify existence of path on share
864 ***************************************************************************/
865 static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
869 memset(outbuf,0,smb_size);
870 set_message(outbuf,0,4 + strlen(fname),True);
871 CVAL(outbuf,smb_com) = SMBchkpth;
872 SSVAL(outbuf,smb_tid,cnum);
873 cli_setup_pkt(outbuf);
877 safe_strcpy(p,fname, strlen(fname));
879 send_smb(Client,outbuf);
880 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
882 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
884 return(CVAL(inbuf,smb_rcls) == 0);
887 /****************************************************************************
888 Make a directory on share
889 ***************************************************************************/
890 static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
892 /* *must* be called with buffer ready malloc'ed */
895 memset(outbuf,0,smb_size);
896 set_message(outbuf,0,2 + strlen(fname),True);
898 CVAL(outbuf,smb_com) = SMBmkdir;
899 SSVAL(outbuf,smb_tid,cnum);
900 cli_setup_pkt(outbuf);
904 safe_strcpy(p,fname, strlen(fname));
906 send_smb(Client,outbuf);
907 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
909 if (CVAL(inbuf,smb_rcls) != 0)
911 DEBUG(0,("%s making remote directory %s\n",
912 smb_errstr(inbuf),fname));
919 /****************************************************************************
920 Ensure a remote path exists (make if necessary)
921 ***************************************************************************/
922 static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
924 /* *must* be called with buffer ready malloc'ed */
925 /* ensures path exists */
927 char *partpath, *ffname;
928 char *p=fname, *basehack;
930 DEBUG(5, ( "Ensurepath called with: %s\n", fname));
932 partpath = string_create_s(strlen(fname));
933 ffname = string_create_s(strlen(fname));
935 if ((partpath == NULL) || (ffname == NULL)){
937 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
944 /* fname copied to ffname so can strtok */
946 safe_strcpy(ffname, fname, strlen(fname));
948 /* do a `basename' on ffname, so don't try and make file name directory */
949 if ((basehack=strrchr(ffname, '\\')) == NULL)
954 p=strtok(ffname, "\\");
958 safe_strcat(partpath, p, strlen(fname) + 1);
960 if (!smbchkpath(partpath, inbuf, outbuf)) {
961 if (!smbmkdir(partpath, inbuf, outbuf))
963 DEBUG(0, ("Error mkdirhiering\n"));
967 DEBUG(3, ("mkdirhiering %s\n", partpath));
971 safe_strcat(partpath, "\\", strlen(fname) + 1);
972 p = strtok(NULL,"/\\");
978 static int padit(char *buf, int bufsize, int padsize)
983 DEBUG(5, ("Padding with %d zeros\n", padsize));
984 memset(buf, 0, bufsize);
985 while( !berr && padsize > 0 ) {
986 bytestowrite= MIN(bufsize, padsize);
987 berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
988 padsize -= bytestowrite;
995 * smbclient functions
997 /****************************************************************************
998 append one remote file to the tar file
999 ***************************************************************************/
1000 static void do_atar(char *rname,char *lname,file_info *finfo1)
1005 char *inbuf,*outbuf;
1007 BOOL close_done = False;
1008 BOOL shallitime=True;
1009 BOOL ignore_close_error = False;
1013 struct timeval tp_start;
1014 GetTimeOfDay(&tp_start);
1016 ftype = '0'; /* An ordinary file ... */
1019 finfo.size = finfo1 -> size;
1020 finfo.mode = finfo1 -> mode;
1021 finfo.uid = finfo1 -> uid;
1022 finfo.gid = finfo1 -> gid;
1023 finfo.mtime = finfo1 -> mtime;
1024 finfo.atime = finfo1 -> atime;
1025 finfo.ctime = finfo1 -> ctime;
1028 finfo.size = def_finfo.size;
1029 finfo.mode = def_finfo.mode;
1030 finfo.uid = def_finfo.uid;
1031 finfo.gid = def_finfo.gid;
1032 finfo.mtime = def_finfo.mtime;
1033 finfo.atime = def_finfo.atime;
1034 finfo.ctime = def_finfo.ctime;
1038 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1039 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1041 if (!inbuf || !outbuf)
1043 DEBUG(0,("out of memory\n"));
1047 memset(outbuf,0,smb_size);
1048 set_message(outbuf,15,1 + strlen(rname),True);
1050 CVAL(outbuf,smb_com) = SMBopenX;
1051 SSVAL(outbuf,smb_tid,cnum);
1052 cli_setup_pkt(outbuf);
1054 SSVAL(outbuf,smb_vwv0,0xFF);
1055 SSVAL(outbuf,smb_vwv2,1);
1056 SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
1057 SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1058 SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
1059 SSVAL(outbuf,smb_vwv8,1);
1061 p = smb_buf(outbuf);
1062 safe_strcpy(p, rname, strlen(rname));
1063 p = skip_string(p,1);
1065 dos_clean_name(rname);
1067 /* do a chained openX with a readX? */
1070 SSVAL(outbuf,smb_vwv0,SMBreadX);
1071 SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
1074 SCVAL(p,smb_wct,10);
1075 SSVAL(p,smb_vwv0,0xFF);
1076 SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
1077 SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
1078 smb_setlen(outbuf,smb_len(outbuf)+11*2+1);
1081 send_smb(Client,outbuf);
1082 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1084 if (CVAL(inbuf,smb_rcls) != 0)
1086 if (CVAL(inbuf,smb_rcls) == ERRSRV &&
1087 SVAL(inbuf,smb_err) == ERRnoresource &&
1088 cli_reopen_connection(inbuf,outbuf))
1090 do_atar(rname,lname,finfo1);
1091 free(inbuf);free(outbuf);
1095 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
1096 free(inbuf);free(outbuf);
1100 finfo.name = string_create_s(strlen(rname));
1101 if (finfo.name == NULL) {
1103 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
1104 free(inbuf); free(outbuf);
1109 safe_strcpy(finfo.name,rname, strlen(rname));
1112 finfo.mode = SVAL(inbuf,smb_vwv3);
1113 finfo.size = IVAL(inbuf,smb_vwv4);
1114 finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
1115 finfo.atime = finfo.ctime = finfo.mtime;
1118 DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
1120 fnum = SVAL(inbuf,smb_vwv2);
1122 if (tar_inc && !(finfo.mode & aARCH))
1124 DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
1127 else if (!tar_system && (finfo.mode & aSYSTEM))
1129 DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
1132 else if (!tar_hidden && (finfo.mode & aHIDDEN))
1134 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
1139 if (SVAL(inbuf,smb_vwv0) == SMBreadX)
1141 p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
1142 datalen = SVAL(p,smb_vwv5);
1143 dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
1151 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1156 /* write a tar header, don't bother with mode - just set to 100644 */
1157 writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
1159 while (nread < finfo.size && !close_done)
1162 static BOOL can_chain_close=True;
1166 DEBUG(3,("nread=%d\n",nread));
1168 /* 3 possible read types. readbraw if a large block is required.
1169 readX + close if not much left and read if neither is supported */
1171 /* we might have already read some data from a chained readX */
1172 if (dataptr && datalen>0)
1175 /* if we can finish now then readX+close */
1176 if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) &&
1177 ((finfo.size - nread) <
1178 (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
1181 /* if we support readraw then use that */
1182 if (method<0 && readbraw_supported)
1185 /* if we can then use readX */
1186 if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
1198 /* use readX + close */
1199 memset(outbuf,0,smb_size);
1200 set_message(outbuf,10,0,True);
1201 CVAL(outbuf,smb_com) = SMBreadX;
1202 SSVAL(outbuf,smb_tid,cnum);
1203 cli_setup_pkt(outbuf);
1207 CVAL(outbuf,smb_vwv0) = SMBclose;
1208 SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
1211 CVAL(outbuf,smb_vwv0) = 0xFF;
1214 SSVAL(outbuf,smb_vwv2,fnum);
1215 SIVAL(outbuf,smb_vwv3,nread);
1216 SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
1217 SSVAL(outbuf,smb_vwv6,0);
1218 SIVAL(outbuf,smb_vwv7,0);
1219 SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
1223 p = smb_buf(outbuf);
1230 /* now set the total packet length */
1231 smb_setlen(outbuf,smb_len(outbuf)+9);
1234 send_smb(Client,outbuf);
1235 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1237 if (CVAL(inbuf,smb_rcls) != 0)
1239 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1244 SVAL(inbuf,smb_vwv0) != SMBclose)
1246 /* NOTE: WfWg sometimes just ignores the chained
1247 command! This seems to break the spec? */
1248 DEBUG(3,("Rejected chained close?\n"));
1250 can_chain_close = False;
1251 ignore_close_error = True;
1254 datalen = SVAL(inbuf,smb_vwv5);
1255 dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
1262 static int readbraw_size = 0xFFFF;
1265 memset(outbuf,0,smb_size);
1266 set_message(outbuf,8,0,True);
1267 CVAL(outbuf,smb_com) = SMBreadbraw;
1268 SSVAL(outbuf,smb_tid,cnum);
1269 cli_setup_pkt(outbuf);
1270 SSVAL(outbuf,smb_vwv0,fnum);
1271 SIVAL(outbuf,smb_vwv1,nread);
1272 SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
1273 SSVAL(outbuf,smb_vwv4,0);
1274 SIVALS(outbuf,smb_vwv5,-1);
1275 send_smb(Client,outbuf);
1277 /* Now read the raw data into the buffer and write it */
1278 if(read_smb_length(Client,inbuf,0) == -1) {
1279 DEBUG(0,("Failed to read length in readbraw\n"));
1283 /* Even though this is not an smb message, smb_len
1284 returns the generic length of an smb message */
1285 datalen = smb_len(inbuf);
1289 /* we got a readbraw error */
1290 DEBUG(4,("readbraw error - reducing size\n"));
1291 readbraw_size = (readbraw_size * 9) / 10;
1293 if (readbraw_size < max_xmit)
1295 DEBUG(0,("disabling readbraw\n"));
1296 readbraw_supported = False;
1303 if(read_data(Client,inbuf,datalen) != datalen) {
1304 DEBUG(0,("Failed to read data in readbraw\n"));
1312 /* we've already read some data with a chained readX */
1316 /* use plain read */
1317 memset(outbuf,0,smb_size);
1318 set_message(outbuf,5,0,True);
1319 CVAL(outbuf,smb_com) = SMBread;
1320 SSVAL(outbuf,smb_tid,cnum);
1321 cli_setup_pkt(outbuf);
1323 SSVAL(outbuf,smb_vwv0,fnum);
1324 SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
1325 SIVAL(outbuf,smb_vwv2,nread);
1326 SSVAL(outbuf,smb_vwv4,finfo.size - nread);
1328 send_smb(Client,outbuf);
1329 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1331 if (CVAL(inbuf,smb_rcls) != 0)
1333 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
1337 datalen = SVAL(inbuf,smb_vwv0);
1338 dataptr = smb_buf(inbuf) + 3;
1343 /* add received bits of file to buffer - dotarbuf will
1344 * write out in 512 byte intervals */
1345 if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
1347 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
1354 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
1362 /* pad tar file with zero's if we couldn't get entire file */
1363 if (nread < finfo.size)
1365 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
1366 if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
1367 DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
1370 /* round tar file to nearest block */
1371 if (finfo.size % TBLOCK)
1372 dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
1374 ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
1380 memset(outbuf,0,smb_size);
1381 set_message(outbuf,3,0,True);
1382 CVAL(outbuf,smb_com) = SMBclose;
1383 SSVAL(outbuf,smb_tid,cnum);
1384 cli_setup_pkt(outbuf);
1386 SSVAL(outbuf,smb_vwv0,fnum);
1387 SIVALS(outbuf,smb_vwv1,-1);
1389 send_smb(Client,outbuf);
1390 client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
1392 if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
1394 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
1395 free(inbuf);free(outbuf);
1402 struct timeval tp_end;
1405 /* if shallitime is true then we didn't skip */
1406 if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
1408 GetTimeOfDay(&tp_end);
1410 (tp_end.tv_sec - tp_start.tv_sec)*1000 +
1411 (tp_end.tv_usec - tp_start.tv_usec)/1000;
1412 get_total_time_ms += this_time;
1413 get_total_size += finfo.size;
1417 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
1418 finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
1422 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1423 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1424 finfo.size / MAX(0.001, (1.024*this_time)),
1425 get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
1428 free(inbuf);free(outbuf);
1431 /****************************************************************************
1432 Append single file to tar file (or not)
1433 ***************************************************************************/
1434 static void do_tar(file_info *finfo)
1438 if (strequal(finfo->name,".."))
1441 /* Is it on the exclude list ? */
1442 if (!tar_excl && clipn) {
1445 DEBUG(5, ("Excl: strlen(cur_dir) = %i\n", strlen(cur_dir)));
1447 safe_strcpy(exclaim, cur_dir, sizeof(pstring));
1448 *(exclaim+strlen(exclaim)-1)='\0';
1450 safe_strcat(exclaim, "\\", sizeof(pstring));
1451 safe_strcat(exclaim, finfo->name, sizeof(exclaim));
1453 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
1455 if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
1457 (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
1459 (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
1461 DEBUG(3,("Skipping file %s\n", exclaim));
1466 if (finfo->mode & aDIR)
1468 pstring saved_curdir;
1470 char *inbuf,*outbuf;
1472 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1473 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1475 if (!inbuf || !outbuf)
1477 DEBUG(0,("out of memory\n"));
1481 safe_strcpy(saved_curdir, cur_dir, sizeof(saved_curdir));
1483 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));
1485 safe_strcat(cur_dir,finfo->name, sizeof(cur_dir));
1486 safe_strcat(cur_dir,"\\", sizeof(cur_dir));
1488 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
1490 /* write a tar directory, don't bother with mode - just set it to
1492 writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
1495 DEBUG(0, (" directory %s\n", cur_dir));
1498 ntarf++; /* Make sure we have a file on there */
1499 safe_strcpy(mtar_mask,cur_dir, sizeof(pstring));
1500 safe_strcat(mtar_mask,"*", sizeof(pstring));
1501 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1502 safe_strcpy(cur_dir,saved_curdir, sizeof(pstring));
1503 free(inbuf);free(outbuf);
1507 safe_strcpy(rname,cur_dir, sizeof(pstring));
1508 safe_strcat(rname,finfo->name, sizeof(pstring));
1509 do_atar(rname,finfo->name,finfo);
1513 /****************************************************************************
1514 Convert from UNIX to DOS file names
1515 ***************************************************************************/
1516 static void unfixtarname(char *tptr, char *fp, int l, BOOL first)
1518 /* remove '.' from start of file name, convert from unix /'s to
1519 * dos \'s in path. Kill any absolute path names. But only if first!
1522 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
1529 if (*fp == '\\' || *fp == '/') {
1537 if(( skip = skip_multibyte_char( *fp )) != 0) {
1542 } else if (skip == 1) {
1546 } else if (*fp == '/') {
1557 #ifndef OLD_DOTARPUT
1559 /****************************************************************************
1560 Move to the next block in the buffer, which may mean read in another set of
1561 blocks. FIXME, we should allow more than one block to be skipped.
1562 ****************************************************************************/
1563 static int next_block(char *ltarbuf, char **bufferp, int bufsiz)
1565 int bufread, total = 0;
1567 DEBUG(5, ("Advancing to next block: %0X\n", *bufferp));
1571 if (*bufferp >= (ltarbuf + bufsiz)) {
1573 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
1577 for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
1579 if (bufread <= 0) { /* An error, return false */
1580 return (total > 0 ? -2 : bufread);
1585 DEBUG(5, ("Total bytes read ... %i\n", total));
1595 /* Skip a file, even if it includes a long file name? */
1596 static int skip_file(int skipsize)
1598 int dsize = skipsize;
1600 DEBUG(5, ("Skiping file. Size = %i\n", skipsize));
1602 /* FIXME, we should skip more than one block at a time */
1606 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1608 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1620 /* We get a file from the tar file and store it */
1621 static int get_file(file_info2 finfo, char * inbuf, char * outbuf)
1623 int fsize = finfo.size;
1624 int fnum, pos = 0, dsize = 0, wsize = 0, rsize = 0;
1626 DEBUG(5, ("get_file: file: %s, size %i\n", finfo.name, fsize));
1628 if (ensurepath(finfo.name, inbuf, outbuf) &&
1629 !smbcreat(finfo, &fnum, inbuf, outbuf))
1631 DEBUG(0, ("abandoning restore\n"));
1635 DEBUG(0, ("restore tar file %s of size %d bytes\n",
1636 finfo.name, finfo.size));
1638 /* read the blocks from the tar file and write to the remote file */
1644 dsize = MIN(tbufsiz - (buffer_p - tarbuf), rsize); /* Calculate the size to write */
1646 DEBUG(5, ("writing %i bytes ...\n", dsize));
1648 if (!smbwrite(fnum, dsize, pos, 0, fsize - pos, buffer_p, inbuf, outbuf)) {
1650 DEBUG(0, ("Error writing remote file\n"));
1657 /* Now figure out how much to move in the buffer */
1659 /* FIXME, we should skip more than one block at a time */
1663 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
1665 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1676 /* Now close the file ... */
1678 if (!smbshut(finfo, fnum, inbuf, outbuf)) {
1680 DEBUG(0, ("Error closing remote file\n"));
1685 /* Now we update the creation date ... */
1687 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
1689 if (!do_setrtime(finfo.name, finfo.mtime, True)) {
1691 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1692 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1701 /* Create a directory. We just ensure that the path exists and return as there
1702 is no file associated with a directory
1704 static int get_dir(file_info2 finfo, char * inbuf, char * outbuf)
1707 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1709 if (!ensurepath(finfo.name, inbuf, outbuf)) {
1711 DEBUG(0, ("Problems creating directory\n"));
1718 /* Get a file with a long file name ... first file has file name, next file
1719 has the data. We only want the long file name, as the loop in do_tarput
1720 will deal with the rest.
1722 static char * get_longfilename(file_info2 finfo)
1724 int namesize = finfo.size + strlen(cur_dir) + 2;
1725 char *longname = malloc(namesize);
1727 int offset = 0, left = finfo.size;
1730 DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
1731 DEBUG(5, ("Len = %i\n", finfo.size));
1734 if (longname == NULL) {
1736 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1737 finfo.size + strlen(cur_dir) + 2));
1741 /* First, add cur_dir to the long file name */
1743 if (strlen(cur_dir) > 0) {
1744 strncpy(longname, cur_dir, namesize);
1745 offset = strlen(cur_dir);
1748 /* Loop through the blocks picking up the name */
1752 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1754 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1759 unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
1760 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
1771 static void do_tarput(void)
1773 file_info2 finfo, *finfo2;
1774 struct timeval tp_start;
1775 char *inbuf, *outbuf, *longfilename = NULL;
1778 GetTimeOfDay(&tp_start);
1780 DEBUG(5, ("RJS do_tarput called ...\n"));
1782 buffer_p = tarbuf + tbufsiz; /* init this to force first read */
1784 #if 0 /* Fix later ... */
1785 if (push_dir(&dir_stack, &finfo)) {
1787 finfo2 = pop_dir(&dir_stack);
1788 inbuf = top_dir_name(&dir_stack); /* FIXME */
1789 if (sub_dir(inbuf, finfo2 -> name)){
1797 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1798 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1800 if (!inbuf || !outbuf) {
1802 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1807 /* Now read through those files ... */
1811 /* Get us to the next block, or the first block first time around */
1813 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1815 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1821 DEBUG(5, ("Reading the next header ...\n"));
1823 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir)) {
1825 case -2: /* Hmm, not good, but not fatal */
1826 DEBUG(0, ("Skipping %s...\n", finfo.name));
1827 if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) &&
1828 !skip_file(finfo.size)) {
1830 DEBUG(0, ("Short file, bailing out...\n"));
1831 free(inbuf); free(outbuf);
1839 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1840 free(inbuf); free(outbuf);
1843 case 0: /* chksum is zero - looks like an EOF */
1844 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1845 free(inbuf); free(outbuf);
1846 return; /* Hmmm, bad here ... */
1853 /* Now, do we have a long file name? */
1855 if (longfilename != NULL) {
1857 free(finfo.name); /* Free the space already allocated */
1858 finfo.name = longfilename;
1859 longfilename = NULL;
1863 /* Well, now we have a header, process the file ... */
1865 /* Should we skip the file? We have the long name as well here */
1868 ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1870 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1872 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1875 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, cliplist[0], finfo.name));
1879 skip_file(finfo.size);
1884 /* We only get this far if we should process the file */
1886 switch (((union hblock *)buffer_p) -> dbuf.linkflag) {
1888 case '0': /* Should use symbolic names--FIXME */
1889 if (!get_file(finfo, inbuf, outbuf)) {
1891 free(inbuf); free(outbuf);
1892 DEBUG(0, ("Abandoning restore\n"));
1899 if (!get_dir(finfo, inbuf, outbuf)) {
1900 free(inbuf); free(outbuf);
1901 DEBUG(0, ("Abandoning restore \n"));
1907 longfilename = get_longfilename(finfo);
1908 if (!longfilename) {
1909 free(inbuf); free(outbuf);
1910 DEBUG(0, ("abandoning restore\n"));
1914 DEBUG(5, ("Long file name: %s\n", longfilename));
1918 skip_file(finfo.size); /* Don't handle these yet */
1930 static void do_tarput()
1933 int nread=0, bufread;
1934 char *inbuf,*outbuf, *longname = NULL;
1937 struct timeval tp_start;
1938 BOOL tskip=False; /* We'll take each file as it comes */
1940 finfo.name = NULL; /* No name in here ... */
1942 GetTimeOfDay(&tp_start);
1944 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1945 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1947 if (!inbuf || !outbuf)
1949 DEBUG(0,("out of memory\n"));
1954 * Must read in tbufsiz dollops
1957 /* These should be the only reads in clitar.c */
1958 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
1962 /* Code to handle a short read.
1963 * We always need a TBLOCK full of stuff
1965 if (bufread % TBLOCK) {
1966 int lchunk=TBLOCK-(bufread % TBLOCK);
1969 /* It's a shorty - a short read that is */
1970 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
1972 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
1974 if (!(lchunk-=lread)) break;
1977 /* If we've reached EOF then that must be a short file */
1978 if (lread<=0) break;
1982 endofbuffer=tarbuf+bufread;
1985 if (fsize<bufread) {
1990 if (fsize==bufread) tskip=False;
1999 int next_header = 1; /* Want at least one header */
2002 if (buffer_p >= endofbuffer) {
2004 bufread = read(tarhandle, tarbuf, tbufsiz);
2008 next_header = 0; /* Don't want the next one ... */
2010 if (finfo.name != NULL) { /* Free the space */
2016 DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n",
2017 (int)tarbuf, (int)buffer_p, (int)endofbuffer));
2018 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
2020 case -2: /* something dodgy but not fatal about this */
2021 DEBUG(0, ("skipping %s...\n", finfo.name));
2022 buffer_p+=TBLOCK; /* header - like a link */
2025 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
2026 free(inbuf); free(outbuf);
2028 case 0: /* chksum is zero - we assume that one all zero
2029 *header block will do for eof */
2031 ("total of %d tar files restored to share\n", ntarf));
2032 free(inbuf); free(outbuf);
2038 /* If we have a longname left from the last time through,
2039 copy it into finfo.name and free it.
2041 The size of a pstring is the limiting factor on filenames
2042 and directory names now. The total pathname length must be
2043 less than sizeof(pstring) - 1, which is currently 1023. */
2045 if (longname != NULL) {
2047 free(finfo.name); /* Free the name in the finfo */
2048 finfo.name = string_create_s(strlen(longname) + 2);
2049 strncpy(finfo.name, longname, strlen(longname) + 1);
2050 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
2056 /* Check if a long-link. We do this before the clip checking
2057 because clip-checking should clip on real name - RJS */
2059 if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
2060 int file_len, first = 0; char *cp;
2062 /* Skip this header, but pick up length, get the name and
2063 fix the name and skip the name. Hmmm, what about end of
2066 longname = malloc(finfo.size + strlen(cur_dir) + 1);
2067 if (longname == NULL) {
2069 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
2070 finfo.size + strlen(cur_dir) + 1)
2072 free(inbuf); free(outbuf);
2077 bzero(longname, finfo.size + strlen(cur_dir) +1);
2079 buffer_p += TBLOCK; /* Skip that longlink header */
2081 /* This needs restructuring ... */
2083 safe_strcpy(longname, cur_dir, strlen(cur_dir) + 1);
2084 cp = longname + strlen(cur_dir);
2085 file_len = finfo.size;
2087 DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n",
2088 (int)longname, (int)cp, file_len));
2090 while (file_len > 0) {
2092 if (buffer_p >= endofbuffer) {
2094 bufread = read(tarhandle, tarbuf, tbufsiz);
2100 unfixtarname(cp, buffer_p, file_len >= TBLOCK?TBLOCK:file_len, first == 0);
2102 first++; /* Not the first anymore */
2103 cp = cp + strlen(cp); /* Move to end of string */
2106 DEBUG(5, ("cp=%0X, file_len=%i\n", (int)cp, file_len));
2107 next_header = 1; /* Force read of next header */
2113 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
2115 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
2117 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
2121 if (finfo.mode & aDIR)
2123 else if ((fsize=finfo.size) % TBLOCK) {
2124 fsize+=TBLOCK-(fsize%TBLOCK);
2126 if (fsize<endofbuffer-buffer_p) {
2131 fsize-=endofbuffer-buffer_p;
2136 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
2138 if (finfo.mode & aDIR)
2141 DEBUG(5, ("Creating directory: %s\n", finfo.name));
2142 DEBUG(0, ("restore tar dir %s of size %d bytes\n",
2143 finfo.name, finfo.size));
2145 if (!ensurepath(finfo.name, inbuf, outbuf))
2147 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
2148 free(inbuf); free(outbuf);
2153 /* Now we update the creation date ... */
2155 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
2157 if (!do_setrtime(finfo.name, finfo.mtime, True)) {
2159 if (tar_real_noisy) {
2160 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
2162 /*return; - Win 95 does not like setting time on dirs */
2174 if (ensurepath(finfo.name, inbuf, outbuf)
2175 && !smbcreat(finfo, &fnum, inbuf, outbuf))
2177 DEBUG(0, ("abandoning restore\n"));
2178 free(inbuf);free(outbuf);
2182 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
2183 finfo.name, finfo.size));
2185 /* if (!finfo.size) {
2186 if (!smbshut(finfo, fnum, inbuf, outbuf)){
2187 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
2188 free(inbuf);free(outbuf);
2194 if ((buffer_p+=TBLOCK) >= endofbuffer) break;
2197 /* write out the file in chunk sized chunks - don't
2198 * go past end of buffer though */
2199 chunk=(fsize-nread < endofbuffer - buffer_p)
2200 ? fsize - nread : endofbuffer - buffer_p;
2203 int minichunk=MIN(chunk, max_xmit-200);
2205 if (!smbwrite(fnum, /* file descriptor */
2207 nread, /* offset low */
2208 0, /* offset high - not implemented */
2209 fsize-nread, /* left - only hint to server */
2214 DEBUG(0, ("Error writing remote file\n"));
2215 free(inbuf); free(outbuf);
2218 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
2220 buffer_p+=minichunk; nread+=minichunk;
2226 if (!smbshut(finfo, fnum, inbuf, outbuf))
2228 DEBUG(0, ("Error closing remote file\n"));
2229 free(inbuf);free(outbuf);
2232 if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
2233 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
2234 (int) buffer_p, (int)(buffer_p - tarbuf)));
2239 } while (buffer_p < endofbuffer);
2242 DEBUG(0, ("premature eof on tar file ?\n"));
2243 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
2245 free(inbuf); free(outbuf);
2250 * samba interactive commands
2253 /****************************************************************************
2255 ***************************************************************************/
2256 void cmd_block(char *dum_in, char *dum_out)
2261 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2263 DEBUG(0, ("blocksize <n>\n"));
2268 if (block < 0 || block > 65535)
2270 DEBUG(0, ("blocksize out of range"));
2275 DEBUG(2,("blocksize is now %d\n", blocksize));
2278 /****************************************************************************
2279 command to set incremental / reset mode
2280 ***************************************************************************/
2281 void cmd_tarmode(char *dum_in, char *dum_out)
2285 while (next_token(NULL,buf,NULL,sizeof(buf))) {
2286 if (strequal(buf, "full"))
2288 else if (strequal(buf, "inc"))
2290 else if (strequal(buf, "reset"))
2292 else if (strequal(buf, "noreset"))
2294 else if (strequal(buf, "system"))
2296 else if (strequal(buf, "nosystem"))
2298 else if (strequal(buf, "hidden"))
2300 else if (strequal(buf, "nohidden"))
2302 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2304 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2306 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2309 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2310 tar_inc ? "incremental" : "full",
2311 tar_system ? "system" : "nosystem",
2312 tar_hidden ? "hidden" : "nohidden",
2313 tar_reset ? "reset" : "noreset",
2314 tar_noisy ? "verbose" : "quiet"));
2318 /****************************************************************************
2319 Feeble attrib command
2320 ***************************************************************************/
2321 void cmd_setmode(char *dum_in, char *dum_out)
2329 attra[0] = attra[1] = 0;
2331 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2333 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2337 safe_strcpy(fname, cur_dir, sizeof(pstring));
2338 safe_strcat(fname, buf, sizeof(pstring));
2340 while (next_token(NULL,buf,NULL,sizeof(buf))) {
2349 case 'r': attra[direct]|=aRONLY;
2351 case 'h': attra[direct]|=aHIDDEN;
2353 case 's': attra[direct]|=aSYSTEM;
2355 case 'a': attra[direct]|=aARCH;
2357 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2362 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2364 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2368 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2369 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2370 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2373 /****************************************************************************
2374 Principal command for creating / extracting
2375 ***************************************************************************/
2376 void cmd_tar(char *inbuf, char *outbuf)
2382 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2384 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
2388 argl=toktocliplist(&argcl, NULL);
2389 if (!tar_parseargs(argcl, argl, buf, 0))
2392 process_tar(inbuf, outbuf);
2397 /****************************************************************************
2398 Command line (option) version
2399 ***************************************************************************/
2400 int process_tar(char *inbuf, char *outbuf)
2416 if (clipn && tar_excl) {
2420 for (i=0; i<clipn; i++) {
2421 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2423 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2424 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2427 if (strrchr(cliplist[i], '\\')) {
2430 safe_strcpy(saved_dir, cur_dir, sizeof(pstring));
2432 if (*cliplist[i]=='\\') {
2433 safe_strcpy(tarmac, cliplist[i], sizeof(pstring));
2435 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2436 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2438 safe_strcpy(cur_dir, tarmac, sizeof(pstring));
2439 *(strrchr(cur_dir, '\\')+1)='\0';
2441 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2442 safe_strcpy(cur_dir,saved_dir, sizeof(pstring));
2444 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2445 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2446 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2451 safe_strcpy(mask,cur_dir, sizeof(pstring));
2452 safe_strcat(mask,"\\*", sizeof(pstring));
2453 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2456 if (ntarf) dotareof(tarhandle);
2460 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2461 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2465 if (must_free_cliplist) {
2467 for (i = 0; i < clipn; ++i) {
2473 must_free_cliplist = False;
2479 /****************************************************************************
2480 Find a token (filename) in a clip list
2481 ***************************************************************************/
2482 static int clipfind(char **aret, int ret, char *tok)
2484 if (aret==NULL) return 0;
2486 /* ignore leading slashes or dots in token */
2487 while(strchr("/\\.", *tok)) tok++;
2492 /* ignore leading slashes or dots in list */
2493 while(strchr("/\\.", *pkey)) pkey++;
2495 if (!strslashcmp(pkey, tok)) return 1;
2501 /****************************************************************************
2502 Read list of files to include from the file and initialize cliplist
2504 ***************************************************************************/
2505 static int read_inclusion_file(char *filename)
2507 FILE *inclusion = NULL;
2508 char buf[MAXPATHLEN + 1];
2509 char *inclusion_buffer = NULL;
2510 int inclusion_buffer_size = 0;
2511 int inclusion_buffer_sofar = 0;
2518 buf[MAXPATHLEN] = '\0'; /* guarantee null-termination */
2519 if ((inclusion = fopen(filename, "r")) == NULL) {
2520 /* XXX It would be better to include a reason for failure, but without
2521 * autoconf, it's hard to use strerror, sys_errlist, etc.
2523 DEBUG(0,("Unable to open inclusion file %s\n", filename));
2527 while ((! error) && (fgets(buf, sizeof(buf)-1, inclusion))) {
2528 if (inclusion_buffer == NULL) {
2529 inclusion_buffer_size = 1024;
2530 if ((inclusion_buffer = malloc(inclusion_buffer_size)) == NULL) {
2531 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
2537 if (buf[strlen(buf)-1] == '\n') {
2538 buf[strlen(buf)-1] = '\0';
2541 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
2542 inclusion_buffer_size *= 2;
2543 inclusion_buffer = Realloc(inclusion_buffer,inclusion_buffer_size);
2544 if (! inclusion_buffer) {
2545 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
2546 inclusion_buffer_size));
2552 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
2553 inclusion_buffer_sofar += strlen(buf) + 1;
2559 /* Allocate an array of clipn + 1 char*'s for cliplist */
2560 cliplist = malloc((clipn + 1) * sizeof(char *));
2561 if (cliplist == NULL) {
2562 DEBUG(0,("failure allocating memory for cliplist\n"));
2565 cliplist[clipn] = NULL;
2566 p = inclusion_buffer;
2567 for (i = 0; (! error) && (i < clipn); i++) {
2568 /* set current item to NULL so array will be null-terminated even if
2569 * malloc fails below. */
2571 if ((tmpstr = (char *)malloc(strlen(p)+1)) == NULL) {
2572 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));
2575 unfixtarname(tmpstr, p, strlen(p) + 1, True);
2576 cliplist[i] = tmpstr;
2577 if ((p = strchr(p, '\000')) == NULL) {
2578 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
2584 must_free_cliplist = True;
2588 if (inclusion_buffer) {
2589 free(inclusion_buffer);
2594 /* We know cliplist is always null-terminated */
2595 for (pp = cliplist; *pp; ++pp) {
2600 must_free_cliplist = False;
2605 /* cliplist and its elements are freed at the end of process_tar. */
2609 /****************************************************************************
2610 Parse tar arguments. Sets tar_type, tar_excl, etc.
2611 ***************************************************************************/
2612 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2614 char tar_clipfl='\0';
2616 /* Reset back to defaults - could be from interactive version
2617 * reset mode and archive mode left as they are though
2628 if (tar_type=='c') {
2629 printf("Tar must be followed by only one of c or x.\n");
2635 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2636 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2647 DEBUG(0,("Option N must be followed by valid file name\n"));
2650 SMB_STRUCT_STAT stbuf;
2651 extern time_t newer_than;
2653 if (dos_stat(argv[Optind], &stbuf) == 0) {
2654 newer_than = stbuf.st_mtime;
2655 DEBUG(1,("Getting files newer than %s",
2656 asctime(LocalTime(&newer_than))));
2659 DEBUG(0,("Error setting newer-than time\n"));
2669 DEBUG(0,("Only one of I,X,F must be specified\n"));
2676 DEBUG(0,("Only one of I,X,F must be specified\n"));
2683 DEBUG(0,("Only one of I,X,F must be specified\n"));
2689 DEBUG(0, ("tar_re_search set\n"));
2690 tar_re_search = True;
2693 DEBUG(0,("Unknown tar option\n"));
2698 printf("Option T must be followed by one of c or x.\n");
2702 /* tar_excl is true if cliplist lists files to be included.
2703 * Both 'I' and 'F' mean include. */
2704 tar_excl=tar_clipfl!='X';
2706 if (tar_clipfl=='F') {
2707 if (argc-Optind-1 != 1) {
2708 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
2711 if (! read_inclusion_file(argv[Optind+1])) {
2714 } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2719 cliplist=argv+Optind+1;
2720 clipn=argc-Optind-1;
2723 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2724 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2730 for (clipcount = 0; clipcount < clipn; clipcount++) {
2732 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2734 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2735 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2740 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);
2741 tmplist[clipcount] = tmpstr;
2742 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2744 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2747 must_free_cliplist = True;
2750 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2754 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2756 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2761 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2765 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2767 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2773 clipn=argc-Optind-1;
2774 cliplist=argv+Optind+1;
2778 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2779 /* Sets tar handle to either 0 or 1, as appropriate */
2780 tarhandle=(tar_type=='c');
2782 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2783 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2785 DEBUG(0,("Error opening local file %s - %s\n",
2786 argv[Optind], strerror(errno)));