2 Unix SMB/Netbios implementation.
5 Copyright (C) Ricky Poulten 1995-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* The following changes developed by Richard Sharpe for Canon Information
22 Systems Research Australia (CISRA) are Copyright (C) 1998 by CISRA and are
23 made available under the terms of the GPL as listed above:
25 1. Restore can now restore files with long file names
26 2. Save now saves directory information so that we can restore
27 directory creation times
28 3. tar now accepts both UNIX path names and DOS path names. I prefer
29 those lovely /'s to those UGLY \'s :-)
40 #define SEPARATORS " \t\n\r"
41 extern int DEBUGLEVEL
;
44 /* These defines are for the do_setrattr routine, to indicate
45 * setting and reseting of file attributes in the function call */
49 static int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
51 #ifndef CLIENT_TIMEOUT
52 #define CLIENT_TIMEOUT (30*1000)
56 static int tp
, ntarf
, tbufsiz
, ttarf
;
57 /* Incremental mode */
59 /* Reset archive bit */
61 /* Include / exclude mode (true=include, false=exclude) */
63 /* Dump files with System attribute */
64 BOOL tar_system
=False
;
65 /* Dump files with Hidden attribute */
67 /* Be noisy - make a catalogue */
71 static char **cliplist
=NULL
;
74 extern file_info def_finfo
;
75 extern BOOL lowercase
;
77 extern BOOL readbraw_supported
;
79 extern pstring cur_dir
;
80 extern int get_total_time_ms
;
81 extern int get_total_size
;
87 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
88 char *amode
, unsigned char ftype
);
89 static void do_atar();
92 static void fixtarname();
93 static int dotarbuf();
94 static void dozerobuf();
95 static void dotareof();
96 static void initarbuf();
97 static int do_setrattr();
99 /* restore functions */
100 static long readtarheader();
102 static void do_tarput();
103 static void unfixtarname();
106 * tar specific utitlities
109 /****************************************************************************
110 Write a tar header to buffer
111 ****************************************************************************/
112 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
113 char *amode
, unsigned char ftype
)
119 DEBUG(5, ("WriteTarHdr, Type = %c, Name = %s\n", ftype
, aname
));
121 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
125 /* write a GNU tar style long header */
127 b
= (char *)malloc(l
+TBLOCK
+100);
129 DEBUG(0,("out of memory\n"));
132 writetarheader(f
, "/./@LongLink", l
+1, 0, " 0 \0", 'L');
133 memset(b
, 0, l
+TBLOCK
+100);
134 fixtarname(b
, aname
, l
+1);
136 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
140 /* use l + 1 to do the null too */
141 fixtarname(hb
.dbuf
.name
, aname
, (l
>= NAMSIZ
) ? NAMSIZ
: l
+ 1);
144 strlower(hb
.dbuf
.name
);
146 /* write out a "standard" tar format header */
148 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
149 strcpy(hb
.dbuf
.mode
, amode
);
150 oct_it(0L, 8, hb
.dbuf
.uid
);
151 oct_it(0L, 8, hb
.dbuf
.gid
);
152 oct_it((long) size
, 13, hb
.dbuf
.size
);
153 oct_it((long) mtime
, 13, hb
.dbuf
.mtime
);
154 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
155 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
156 hb
.dbuf
.linkflag
=ftype
;
158 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
160 oct_it((long) chk
, 8, hb
.dbuf
.chksum
);
161 hb
.dbuf
.chksum
[6] = '\0';
163 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
166 /****************************************************************************
167 Read a tar header into a hblock structure, and validate
168 ***************************************************************************/
169 static long readtarheader(union hblock
*hb
, file_info
*finfo
, char *prefix
)
176 * read in a "standard" tar format header - we're not that interested
177 * in that many fields, though
180 /* check the checksum */
181 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
186 /* compensate for blanks in chksum header */
187 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
190 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
192 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
194 DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
195 chk
, fchk
, hb
->dbuf
.chksum
));
199 DEBUG(0, ("checksums don't match %d %d\n", fchk
, chk
));
203 strcpy(finfo
->name
, prefix
);
205 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
206 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
207 strlen(hb
->dbuf
.name
) + 1);
209 /* can't handle some links at present */
210 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
211 if (hb
->dbuf
.linkflag
== 0) {
212 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
215 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
216 /* Do nothing here at the moment. do_tarput will handle this
217 as long as the longlink gets back to it, as it has to advance
218 the buffer pointer, etc */
221 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
227 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
)
228 || (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\'))
233 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
234 * just make it a regular file */
236 * Bug fix by richard@sj.co.uk
238 * REC: restore times correctly (as does tar)
239 * We only get the modification time of the file; set the creation time
240 * from the mod. time, and the access time to current time
242 finfo
->mtime
= finfo
->ctime
= strtol(hb
->dbuf
.mtime
, NULL
, 8);
243 finfo
->atime
= time(NULL
);
244 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
249 /****************************************************************************
250 Write out the tar buffer to tape or wherever
251 ****************************************************************************/
252 static int dotarbuf(int f
, char *b
, int n
)
256 /* This routine and the next one should be the only ones that do write()s */
257 if (tp
+ n
>= tbufsiz
)
262 memcpy(tarbuf
+ tp
, b
, diff
);
263 fail
=fail
&& (1+write(f
, tarbuf
, tbufsiz
));
270 fail
=fail
&& (1 + write(f
, b
, tbufsiz
));
276 memcpy(tarbuf
+tp
, b
, n
);
280 return(fail
? writ
: 0);
283 /****************************************************************************
284 Write zeros to buffer / tape
285 ****************************************************************************/
286 static void dozerobuf(int f
, int n
)
288 /* short routine just to write out n zeros to buffer -
289 * used to round files to nearest block
290 * and to do tar EOFs */
294 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
296 write(f
, tarbuf
, tbufsiz
);
297 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
301 memset(tarbuf
+tp
, 0, n
);
306 /****************************************************************************
308 ****************************************************************************/
309 static void initarbuf()
311 /* initialize tar buffer */
312 tbufsiz
=blocksize
*TBLOCK
;
313 tarbuf
=malloc(tbufsiz
); /* FIXME: We might not get the buffer */
315 /* reset tar buffer pointer and tar file counter and total dumped */
316 tp
=0; ntarf
=0; ttarf
=0;
319 /****************************************************************************
320 Write two zero blocks at end of file
321 ****************************************************************************/
322 static void dotareof(int f
)
325 /* Two zero blocks at end of file, write out full buffer */
327 (void) dozerobuf(f
, TBLOCK
);
328 (void) dozerobuf(f
, TBLOCK
);
330 if (fstat(f
, &stbuf
) == -1)
332 DEBUG(0, ("Couldn't stat file handle\n"));
336 /* Could be a pipe, in which case S_ISREG should fail,
337 * and we should write out at full size */
338 if (tp
> 0) write(f
, tarbuf
, S_ISREG(stbuf
.st_mode
) ? tp
: tbufsiz
);
341 /****************************************************************************
342 (Un)mangle DOS pathname, make nonabsolute
343 ****************************************************************************/
344 static void fixtarname(char *tptr
, char *fp
, int l
)
346 /* add a '.' to start of file name, convert from ugly dos \'s in path
347 * to lovely unix /'s :-} */
353 if((skip
= skip_multibyte_char( *fp
)) != 0) {
358 } else if (skip
== 1) {
362 } else if (*fp
== '\\') {
373 /****************************************************************************
374 Convert from decimal to octal string
375 ****************************************************************************/
376 static void oct_it (register long value
, register int ndgs
, register char *p
)
378 /* Converts long to octal string, pads with leading zeros */
380 /* skip final null, but do final space */
384 /* Loop does at least one digit */
386 p
[--ndgs
] = '0' + (char) (value
& 7);
389 while (ndgs
> 0 && value
!= 0);
391 /* Do leading zeros */
396 /****************************************************************************
397 Convert from octal string to long
398 ***************************************************************************/
399 static long unoct(char *p
, int ndgs
)
402 /* Converts octal string to long, ignoring any non-digit */
407 value
= (value
<< 3) | (long) (*p
- '0');
415 /****************************************************************************
416 Compare two strings in a slash insensitive way, allowing s1 to match s2
417 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
418 a file in any subdirectory of s1, declare a match.
419 ***************************************************************************/
420 static int strslashcmp(char *s1
, char *s2
)
426 || tolower(*s1
) == tolower(*s2
)
427 || (*s1
== '\\' && *s2
=='/')
428 || (*s1
== '/' && *s2
=='\\'))) {
432 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
435 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\')) return 0;
437 /* ignore trailing slash on s1 */
438 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1)) return 0;
440 /* check for s1 is an "initial" string of s2 */
441 if (*s2
== '/' || *s2
== '\\') return 0;
447 * general smb utility functions
449 /**********************************************************************
450 do_setrtime, set time on a file or dir ...
451 **********************************************************************/
453 static int do_setrtime(char *fname
, int mtime
)
455 char *inbuf
, *outbuf
, *p
;
458 name
= (char *)malloc(strlen(fname
) + 1 + 1);
461 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname
));
470 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
471 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
473 if (!inbuf
|| !outbuf
) {
475 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname
));
480 memset(outbuf
, 0, smb_size
);
481 set_message(outbuf
, 8, 4 + strlen(fname
), True
);
482 CVAL(outbuf
, smb_com
) = SMBsetatr
;
483 SSVAL(outbuf
, smb_tid
, cnum
);
484 cli_setup_pkt(outbuf
);
486 SSVAL(outbuf
, smb_vwv0
, 0);
487 put_dos_date3(outbuf
, smb_vwv1
, mtime
);
492 p
+= (strlen(fname
)+1);
497 send_smb(Client
, outbuf
);
498 client_receive_smb(Client
, inbuf
, CLIENT_TIMEOUT
);
500 if (CVAL(inbuf
,smb_rcls
) != 0)
502 DEBUG(0,("%s setting attributes on file %s\n",
503 smb_errstr(inbuf
), fname
));
504 free(inbuf
);free(outbuf
);
508 free(inbuf
);free(outbuf
);
513 /****************************************************************************
514 Set DOS file attributes
515 ***************************************************************************/
516 static int do_setrattr(char *fname
, int attr
, int setit
)
519 * First get the existing attribs from existing file
530 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
531 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
533 if (!inbuf
|| !outbuf
)
535 DEBUG(0,("out of memory\n"));
539 /* send an smb getatr message */
541 memset(outbuf
,0,smb_size
);
542 set_message(outbuf
,0,2 + strlen(fname
),True
);
543 CVAL(outbuf
,smb_com
) = SMBgetatr
;
544 SSVAL(outbuf
,smb_tid
,cnum
);
545 cli_setup_pkt(outbuf
);
550 p
+= (strlen(fname
)+1);
555 send_smb(Client
,outbuf
);
556 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
558 if (CVAL(inbuf
,smb_rcls
) != 0)
559 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf
)));
562 DEBUG(5,("\nattr 0x%X time %d size %d\n",
563 (int)CVAL(inbuf
,smb_vwv0
),
564 SVAL(inbuf
,smb_vwv1
),
565 SVAL(inbuf
,smb_vwv3
)));
568 fattr
=CVAL(inbuf
,smb_vwv0
);
570 /* combine found attributes with bits to be set or reset */
572 attr
=setit
? (fattr
| attr
) : (fattr
& ~attr
);
574 /* now try and set attributes by sending smb reset message */
576 /* clear out buffer and start again */
577 memset(outbuf
,0,smb_size
);
578 set_message(outbuf
,8,4 + strlen(fname
),True
);
579 CVAL(outbuf
,smb_com
) = SMBsetatr
;
580 SSVAL(outbuf
,smb_tid
,cnum
);
581 cli_setup_pkt(outbuf
);
583 SSVAL(outbuf
,smb_vwv0
,attr
);
588 p
+= (strlen(fname
)+1);
593 send_smb(Client
,outbuf
);
594 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
596 if (CVAL(inbuf
,smb_rcls
) != 0)
598 DEBUG(0,("%s setting attributes on file %s\n",
599 smb_errstr(inbuf
), fname
));
600 free(inbuf
);free(outbuf
);
604 free(inbuf
);free(outbuf
);
608 /****************************************************************************
609 Create a file on a share
610 ***************************************************************************/
611 static BOOL
smbcreat(file_info finfo
, int *fnum
, char *inbuf
, char *outbuf
)
614 /* *must* be called with buffer ready malloc'ed */
615 /* open remote file */
617 memset(outbuf
,0,smb_size
);
618 set_message(outbuf
,3,2 + strlen(finfo
.name
),True
);
619 CVAL(outbuf
,smb_com
) = SMBcreate
;
620 SSVAL(outbuf
,smb_tid
,cnum
);
621 cli_setup_pkt(outbuf
);
623 SSVAL(outbuf
,smb_vwv0
,finfo
.mode
);
624 put_dos_date3(outbuf
,smb_vwv1
,finfo
.mtime
);
628 strcpy(p
,finfo
.name
);
630 send_smb(Client
,outbuf
);
631 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
633 if (CVAL(inbuf
,smb_rcls
) != 0)
635 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),
640 *fnum
= SVAL(inbuf
,smb_vwv0
);
644 /****************************************************************************
645 Write a file to a share
646 ***************************************************************************/
647 static BOOL
smbwrite(int fnum
, int n
, int low
, int high
, int left
,
648 char *bufferp
, char *inbuf
, char *outbuf
)
650 /* *must* be called with buffer ready malloc'ed */
652 memset(outbuf
,0,smb_size
);
653 set_message(outbuf
,5,n
+ 3,True
);
655 memcpy(smb_buf(outbuf
)+3, bufferp
, n
);
657 set_message(outbuf
,5,n
+ 3, False
);
658 CVAL(outbuf
,smb_com
) = SMBwrite
;
659 SSVAL(outbuf
,smb_tid
,cnum
);
660 cli_setup_pkt(outbuf
);
662 SSVAL(outbuf
,smb_vwv0
,fnum
);
663 SSVAL(outbuf
,smb_vwv1
,n
);
664 SIVAL(outbuf
,smb_vwv2
,low
);
665 SSVAL(outbuf
,smb_vwv4
,left
);
666 CVAL(smb_buf(outbuf
),0) = 1;
667 SSVAL(smb_buf(outbuf
),1,n
);
669 send_smb(Client
,outbuf
);
670 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
672 if (CVAL(inbuf
,smb_rcls
) != 0)
674 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf
)));
678 if (n
!= SVAL(inbuf
,smb_vwv0
))
680 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
681 SVAL(inbuf
,smb_vwv0
), n
));
688 /****************************************************************************
689 Close a file on a share
690 ***************************************************************************/
691 static BOOL
smbshut(file_info finfo
, int fnum
, char *inbuf
, char *outbuf
)
693 /* *must* be called with buffer ready malloc'ed */
695 memset(outbuf
,0,smb_size
);
696 set_message(outbuf
,3,0,True
);
697 CVAL(outbuf
,smb_com
) = SMBclose
;
698 SSVAL(outbuf
,smb_tid
,cnum
);
699 cli_setup_pkt(outbuf
);
701 SSVAL(outbuf
,smb_vwv0
,fnum
);
702 put_dos_date3(outbuf
,smb_vwv1
,finfo
.mtime
);
704 DEBUG(3,("Setting date to %s (0x%X)",
705 asctime(LocalTime(&finfo
.mtime
)),
708 send_smb(Client
,outbuf
);
709 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
711 if (CVAL(inbuf
,smb_rcls
) != 0)
713 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf
),
721 /****************************************************************************
722 Verify existence of path on share
723 ***************************************************************************/
724 static BOOL
smbchkpath(char *fname
, char *inbuf
, char *outbuf
)
728 memset(outbuf
,0,smb_size
);
729 set_message(outbuf
,0,4 + strlen(fname
),True
);
730 CVAL(outbuf
,smb_com
) = SMBchkpth
;
731 SSVAL(outbuf
,smb_tid
,cnum
);
732 cli_setup_pkt(outbuf
);
738 send_smb(Client
,outbuf
);
739 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
741 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf
)));
743 return(CVAL(inbuf
,smb_rcls
) == 0);
746 /****************************************************************************
747 Make a directory on share
748 ***************************************************************************/
749 static BOOL
smbmkdir(char *fname
, char *inbuf
, char *outbuf
)
751 /* *must* be called with buffer ready malloc'ed */
754 memset(outbuf
,0,smb_size
);
755 set_message(outbuf
,0,2 + strlen(fname
),True
);
757 CVAL(outbuf
,smb_com
) = SMBmkdir
;
758 SSVAL(outbuf
,smb_tid
,cnum
);
759 cli_setup_pkt(outbuf
);
765 send_smb(Client
,outbuf
);
766 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
768 if (CVAL(inbuf
,smb_rcls
) != 0)
770 DEBUG(0,("%s making remote directory %s\n",
771 smb_errstr(inbuf
),fname
));
778 /****************************************************************************
779 Ensure a remote path exists (make if necessary)
780 ***************************************************************************/
781 static BOOL
ensurepath(char *fname
, char *inbuf
, char *outbuf
)
783 /* *must* be called with buffer ready malloc'ed */
784 /* ensures path exists */
786 pstring partpath
, ffname
;
787 char *p
=fname
, *basehack
;
789 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
793 /* fname copied to ffname so can strtok */
795 strcpy(ffname
, fname
);
797 /* do a `basename' on ffname, so don't try and make file name directory */
798 if ((basehack
=strrchr(ffname
, '\\')) == NULL
)
803 p
=strtok(ffname
, "\\");
809 if (!smbchkpath(partpath
, inbuf
, outbuf
)) {
810 if (!smbmkdir(partpath
, inbuf
, outbuf
))
812 DEBUG(0, ("Error mkdirhiering\n"));
816 DEBUG(3, ("mkdirhiering %s\n", partpath
));
820 strcat(partpath
, "\\");
821 p
= strtok(NULL
,"/\\");
827 int padit(char *buf
, int bufsize
, int padsize
)
832 DEBUG(0, ("Padding with %d zeros\n", padsize
));
833 memset(buf
, 0, bufsize
);
834 while( !berr
&& padsize
> 0 ) {
835 bytestowrite
= MIN(bufsize
, padsize
);
836 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
837 padsize
-= bytestowrite
;
844 * smbclient functions
846 /****************************************************************************
847 append one remote file to the tar file
848 ***************************************************************************/
849 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
856 BOOL close_done
= False
;
857 BOOL shallitime
=True
;
858 BOOL ignore_close_error
= False
;
862 struct timeval tp_start
;
863 GetTimeOfDay(&tp_start
);
865 ftype
= '0'; /* An ordinary file ... */
872 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
873 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
875 if (!inbuf
|| !outbuf
)
877 DEBUG(0,("out of memory\n"));
881 memset(outbuf
,0,smb_size
);
882 set_message(outbuf
,15,1 + strlen(rname
),True
);
884 CVAL(outbuf
,smb_com
) = SMBopenX
;
885 SSVAL(outbuf
,smb_tid
,cnum
);
886 cli_setup_pkt(outbuf
);
888 SSVAL(outbuf
,smb_vwv0
,0xFF);
889 SSVAL(outbuf
,smb_vwv2
,1);
890 SSVAL(outbuf
,smb_vwv3
,(DENY_NONE
<<4));
891 SSVAL(outbuf
,smb_vwv4
,aSYSTEM
| aHIDDEN
);
892 SSVAL(outbuf
,smb_vwv5
,aSYSTEM
| aHIDDEN
);
893 SSVAL(outbuf
,smb_vwv8
,1);
897 p
= skip_string(p
,1);
899 dos_clean_name(rname
);
901 /* do a chained openX with a readX? */
904 SSVAL(outbuf
,smb_vwv0
,SMBreadX
);
905 SSVAL(outbuf
,smb_vwv1
,PTR_DIFF(p
,outbuf
) - 4);
909 SSVAL(p
,smb_vwv0
,0xFF);
910 SSVAL(p
,smb_vwv5
,MIN(max_xmit
-500,finfo
.size
));
911 SSVAL(p
,smb_vwv9
,MIN(0xFFFF,finfo
.size
));
912 smb_setlen(outbuf
,smb_len(outbuf
)+11*2+1);
915 send_smb(Client
,outbuf
);
916 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
918 if (CVAL(inbuf
,smb_rcls
) != 0)
920 if (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
921 SVAL(inbuf
,smb_err
) == ERRnoresource
&&
922 cli_reopen_connection(inbuf
,outbuf
))
924 do_atar(rname
,lname
,finfo1
);
925 free(inbuf
);free(outbuf
);
929 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),rname
));
930 free(inbuf
);free(outbuf
);
934 strcpy(finfo
.name
,rname
);
937 finfo
.mode
= SVAL(inbuf
,smb_vwv3
);
938 finfo
.size
= IVAL(inbuf
,smb_vwv4
);
939 finfo
.mtime
= make_unix_date3(inbuf
+smb_vwv6
);
940 finfo
.atime
= finfo
.ctime
= finfo
.mtime
;
943 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
945 fnum
= SVAL(inbuf
,smb_vwv2
);
947 if (tar_inc
&& !(finfo
.mode
& aARCH
))
949 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
952 else if (!tar_system
&& (finfo
.mode
& aSYSTEM
))
954 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
957 else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
))
959 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
964 if (SVAL(inbuf
,smb_vwv0
) == SMBreadX
)
966 p
= (inbuf
+4+SVAL(inbuf
,smb_vwv1
)) - smb_wct
;
967 datalen
= SVAL(p
,smb_vwv5
);
968 dataptr
= inbuf
+ 4 + SVAL(p
,smb_vwv6
);
976 DEBUG(2,("getting file %s of size %d bytes as a tar file %s",
981 /* write a tar header, don't bother with mode - just set to 100644 */
982 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
984 while (nread
< finfo
.size
&& !close_done
)
987 static BOOL can_chain_close
=True
;
991 DEBUG(3,("nread=%d\n",nread
));
993 /* 3 possible read types. readbraw if a large block is required.
994 readX + close if not much left and read if neither is supported */
996 /* we might have already read some data from a chained readX */
997 if (dataptr
&& datalen
>0)
1000 /* if we can finish now then readX+close */
1001 if (method
<0 && can_chain_close
&& (Protocol
>= PROTOCOL_LANMAN1
) &&
1002 ((finfo
.size
- nread
) <
1003 (max_xmit
- (2*smb_size
+ 13*SIZEOFWORD
+ 300))))
1006 /* if we support readraw then use that */
1007 if (method
<0 && readbraw_supported
)
1010 /* if we can then use readX */
1011 if (method
<0 && (Protocol
>= PROTOCOL_LANMAN1
))
1023 /* use readX + close */
1024 memset(outbuf
,0,smb_size
);
1025 set_message(outbuf
,10,0,True
);
1026 CVAL(outbuf
,smb_com
) = SMBreadX
;
1027 SSVAL(outbuf
,smb_tid
,cnum
);
1028 cli_setup_pkt(outbuf
);
1032 CVAL(outbuf
,smb_vwv0
) = SMBclose
;
1033 SSVAL(outbuf
,smb_vwv1
,PTR_DIFF(smb_buf(outbuf
),outbuf
) - 4);
1036 CVAL(outbuf
,smb_vwv0
) = 0xFF;
1039 SSVAL(outbuf
,smb_vwv2
,fnum
);
1040 SIVAL(outbuf
,smb_vwv3
,nread
);
1041 SSVAL(outbuf
,smb_vwv5
,MIN(max_xmit
-200,finfo
.size
- nread
));
1042 SSVAL(outbuf
,smb_vwv6
,0);
1043 SIVAL(outbuf
,smb_vwv7
,0);
1044 SSVAL(outbuf
,smb_vwv9
,MIN(0xFFFF,finfo
.size
-nread
));
1048 p
= smb_buf(outbuf
);
1055 /* now set the total packet length */
1056 smb_setlen(outbuf
,smb_len(outbuf
)+9);
1059 send_smb(Client
,outbuf
);
1060 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1062 if (CVAL(inbuf
,smb_rcls
) != 0)
1064 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1069 SVAL(inbuf
,smb_vwv0
) != SMBclose
)
1071 /* NOTE: WfWg sometimes just ignores the chained
1072 command! This seems to break the spec? */
1073 DEBUG(3,("Rejected chained close?\n"));
1075 can_chain_close
= False
;
1076 ignore_close_error
= True
;
1079 datalen
= SVAL(inbuf
,smb_vwv5
);
1080 dataptr
= inbuf
+ 4 + SVAL(inbuf
,smb_vwv6
);
1087 static int readbraw_size
= 0xFFFF;
1090 memset(outbuf
,0,smb_size
);
1091 set_message(outbuf
,8,0,True
);
1092 CVAL(outbuf
,smb_com
) = SMBreadbraw
;
1093 SSVAL(outbuf
,smb_tid
,cnum
);
1094 cli_setup_pkt(outbuf
);
1095 SSVAL(outbuf
,smb_vwv0
,fnum
);
1096 SIVAL(outbuf
,smb_vwv1
,nread
);
1097 SSVAL(outbuf
,smb_vwv3
,MIN(finfo
.size
-nread
,readbraw_size
));
1098 SSVAL(outbuf
,smb_vwv4
,0);
1099 SIVALS(outbuf
,smb_vwv5
,-1);
1100 send_smb(Client
,outbuf
);
1102 /* Now read the raw data into the buffer and write it */
1103 if(read_smb_length(Client
,inbuf
,0) == -1) {
1104 DEBUG(0,("Failed to read length in readbraw\n"));
1108 /* Even though this is not an smb message, smb_len
1109 returns the generic length of an smb message */
1110 datalen
= smb_len(inbuf
);
1114 /* we got a readbraw error */
1115 DEBUG(4,("readbraw error - reducing size\n"));
1116 readbraw_size
= (readbraw_size
* 9) / 10;
1118 if (readbraw_size
< max_xmit
)
1120 DEBUG(0,("disabling readbraw\n"));
1121 readbraw_supported
= False
;
1128 if(read_data(Client
,inbuf
,datalen
) != datalen
) {
1129 DEBUG(0,("Failed to read data in readbraw\n"));
1137 /* we've already read some data with a chained readX */
1141 /* use plain read */
1142 memset(outbuf
,0,smb_size
);
1143 set_message(outbuf
,5,0,True
);
1144 CVAL(outbuf
,smb_com
) = SMBread
;
1145 SSVAL(outbuf
,smb_tid
,cnum
);
1146 cli_setup_pkt(outbuf
);
1148 SSVAL(outbuf
,smb_vwv0
,fnum
);
1149 SSVAL(outbuf
,smb_vwv1
,MIN(max_xmit
-200,finfo
.size
- nread
));
1150 SIVAL(outbuf
,smb_vwv2
,nread
);
1151 SSVAL(outbuf
,smb_vwv4
,finfo
.size
- nread
);
1153 send_smb(Client
,outbuf
);
1154 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1156 if (CVAL(inbuf
,smb_rcls
) != 0)
1158 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1162 datalen
= SVAL(inbuf
,smb_vwv0
);
1163 dataptr
= smb_buf(inbuf
) + 3;
1168 /* add received bits of file to buffer - dotarbuf will
1169 * write out in 512 byte intervals */
1170 if (dotarbuf(tarhandle
,dataptr
,datalen
) != datalen
)
1172 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
1179 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
1187 /* pad tar file with zero's if we couldn't get entire file */
1188 if (nread
< finfo
.size
)
1190 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo
.size
, nread
));
1191 if (padit(inbuf
, BUFFER_SIZE
, finfo
.size
- nread
))
1192 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
1195 /* round tar file to nearest block */
1196 if (finfo
.size
% TBLOCK
)
1197 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
1199 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
1205 memset(outbuf
,0,smb_size
);
1206 set_message(outbuf
,3,0,True
);
1207 CVAL(outbuf
,smb_com
) = SMBclose
;
1208 SSVAL(outbuf
,smb_tid
,cnum
);
1209 cli_setup_pkt(outbuf
);
1211 SSVAL(outbuf
,smb_vwv0
,fnum
);
1212 SIVALS(outbuf
,smb_vwv1
,-1);
1214 send_smb(Client
,outbuf
);
1215 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1217 if (!ignore_close_error
&& CVAL(inbuf
,smb_rcls
) != 0)
1219 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf
)));
1220 free(inbuf
);free(outbuf
);
1227 struct timeval tp_end
;
1230 /* if shallitime is true then we didn't skip */
1231 if (tar_reset
) (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
1233 GetTimeOfDay(&tp_end
);
1235 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
1236 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
1237 get_total_time_ms
+= this_time
;
1238 get_total_size
+= finfo
.size
;
1240 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1241 DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
1242 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
1243 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
1246 printf("%10d (%7.1f kb/s) %s\n",
1247 finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
1253 free(inbuf
);free(outbuf
);
1256 /****************************************************************************
1257 Append single file to tar file (or not)
1258 ***************************************************************************/
1259 static void do_tar(file_info
*finfo
)
1263 if (strequal(finfo
->name
,".."))
1266 /* Is it on the exclude list ? */
1267 if (!tar_excl
&& clipn
) {
1270 strcpy(exclaim
, cur_dir
);
1271 *(exclaim
+strlen(exclaim
)-1)='\0';
1273 strcat(exclaim
, "\\");
1274 strcat(exclaim
, finfo
->name
);
1276 if (clipfind(cliplist
, clipn
, exclaim
)) {
1277 DEBUG(3,("Skipping file %s\n", exclaim
));
1282 if (finfo
->mode
& aDIR
)
1284 pstring saved_curdir
;
1286 char *inbuf
,*outbuf
;
1288 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1289 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1291 if (!inbuf
|| !outbuf
)
1293 DEBUG(0,("out of memory\n"));
1297 strcpy(saved_curdir
,cur_dir
);
1299 strcat(cur_dir
,finfo
->name
);
1300 strcat(cur_dir
,"\\");
1302 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
1304 /* write a tar directory, don't bother with mode - just set it to
1306 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
1307 ntarf
++; /* Make sure we have a file on there */
1308 strcpy(mtar_mask
,cur_dir
);
1309 strcat(mtar_mask
,"*");
1310 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1311 strcpy(cur_dir
,saved_curdir
);
1312 free(inbuf
);free(outbuf
);
1316 strcpy(rname
,cur_dir
);
1317 strcat(rname
,finfo
->name
);
1318 do_atar(rname
,finfo
->name
,finfo
);
1322 /****************************************************************************
1323 Convert from UNIX to DOS file names
1324 ***************************************************************************/
1325 static void unfixtarname(char *tptr
, char *fp
, int l
)
1327 /* remove '.' from start of file name, convert from unix /'s to
1328 * dos \'s in path. Kill any absolute path names.
1331 if (*fp
== '.') fp
++;
1332 if (*fp
== '\\' || *fp
== '/') fp
++;
1336 if(( skip
= skip_multibyte_char( *fp
)) != 0) {
1341 } else if (skip
== 1) {
1345 } else if (*fp
== '/') {
1356 /****************************************************************************
1357 Move to the next block in the buffer, which may mean read in another set of
1359 ****************************************************************************/
1360 int next_block(char *tarbuf
, char *bufferp
, int bufsiz
)
1362 int bufread
, total
= 0;
1364 for (bufread
= read(tarhandle
, tarbuf
, bufsiz
); total
+= bufread
; total
< bufsiz
) {
1370 static void do_tarput()
1373 int nread
=0, bufread
;
1374 char *inbuf
,*outbuf
, *longname
= NULL
;
1377 struct timeval tp_start
;
1378 BOOL tskip
=False
; /* We'll take each file as it comes */
1380 GetTimeOfDay(&tp_start
);
1382 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1383 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1385 if (!inbuf
|| !outbuf
)
1387 DEBUG(0,("out of memory\n"));
1392 * Must read in tbufsiz dollops
1395 /* These should be the only reads in clitar.c */
1396 while ((bufread
=read(tarhandle
, tarbuf
, tbufsiz
))>0) {
1397 char *bufferp
, *endofbuffer
;
1400 /* Code to handle a short read.
1401 * We always need a TBLOCK full of stuff
1403 if (bufread
% TBLOCK
) {
1404 int lchunk
=TBLOCK
-(bufread
% TBLOCK
);
1407 /* It's a shorty - a short read that is */
1408 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread
, lchunk
));
1410 while ((lread
=read(tarhandle
, tarbuf
+bufread
, lchunk
))>0) {
1412 if (!(lchunk
-=lread
)) break;
1415 /* If we've reached EOF then that must be a short file */
1416 if (lread
<=0) break;
1420 endofbuffer
=tarbuf
+bufread
;
1423 if (fsize
<bufread
) {
1428 if (fsize
==bufread
) tskip
=False
;
1437 int next_header
= 1; /* Want at least one header */
1440 if (bufferp
>= endofbuffer
) {
1442 bufread
= read(tarhandle
, tarbuf
, tbufsiz
);
1446 next_header
= 0; /* Don't want the next one ... */
1447 switch (readtarheader((union hblock
*) bufferp
, &finfo
, cur_dir
))
1449 case -2: /* something dodgy but not fatal about this */
1450 DEBUG(0, ("skipping %s...\n", finfo
.name
));
1451 bufferp
+=TBLOCK
; /* header - like a link */
1454 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
1455 free(inbuf
); free(outbuf
);
1457 case 0: /* chksum is zero - we assume that one all zero
1458 *header block will do for eof */
1460 ("total of %d tar files restored to share\n", ntarf
));
1461 free(inbuf
); free(outbuf
);
1467 /* If we have a longname left from the last time through,
1468 copy it into finfo.name and free it.
1470 The size of a pstring is the limiting factor on filenames
1471 and directory names now. The total pathname length must be
1472 less than sizeof(pstring) - 1, which is currently 1023. */
1474 if (longname
!= NULL
) {
1476 strncpy(finfo
.name
, longname
, sizeof(pstring
) - 1);
1482 /* Check if a long-link. We do this before the clip checking
1483 because clip-checking should clip on real name - RJS */
1485 if (((union hblock
*)bufferp
) -> dbuf
.linkflag
== 'L') {
1487 /* Skip this header, but pick up length, get the name and
1488 fix the name and skip the name. Hmmm, what about end of
1491 longname
= malloc(finfo
.size
+ strlen(cur_dir
) + 1);
1492 if (longname
== NULL
) {
1494 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1495 finfo
.size
+ strlen(cur_dir
) + 1)
1497 free(inbuf
); free(outbuf
);
1501 bufferp
+= TBLOCK
; /* Skip that longlink header */
1503 /* This needs restructuring ... */
1505 if (bufferp
>= endofbuffer
) {
1507 bufread
= read(tarhandle
, tarbuf
, tbufsiz
);
1513 strncpy(longname
, cur_dir
, strlen(cur_dir
));
1514 unfixtarname(longname
+strlen(cur_dir
), bufferp
, finfo
.size
);
1516 /* Next rounds up to next TBLOCK and takes care of us being right
1517 on a TBLOCK boundary */
1519 bufferp
+= (((finfo
.size
- 1)/TBLOCK
)+1)*TBLOCK
;
1520 next_header
= 1; /* Force read of next header */
1525 && (clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
);
1528 if (finfo
.mode
& aDIR
)
1530 else if ((fsize
=finfo
.size
) % TBLOCK
) {
1531 fsize
+=TBLOCK
-(fsize
%TBLOCK
);
1533 if (fsize
<endofbuffer
-bufferp
) {
1538 fsize
-=endofbuffer
-bufferp
;
1543 DEBUG(5, ("do_tarput: File is: %s\n", finfo
.name
));
1545 if (finfo
.mode
& aDIR
)
1547 if (!ensurepath(finfo
.name
, inbuf
, outbuf
))
1548 /* if (!smbchkpath(finfo.name, inbuf, outbuf)
1549 && !smbmkdir(finfo.name, inbuf, outbuf))*/
1551 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
1552 free(inbuf
); free(outbuf
);
1557 /* Now we update the creation date ... */
1559 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1561 if (!do_setrtime(finfo
.name
, finfo
.mtime
)) {
1563 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1576 if (ensurepath(finfo
.name
, inbuf
, outbuf
)
1577 && !smbcreat(finfo
, &fnum
, inbuf
, outbuf
))
1579 DEBUG(0, ("abandoning restore\n"));
1580 free(inbuf
);free(outbuf
);
1584 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
1585 finfo
.name
,finfo
.size
));
1588 if (!smbshut(finfo
, fnum
, inbuf
, outbuf
)){
1589 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo
.name
));
1590 free(inbuf
);free(outbuf
);
1596 if ((bufferp
+=TBLOCK
) >= endofbuffer
) break;
1599 /* write out the file in chunk sized chunks - don't
1600 * go past end of buffer though */
1601 chunk
=(fsize
-nread
< endofbuffer
- bufferp
)
1602 ? fsize
- nread
: endofbuffer
- bufferp
;
1605 int minichunk
=MIN(chunk
, max_xmit
-200);
1607 if (!smbwrite(fnum
, /* file descriptor */
1609 nread
, /* offset low */
1610 0, /* offset high - not implemented */
1611 fsize
-nread
, /* left - only hint to server */
1616 DEBUG(0, ("Error writing remote file\n"));
1617 free(inbuf
); free(outbuf
);
1620 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo
.name
, fnum
, nread
, minichunk
, chunk
, fsize
));
1622 bufferp
+=minichunk
; nread
+=minichunk
;
1628 if (!smbshut(finfo
, fnum
, inbuf
, outbuf
))
1630 DEBUG(0, ("Error closing remote file\n"));
1631 free(inbuf
);free(outbuf
);
1634 if (fsize
% TBLOCK
) bufferp
+=TBLOCK
- (fsize
% TBLOCK
);
1635 DEBUG(5, ("bufferp is now %d (psn=%d)\n",
1636 (long) bufferp
, (long)(bufferp
- tarbuf
)));
1640 } while (bufferp
< endofbuffer
);
1643 DEBUG(0, ("premature eof on tar file ?\n"));
1644 DEBUG(0,("total of %d tar files restored to share\n", ntarf
));
1646 free(inbuf
); free(outbuf
);
1650 * samba interactive commands
1653 /****************************************************************************
1655 ***************************************************************************/
1656 void cmd_block(void)
1661 if (!next_token(NULL
,buf
,NULL
))
1663 DEBUG(0, ("blocksize <n>\n"));
1668 if (block
< 0 || block
> 65535)
1670 DEBUG(0, ("blocksize out of range"));
1675 DEBUG(2,("blocksize is now %d\n", blocksize
));
1678 /****************************************************************************
1679 command to set incremental / reset mode
1680 ***************************************************************************/
1681 void cmd_tarmode(void)
1685 while (next_token(NULL
,buf
,NULL
)) {
1686 if (strequal(buf
, "full"))
1688 else if (strequal(buf
, "inc"))
1690 else if (strequal(buf
, "reset"))
1692 else if (strequal(buf
, "noreset"))
1694 else if (strequal(buf
, "system"))
1696 else if (strequal(buf
, "nosystem"))
1698 else if (strequal(buf
, "hidden"))
1700 else if (strequal(buf
, "nohidden"))
1702 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1704 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1706 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1709 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1710 tar_inc
? "incremental" : "full",
1711 tar_system
? "system" : "nosystem",
1712 tar_hidden
? "hidden" : "nohidden",
1713 tar_reset
? "reset" : "noreset",
1714 tar_noisy
? "verbose" : "quiet"));
1718 /****************************************************************************
1719 Feeble attrib command
1720 ***************************************************************************/
1721 void cmd_setmode(void)
1729 attra
[0] = attra
[1] = 0;
1731 if (!next_token(NULL
,buf
,NULL
))
1733 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1737 strcpy(fname
, cur_dir
);
1740 while (next_token(NULL
,buf
,NULL
)) {
1749 case 'r': attra
[direct
]|=aRONLY
;
1751 case 'h': attra
[direct
]|=aHIDDEN
;
1753 case 's': attra
[direct
]|=aSYSTEM
;
1755 case 'a': attra
[direct
]|=aARCH
;
1757 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1762 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0)
1764 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1768 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1769 (void) do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1770 (void) do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1773 /****************************************************************************
1774 Principal command for creating / extracting
1775 ***************************************************************************/
1776 void cmd_tar(char *inbuf
, char *outbuf
)
1782 if (!next_token(NULL
,buf
,NULL
))
1784 DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
1788 argl
=toktocliplist(&argcl
, NULL
);
1789 if (!tar_parseargs(argcl
, argl
, buf
, 0))
1792 process_tar(inbuf
, outbuf
);
1797 /****************************************************************************
1798 Command line (option) version
1799 ***************************************************************************/
1800 int process_tar(char *inbuf
, char *outbuf
)
1811 if (clipn
&& tar_excl
) {
1815 for (i
=0; i
<clipn
; i
++) {
1816 DEBUG(0,("arg %d = %s\n", i
, cliplist
[i
]));
1818 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1819 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1822 if (strrchr(cliplist
[i
], '\\')) {
1825 strcpy(saved_dir
, cur_dir
);
1827 if (*cliplist
[i
]=='\\') {
1828 strcpy(tarmac
, cliplist
[i
]);
1830 strcpy(tarmac
, cur_dir
);
1831 strcat(tarmac
, cliplist
[i
]);
1833 strcpy(cur_dir
, tarmac
);
1834 *(strrchr(cur_dir
, '\\')+1)='\0';
1836 do_dir((char *)inbuf
,(char *)outbuf
,tarmac
,attribute
,do_tar
,recurse
, True
);
1837 strcpy(cur_dir
,saved_dir
);
1839 strcpy(tarmac
, cur_dir
);
1840 strcat(tarmac
, cliplist
[i
]);
1841 do_dir((char *)inbuf
,(char *)outbuf
,tarmac
,attribute
,do_tar
,recurse
, True
);
1846 strcpy(mask
,cur_dir
);
1848 do_dir((char *)inbuf
,(char *)outbuf
,mask
,attribute
,do_tar
,recurse
, True
);
1851 if (ntarf
) dotareof(tarhandle
);
1855 DEBUG(0, ("tar: dumped %d tar files\n", ntarf
));
1856 DEBUG(0, ("Total bytes written: %d\n", ttarf
));
1863 /****************************************************************************
1864 Find a token (filename) in a clip list
1865 ***************************************************************************/
1866 int clipfind(char **aret
, int ret
, char *tok
)
1868 if (aret
==NULL
) return 0;
1870 /* ignore leading slashes or dots in token */
1871 while(strchr("/\\.", *tok
)) tok
++;
1876 /* ignore leading slashes or dots in list */
1877 while(strchr("/\\.", *pkey
)) pkey
++;
1879 if (!strslashcmp(pkey
, tok
)) return 1;
1885 /****************************************************************************
1886 Parse tar arguments. Sets tar_type, tar_excl, etc.
1887 ***************************************************************************/
1888 int tar_parseargs(int argc
, char *argv
[], char *Optarg
, int Optind
)
1890 char tar_clipfl
='\0';
1892 /* Reset back to defaults - could be from interactive version
1893 * reset mode and archive mode left as they are though
1904 if (tar_type
=='c') {
1905 printf("Tar must be followed by only one of c or x.\n");
1911 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1912 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1923 DEBUG(0,("Option N must be followed by valid file name\n"));
1927 extern time_t newer_than
;
1929 if (sys_stat(argv
[Optind
], &stbuf
) == 0) {
1930 newer_than
= stbuf
.st_mtime
;
1931 DEBUG(1,("Getting files newer than %s",
1932 asctime(LocalTime(&newer_than
))));
1935 DEBUG(0,("Error setting newer-than time\n"));
1945 DEBUG(0,("Only one of I,X must be specified\n"));
1952 DEBUG(0,("Only one of I,X must be specified\n"));
1958 DEBUG(0,("Unknown tar option\n"));
1963 printf("Option T must be followed by one of c or x.\n");
1967 tar_excl
=tar_clipfl
!='X';
1968 if (Optind
+1<argc
) {
1973 cliplist
=argv
+Optind
+1;
1974 clipn
=argc
-Optind
-1;
1977 if ((tmplist
=malloc(clipn
*sizeof(char *))) == NULL
) {
1978 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
1984 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1986 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1988 if ((tmpstr
= (char *)malloc(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1989 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
1994 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1);
1995 tmplist
[clipcount
] = tmpstr
;
1996 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1998 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
2002 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
2003 /* Sets tar handle to either 0 or 1, as appropriate */
2004 tarhandle
=(tar_type
=='c');
2006 if ((tar_type
=='x' && (tarhandle
= open(argv
[Optind
], O_RDONLY
)) == -1)
2007 || (tar_type
=='c' && (tarhandle
=creat(argv
[Optind
], 0644)) < 0))
2009 DEBUG(0,("Error opening local file %s - %s\n",
2010 argv
[Optind
], strerror(errno
)));