2 Unix SMB/CIFS implementation.
4 Copyright (C) Ricky Poulten 1995-1998
5 Copyright (C) Richard Sharpe 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)
24 1. Restore can now restore files with long file names
25 2. Save now saves directory information so that we can restore
26 directory creation times
27 3. tar now accepts both UNIX path names and DOS path names. I prefer
28 those lovely /'s to those UGLY \'s :-)
29 4. the files to exclude can be specified as a regular expression by adding
30 an r flag to the other tar flags. Eg:
32 -TcrX file.tar "*.(obj|exe)"
34 will skip all .obj and .exe files
40 #include "../client/client_proto.h"
42 static int clipfind(char **aret
, int ret
, char *tok
);
44 typedef struct file_info_struct file_info2
;
46 struct file_info_struct
{
51 /* These times are normally kept in GMT */
55 char *name
; /* This is dynamically allocate */
57 file_info2
*next
, *prev
; /* Used in the stack ... */
65 #define SEPARATORS " \t\n\r"
66 extern struct cli_state
*cli
;
68 /* These defines are for the do_setrattr routine, to indicate
69 * setting and reseting of file attributes in the function call */
73 static uint16 attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
75 #ifndef CLIENT_TIMEOUT
76 #define CLIENT_TIMEOUT (30*1000)
79 static char *tarbuf
, *buffer_p
;
80 static int tp
, ntarf
, tbufsiz
;
82 /* Incremental mode */
83 static BOOL tar_inc
=False
;
84 /* Reset archive bit */
85 static BOOL tar_reset
=False
;
86 /* Include / exclude mode (true=include, false=exclude) */
87 static BOOL tar_excl
=True
;
88 /* use regular expressions for search on file names */
89 static BOOL tar_re_search
=False
;
93 /* Do not dump anything, just calculate sizes */
94 static BOOL dry_run
=False
;
95 /* Dump files with System attribute */
96 static BOOL tar_system
=True
;
97 /* Dump files with Hidden attribute */
98 static BOOL tar_hidden
=True
;
99 /* Be noisy - make a catalogue */
100 static BOOL tar_noisy
=True
;
101 static BOOL tar_real_noisy
=False
; /* Don't want to be really noisy by default */
104 static char **cliplist
=NULL
;
106 static BOOL must_free_cliplist
= False
;
108 extern file_info def_finfo
;
109 extern BOOL lowercase
;
111 extern BOOL readbraw_supported
;
113 extern pstring cur_dir
;
114 extern int get_total_time_ms
;
115 extern int get_total_size
;
117 static int blocksize
=20;
118 static int tarhandle
;
120 static void writetarheader(int f
, const char *aname
, SMB_BIG_UINT size
, time_t mtime
,
121 const char *amode
, unsigned char ftype
);
122 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
);
123 static void do_tar(file_info
*finfo
);
124 static void oct_it(SMB_BIG_UINT value
, int ndgs
, char *p
);
125 static void fixtarname(char *tptr
, const char *fp
, size_t l
);
126 static int dotarbuf(int f
, char *b
, int n
);
127 static void dozerobuf(int f
, int n
);
128 static void dotareof(int f
);
129 static void initarbuf(void);
131 /* restore functions */
132 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
);
133 static long unoct(char *p
, int ndgs
);
134 static void do_tarput(void);
135 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
);
138 * tar specific utitlities
141 /*******************************************************************
142 Create a string of size size+1 (for the null)
143 *******************************************************************/
145 static char *string_create_s(int size
)
149 tmp
= (char *)malloc(size
+1);
152 DEBUG(0, ("Out of memory in string_create_s\n"));
158 /****************************************************************************
159 Write a tar header to buffer
160 ****************************************************************************/
162 static void writetarheader(int f
, const char *aname
, SMB_BIG_UINT size
, time_t mtime
,
163 const char *amode
, unsigned char ftype
)
169 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype
, (double)size
, aname
));
171 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
174 /* We will be prepending a '.' in fixtarheader so use +2 to
175 * take care of the . and terminating zero. JRA.
178 /* write a GNU tar style long header */
180 b
= (char *)malloc(l
+TBLOCK
+100);
182 DEBUG(0,("out of memory\n"));
185 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
186 memset(b
, 0, l
+TBLOCK
+100);
187 fixtarname(b
, aname
, l
+2);
189 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
190 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
194 fixtarname(hb
.dbuf
.name
, aname
, (l
+2 >= NAMSIZ
) ? NAMSIZ
: l
+ 2);
197 strlower_m(hb
.dbuf
.name
);
199 /* write out a "standard" tar format header */
201 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
202 safe_strcpy(hb
.dbuf
.mode
, amode
, sizeof(hb
.dbuf
.mode
)-1);
203 oct_it((SMB_BIG_UINT
)0, 8, hb
.dbuf
.uid
);
204 oct_it((SMB_BIG_UINT
)0, 8, hb
.dbuf
.gid
);
205 oct_it((SMB_BIG_UINT
) size
, 13, hb
.dbuf
.size
);
206 if (size
> (SMB_BIG_UINT
)077777777777LL) {
208 /* This is a non-POSIX compatible extention to store files
211 memset(hb
.dbuf
.size
, 0, 4);
213 for (i
= 8, jp
=(char*)&size
; i
; i
--)
214 hb
.dbuf
.size
[i
+3] = *(jp
++);
216 oct_it((SMB_BIG_UINT
) mtime
, 13, hb
.dbuf
.mtime
);
217 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
218 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
219 hb
.dbuf
.linkflag
=ftype
;
221 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;)
224 oct_it((SMB_BIG_UINT
) chk
, 8, hb
.dbuf
.chksum
);
225 hb
.dbuf
.chksum
[6] = '\0';
227 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
230 /****************************************************************************
231 Read a tar header into a hblock structure, and validate
232 ***************************************************************************/
234 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
)
241 * read in a "standard" tar format header - we're not that interested
242 * in that many fields, though
245 /* check the checksum */
246 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;)
252 /* compensate for blanks in chksum header */
253 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
256 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
258 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
260 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
261 chk
, fchk
, hb
->dbuf
.chksum
));
264 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
265 dump_data(5, (char *)hb
- TBLOCK
, TBLOCK
*3);
269 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
270 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
274 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
276 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
277 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
278 strlen(hb
->dbuf
.name
) + 1, True
);
280 /* can't handle some links at present */
281 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
282 if (hb
->dbuf
.linkflag
== 0) {
283 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
286 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
287 /* Do nothing here at the moment. do_tarput will handle this
288 as long as the longlink gets back to it, as it has to advance
289 the buffer pointer, etc */
291 DEBUG(0, ("this tar file appears to contain some kind \
292 of link other than a GNUtar Longlink - ignoring\n"));
298 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
) ||
299 (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\')) {
302 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
303 * just make it a regular file */
307 * Bug fix by richard@sj.co.uk
309 * REC: restore times correctly (as does tar)
310 * We only get the modification time of the file; set the creation time
311 * from the mod. time, and the access time to current time
313 finfo
->mtime
= finfo
->ctime
= strtol(hb
->dbuf
.mtime
, NULL
, 8);
314 finfo
->atime
= time(NULL
);
315 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
320 /****************************************************************************
321 Write out the tar buffer to tape or wherever
322 ****************************************************************************/
324 static int dotarbuf(int f
, char *b
, int n
)
331 /* This routine and the next one should be the only ones that do write()s */
332 if (tp
+ n
>= tbufsiz
) {
336 memcpy(tarbuf
+ tp
, b
, diff
);
337 fail
=fail
&& (1+write(f
, tarbuf
, tbufsiz
));
342 while (n
>= tbufsiz
) {
343 fail
=fail
&& (1 + write(f
, b
, tbufsiz
));
350 memcpy(tarbuf
+tp
, b
, n
);
354 return(fail
? writ
: 0);
357 /****************************************************************************
358 Write zeros to buffer / tape
359 ****************************************************************************/
361 static void dozerobuf(int f
, int n
)
363 /* short routine just to write out n zeros to buffer -
364 * used to round files to nearest block
365 * and to do tar EOFs */
370 if (n
+tp
>= tbufsiz
) {
371 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
372 write(f
, tarbuf
, tbufsiz
);
373 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
375 memset(tarbuf
+tp
, 0, n
);
380 /****************************************************************************
382 ****************************************************************************/
384 static void initarbuf(void)
386 /* initialize tar buffer */
387 tbufsiz
=blocksize
*TBLOCK
;
388 tarbuf
=malloc(tbufsiz
); /* FIXME: We might not get the buffer */
390 /* reset tar buffer pointer and tar file counter and total dumped */
391 tp
=0; ntarf
=0; ttarf
=0;
394 /****************************************************************************
395 Write two zero blocks at end of file
396 ****************************************************************************/
398 static void dotareof(int f
)
400 SMB_STRUCT_STAT stbuf
;
401 /* Two zero blocks at end of file, write out full buffer */
406 (void) dozerobuf(f
, TBLOCK
);
407 (void) dozerobuf(f
, TBLOCK
);
409 if (sys_fstat(f
, &stbuf
) == -1) {
410 DEBUG(0, ("Couldn't stat file handle\n"));
414 /* Could be a pipe, in which case S_ISREG should fail,
415 * and we should write out at full size */
417 write(f
, tarbuf
, S_ISREG(stbuf
.st_mode
) ? tp
: tbufsiz
);
420 /****************************************************************************
421 (Un)mangle DOS pathname, make nonabsolute
422 ****************************************************************************/
424 static void fixtarname(char *tptr
, const char *fp
, size_t l
)
426 /* add a '.' to start of file name, convert from ugly dos \'s in path
427 * to lovely unix /'s :-} */
431 StrnCpy(tptr
, fp
, l
-1);
432 string_replace(tptr
, '\\', '/');
435 /****************************************************************************
436 Convert from decimal to octal string
437 ****************************************************************************/
439 static void oct_it (SMB_BIG_UINT value
, int ndgs
, char *p
)
441 /* Converts long to octal string, pads with leading zeros */
443 /* skip final null, but do final space */
447 /* Loop does at least one digit */
449 p
[--ndgs
] = '0' + (char) (value
& 7);
451 } while (ndgs
> 0 && value
!= 0);
453 /* Do leading zeros */
458 /****************************************************************************
459 Convert from octal string to long
460 ***************************************************************************/
462 static long unoct(char *p
, int ndgs
)
465 /* Converts octal string to long, ignoring any non-digit */
468 if (isdigit((int)*p
))
469 value
= (value
<< 3) | (long) (*p
- '0');
477 /****************************************************************************
478 Compare two strings in a slash insensitive way, allowing s1 to match s2
479 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
480 a file in any subdirectory of s1, declare a match.
481 ***************************************************************************/
483 static int strslashcmp(char *s1
, char *s2
)
487 while(*s1
&& *s2
&& (*s1
== *s2
|| tolower(*s1
) == tolower(*s2
) ||
488 (*s1
== '\\' && *s2
=='/') || (*s1
== '/' && *s2
=='\\'))) {
492 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
495 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\'))
498 /* ignore trailing slash on s1 */
499 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1))
502 /* check for s1 is an "initial" string of s2 */
503 if ((*s2
== '/' || *s2
== '\\') && !*s1
)
509 /****************************************************************************
510 Ensure a remote path exists (make if necessary)
511 ***************************************************************************/
513 static BOOL
ensurepath(char *fname
)
515 /* *must* be called with buffer ready malloc'ed */
516 /* ensures path exists */
518 char *partpath
, *ffname
;
519 char *p
=fname
, *basehack
;
521 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
523 partpath
= string_create_s(strlen(fname
));
524 ffname
= string_create_s(strlen(fname
));
526 if ((partpath
== NULL
) || (ffname
== NULL
)){
527 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
533 /* fname copied to ffname so can strtok */
535 safe_strcpy(ffname
, fname
, strlen(fname
));
537 /* do a `basename' on ffname, so don't try and make file name directory */
538 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
)
543 p
=strtok(ffname
, "\\");
546 safe_strcat(partpath
, p
, strlen(fname
) + 1);
548 if (!cli_chkpath(cli
, partpath
)) {
549 if (!cli_mkdir(cli
, partpath
)) {
550 DEBUG(0, ("Error mkdirhiering\n"));
553 DEBUG(3, ("mkdirhiering %s\n", partpath
));
557 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
558 p
= strtok(NULL
,"/\\");
564 static int padit(char *buf
, int bufsize
, int padsize
)
569 DEBUG(5, ("Padding with %d zeros\n", padsize
));
570 memset(buf
, 0, bufsize
);
571 while( !berr
&& padsize
> 0 ) {
572 bytestowrite
= MIN(bufsize
, padsize
);
573 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
574 padsize
-= bytestowrite
;
580 static void do_setrattr(char *name
, uint16 attr
, int set
)
584 if (!cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
)) return;
586 if (set
== ATTRSET
) {
589 attr
= oldattr
& ~attr
;
592 if (!cli_setatr(cli
, name
, attr
, 0)) {
593 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
597 /****************************************************************************
598 append one remote file to the tar file
599 ***************************************************************************/
601 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
604 SMB_BIG_UINT nread
=0;
607 BOOL close_done
= False
;
608 BOOL shallitime
=True
;
610 int read_size
= 65520;
613 struct timeval tp_start
;
615 GetTimeOfDay(&tp_start
);
617 ftype
= '0'; /* An ordinary file ... */
620 finfo
.size
= finfo1
-> size
;
621 finfo
.mode
= finfo1
-> mode
;
622 finfo
.uid
= finfo1
-> uid
;
623 finfo
.gid
= finfo1
-> gid
;
624 finfo
.mtime
= finfo1
-> mtime
;
625 finfo
.atime
= finfo1
-> atime
;
626 finfo
.ctime
= finfo1
-> ctime
;
627 finfo
.name
= finfo1
-> name
;
629 finfo
.size
= def_finfo
.size
;
630 finfo
.mode
= def_finfo
.mode
;
631 finfo
.uid
= def_finfo
.uid
;
632 finfo
.gid
= def_finfo
.gid
;
633 finfo
.mtime
= def_finfo
.mtime
;
634 finfo
.atime
= def_finfo
.atime
;
635 finfo
.ctime
= def_finfo
.ctime
;
636 finfo
.name
= def_finfo
.name
;
640 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo
.name
,
641 (double)finfo
.size
));
643 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
648 fnum
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
);
650 dos_clean_name(rname
);
653 DEBUG(0,("%s opening remote file %s (%s)\n",
654 cli_errstr(cli
),rname
, cur_dir
));
658 finfo
.name
= string_create_s(strlen(rname
));
659 if (finfo
.name
== NULL
) {
660 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
664 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
666 if (!cli_getattrE(cli
, fnum
, &finfo
.mode
, &finfo
.size
, NULL
, &finfo
.atime
, &finfo
.mtime
)) {
667 DEBUG(0, ("getattrE: %s\n", cli_errstr(cli
)));
670 finfo
.ctime
= finfo
.mtime
;
673 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
675 if (tar_inc
&& !(finfo
.mode
& aARCH
)) {
676 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
678 } else if (!tar_system
&& (finfo
.mode
& aSYSTEM
)) {
679 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
681 } else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
)) {
682 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
685 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
686 finfo
.name
, (double)finfo
.size
, lname
));
688 /* write a tar header, don't bother with mode - just set to 100644 */
689 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
691 while (nread
< finfo
.size
&& !close_done
) {
693 DEBUG(3,("nread=%.0f\n",(double)nread
));
695 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
698 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
704 /* if file size has increased since we made file size query, truncate
705 read so tar header for this file will be correct.
708 if (nread
> finfo
.size
) {
709 datalen
-= nread
- finfo
.size
;
710 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
711 finfo
.name
, (double)finfo
.size
));
714 /* add received bits of file to buffer - dotarbuf will
715 * write out in 512 byte intervals */
717 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
718 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
723 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
730 /* pad tar file with zero's if we couldn't get entire file */
731 if (nread
< finfo
.size
) {
732 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
733 (double)finfo
.size
, (int)nread
));
734 if (padit(data
, sizeof(data
), finfo
.size
- nread
))
735 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
738 /* round tar file to nearest block */
739 if (finfo
.size
% TBLOCK
)
740 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
742 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
746 cli_close(cli
, fnum
);
749 struct timeval tp_end
;
752 /* if shallitime is true then we didn't skip */
753 if (tar_reset
&& !dry_run
)
754 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
756 GetTimeOfDay(&tp_end
);
757 this_time
= (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 + (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
758 get_total_time_ms
+= this_time
;
759 get_total_size
+= finfo
.size
;
762 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
763 (double)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
767 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
768 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
769 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
770 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
774 /****************************************************************************
775 Append single file to tar file (or not)
776 ***************************************************************************/
778 static void do_tar(file_info
*finfo
)
782 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
785 /* Is it on the exclude list ? */
786 if (!tar_excl
&& clipn
) {
789 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir
)));
791 pstrcpy(exclaim
, cur_dir
);
792 *(exclaim
+strlen(exclaim
)-1)='\0';
794 pstrcat(exclaim
, "\\");
795 pstrcat(exclaim
, finfo
->name
);
797 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
799 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
801 (tar_re_search
&& !regexec(preg
, exclaim
, 0, NULL
, 0))) {
803 (tar_re_search
&& mask_match_list(exclaim
, cliplist
, clipn
, True
))) {
805 DEBUG(3,("Skipping file %s\n", exclaim
));
810 if (finfo
->mode
& aDIR
) {
811 pstring saved_curdir
;
814 pstrcpy(saved_curdir
, cur_dir
);
816 DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, \
817 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
818 (int)sizeof(cur_dir
), (int)strlen(cur_dir
),
819 (int)strlen(finfo
->name
), finfo
->name
, cur_dir
));
821 pstrcat(cur_dir
,finfo
->name
);
822 pstrcat(cur_dir
,"\\");
824 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
826 /* write a tar directory, don't bother with mode - just set it to
828 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
830 DEBUG(0,(" directory %s\n", cur_dir
));
832 ntarf
++; /* Make sure we have a file on there */
833 pstrcpy(mtar_mask
,cur_dir
);
834 pstrcat(mtar_mask
,"*");
835 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
836 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
837 pstrcpy(cur_dir
,saved_curdir
);
839 pstrcpy(rname
,cur_dir
);
840 pstrcat(rname
,finfo
->name
);
841 do_atar(rname
,finfo
->name
,finfo
);
845 /****************************************************************************
846 Convert from UNIX to DOS file names
847 ***************************************************************************/
849 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
)
851 /* remove '.' from start of file name, convert from unix /'s to
852 * dos \'s in path. Kill any absolute path names. But only if first!
855 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
862 if (*fp
== '\\' || *fp
== '/') {
868 safe_strcpy(tptr
, fp
, l
);
869 string_replace(tptr
, '/', '\\');
872 /****************************************************************************
873 Move to the next block in the buffer, which may mean read in another set of
874 blocks. FIXME, we should allow more than one block to be skipped.
875 ****************************************************************************/
877 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
879 int bufread
, total
= 0;
881 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
885 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
887 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
890 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
891 * Fixes bug where read can return short if coming from
895 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
898 while (total
< bufsiz
) {
899 if (bufread
< 0) { /* An error, return false */
900 return (total
> 0 ? -2 : bufread
);
908 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
912 DEBUG(5, ("Total bytes read ... %i\n", total
));
920 /* Skip a file, even if it includes a long file name? */
921 static int skip_file(int skipsize
)
923 int dsize
= skipsize
;
925 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
927 /* FIXME, we should skip more than one block at a time */
930 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
931 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
940 /*************************************************************
941 Get a file from the tar file and store it.
942 When this is called, tarbuf already contains the first
943 file block. This is a bit broken & needs fixing.
944 **************************************************************/
946 static int get_file(file_info2 finfo
)
948 int fnum
= -1, pos
= 0, dsize
= 0, bpos
= 0;
949 SMB_BIG_UINT rsize
= 0;
951 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo
.name
, (double)finfo
.size
));
953 if (ensurepath(finfo
.name
) &&
954 (fnum
=cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
)) == -1) {
955 DEBUG(0, ("abandoning restore\n"));
959 /* read the blocks from the tar file and write to the remote file */
961 rsize
= finfo
.size
; /* This is how much to write */
965 /* We can only write up to the end of the buffer */
966 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
967 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
968 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
970 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
971 DEBUG(0, ("Error writing remote file\n"));
978 /* Now figure out how much to move in the buffer */
980 /* FIXME, we should skip more than one block at a time */
982 /* First, skip any initial part of the part written that is left over */
983 /* from the end of the first TBLOCK */
985 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
986 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
989 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
990 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
996 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
997 * If the file being extracted is an exact multiple of
998 * TBLOCK bytes then we don't want to extract the next
999 * block from the tarfile here, as it will be done in
1000 * the caller of get_file().
1003 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1004 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1006 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1007 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1016 /* Now close the file ... */
1018 if (!cli_close(cli
, fnum
)) {
1019 DEBUG(0, ("Error closing remote file\n"));
1023 /* Now we update the creation date ... */
1024 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1026 if (!cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime
)) {
1027 if (tar_real_noisy
) {
1028 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1029 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1034 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo
.name
, (double)finfo
.size
));
1038 /* Create a directory. We just ensure that the path exists and return as there
1039 is no file associated with a directory
1041 static int get_dir(file_info2 finfo
)
1043 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1045 if (!ensurepath(finfo
.name
)) {
1046 DEBUG(0, ("Problems creating directory\n"));
1053 /* Get a file with a long file name ... first file has file name, next file
1054 has the data. We only want the long file name, as the loop in do_tarput
1055 will deal with the rest.
1057 static char *get_longfilename(file_info2 finfo
)
1059 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1061 int namesize
= finfo
.size
+ strlen(cur_dir
) + 2;
1062 char *longname
= malloc(namesize
);
1063 int offset
= 0, left
= finfo
.size
;
1066 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1067 DEBUG(5, ("Len = %.0f\n", (double)finfo
.size
));
1069 if (longname
== NULL
) {
1070 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize
));
1074 /* First, add cur_dir to the long file name */
1076 if (strlen(cur_dir
) > 0) {
1077 strncpy(longname
, cur_dir
, namesize
);
1078 offset
= strlen(cur_dir
);
1081 /* Loop through the blocks picking up the name */
1084 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1085 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1089 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1090 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1099 static void do_tarput(void)
1102 struct timeval tp_start
;
1103 char *longfilename
= NULL
, linkflag
;
1106 GetTimeOfDay(&tp_start
);
1107 DEBUG(5, ("RJS do_tarput called ...\n"));
1109 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1111 /* Now read through those files ... */
1113 /* Get us to the next block, or the first block first time around */
1114 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1115 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1119 DEBUG(5, ("Reading the next header ...\n"));
1121 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
)) {
1122 case -2: /* Hmm, not good, but not fatal */
1123 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1124 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) && !skip_file(finfo
.size
)) {
1125 DEBUG(0, ("Short file, bailing out...\n"));
1131 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1134 case 0: /* chksum is zero - looks like an EOF */
1135 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1136 return; /* Hmmm, bad here ... */
1143 /* Now, do we have a long file name? */
1144 if (longfilename
!= NULL
) {
1145 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1146 finfo
.name
= longfilename
;
1147 longfilename
= NULL
;
1150 /* Well, now we have a header, process the file ... */
1151 /* Should we skip the file? We have the long name as well here */
1152 skip
= clipn
&& ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
) ||
1154 (tar_re_search
&& !regexec(preg
, finfo
.name
, 0, NULL
, 0)));
1156 (tar_re_search
&& mask_match_list(finfo
.name
, cliplist
, clipn
, True
)));
1159 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1161 skip_file(finfo
.size
);
1165 /* We only get this far if we should process the file */
1166 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1168 case '0': /* Should use symbolic names--FIXME */
1170 * Skip to the next block first, so we can get the file, FIXME, should
1171 * be in get_file ...
1172 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1173 * Fixes bug where file size in tarfile is zero.
1175 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1176 DEBUG(0, ("Short file, bailing out...\n"));
1179 if (!get_file(finfo
)) {
1180 DEBUG(0, ("Abandoning restore\n"));
1185 if (!get_dir(finfo
)) {
1186 DEBUG(0, ("Abandoning restore \n"));
1191 longfilename
= get_longfilename(finfo
);
1192 if (!longfilename
) {
1193 DEBUG(0, ("abandoning restore\n"));
1196 DEBUG(5, ("Long file name: %s\n", longfilename
));
1200 skip_file(finfo
.size
); /* Don't handle these yet */
1207 * samba interactive commands
1210 /****************************************************************************
1212 ***************************************************************************/
1219 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1220 DEBUG(0, ("blocksize <n>\n"));
1225 if (block
< 0 || block
> 65535) {
1226 DEBUG(0, ("blocksize out of range"));
1231 DEBUG(2,("blocksize is now %d\n", blocksize
));
1236 /****************************************************************************
1237 command to set incremental / reset mode
1238 ***************************************************************************/
1240 int cmd_tarmode(void)
1244 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1245 if (strequal(buf
, "full"))
1247 else if (strequal(buf
, "inc"))
1249 else if (strequal(buf
, "reset"))
1251 else if (strequal(buf
, "noreset"))
1253 else if (strequal(buf
, "system"))
1255 else if (strequal(buf
, "nosystem"))
1257 else if (strequal(buf
, "hidden"))
1259 else if (strequal(buf
, "nohidden"))
1261 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1263 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1266 DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1269 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1270 tar_inc
? "incremental" : "full",
1271 tar_system
? "system" : "nosystem",
1272 tar_hidden
? "hidden" : "nohidden",
1273 tar_reset
? "reset" : "noreset",
1274 tar_noisy
? "verbose" : "quiet"));
1278 /****************************************************************************
1279 Feeble attrib command
1280 ***************************************************************************/
1282 int cmd_setmode(void)
1290 attra
[0] = attra
[1] = 0;
1292 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1293 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1297 pstrcpy(fname
, cur_dir
);
1298 pstrcat(fname
, buf
);
1300 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1312 attra
[direct
]|=aRONLY
;
1315 attra
[direct
]|=aHIDDEN
;
1318 attra
[direct
]|=aSYSTEM
;
1321 attra
[direct
]|=aARCH
;
1324 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1330 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0) {
1331 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1335 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1336 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1337 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1341 /****************************************************************************
1342 Principal command for creating / extracting
1343 ***************************************************************************/
1351 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1352 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1356 argl
=toktocliplist(&argcl
, NULL
);
1357 if (!tar_parseargs(argcl
, argl
, buf
, 0))
1361 return process_tar();
1364 /****************************************************************************
1365 Command line (option) version
1366 ***************************************************************************/
1368 int process_tar(void)
1385 if (clipn
&& tar_excl
) {
1389 for (i
=0; i
<clipn
; i
++) {
1390 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1392 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1393 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1396 if (strrchr_m(cliplist
[i
], '\\')) {
1399 pstrcpy(saved_dir
, cur_dir
);
1401 if (*cliplist
[i
]=='\\') {
1402 pstrcpy(tarmac
, cliplist
[i
]);
1404 pstrcpy(tarmac
, cur_dir
);
1405 pstrcat(tarmac
, cliplist
[i
]);
1407 pstrcpy(cur_dir
, tarmac
);
1408 *(strrchr_m(cur_dir
, '\\')+1)='\0';
1410 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1411 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1412 pstrcpy(cur_dir
,saved_dir
);
1414 pstrcpy(tarmac
, cur_dir
);
1415 pstrcat(tarmac
, cliplist
[i
]);
1416 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1417 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1422 pstrcpy(mask
,cur_dir
);
1423 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1424 pstrcat(mask
,"\\*");
1425 do_list(mask
,attribute
,do_tar
,False
, True
);
1429 dotareof(tarhandle
);
1433 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1434 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1438 if (must_free_cliplist
) {
1440 for (i
= 0; i
< clipn
; ++i
) {
1441 SAFE_FREE(cliplist
[i
]);
1443 SAFE_FREE(cliplist
);
1446 must_free_cliplist
= False
;
1451 /****************************************************************************
1452 Find a token (filename) in a clip list
1453 ***************************************************************************/
1455 static int clipfind(char **aret
, int ret
, char *tok
)
1460 /* ignore leading slashes or dots in token */
1461 while(strchr_m("/\\.", *tok
))
1467 /* ignore leading slashes or dots in list */
1468 while(strchr_m("/\\.", *pkey
))
1471 if (!strslashcmp(pkey
, tok
))
1477 /****************************************************************************
1478 Read list of files to include from the file and initialize cliplist
1480 ***************************************************************************/
1482 static int read_inclusion_file(char *filename
)
1484 XFILE
*inclusion
= NULL
;
1485 char buf
[PATH_MAX
+ 1];
1486 char *inclusion_buffer
= NULL
;
1487 int inclusion_buffer_size
= 0;
1488 int inclusion_buffer_sofar
= 0;
1495 buf
[PATH_MAX
] = '\0'; /* guarantee null-termination */
1496 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1497 /* XXX It would be better to include a reason for failure, but without
1498 * autoconf, it's hard to use strerror, sys_errlist, etc.
1500 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1504 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1505 if (inclusion_buffer
== NULL
) {
1506 inclusion_buffer_size
= 1024;
1507 if ((inclusion_buffer
= malloc(inclusion_buffer_size
)) == NULL
) {
1508 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1514 if (buf
[strlen(buf
)-1] == '\n') {
1515 buf
[strlen(buf
)-1] = '\0';
1518 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1520 inclusion_buffer_size
*= 2;
1521 ib
= Realloc(inclusion_buffer
,inclusion_buffer_size
);
1523 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1524 inclusion_buffer_size
));
1528 inclusion_buffer
= ib
;
1532 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1533 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1536 x_fclose(inclusion
);
1539 /* Allocate an array of clipn + 1 char*'s for cliplist */
1540 cliplist
= malloc((clipn
+ 1) * sizeof(char *));
1541 if (cliplist
== NULL
) {
1542 DEBUG(0,("failure allocating memory for cliplist\n"));
1545 cliplist
[clipn
] = NULL
;
1546 p
= inclusion_buffer
;
1547 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1548 /* set current item to NULL so array will be null-terminated even if
1549 * malloc fails below. */
1551 if ((tmpstr
= (char *)malloc(strlen(p
)+1)) == NULL
) {
1552 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1555 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1556 cliplist
[i
] = tmpstr
;
1557 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1558 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1564 must_free_cliplist
= True
;
1568 SAFE_FREE(inclusion_buffer
);
1572 /* We know cliplist is always null-terminated */
1573 for (pp
= cliplist
; *pp
; ++pp
) {
1576 SAFE_FREE(cliplist
);
1578 must_free_cliplist
= False
;
1583 /* cliplist and its elements are freed at the end of process_tar. */
1587 /****************************************************************************
1588 Parse tar arguments. Sets tar_type, tar_excl, etc.
1589 ***************************************************************************/
1591 int tar_parseargs(int argc
, char *argv
[], const char *Optarg
, int Optind
)
1593 int newOptind
= Optind
;
1594 char tar_clipfl
='\0';
1596 /* Reset back to defaults - could be from interactive version
1597 * reset mode and archive mode left as they are though
1609 if (tar_type
=='c') {
1610 printf("Tar must be followed by only one of c or x.\n");
1616 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1617 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1629 DEBUG(0,("Option N must be followed by valid file name\n"));
1632 SMB_STRUCT_STAT stbuf
;
1633 extern time_t newer_than
;
1635 if (sys_stat(argv
[Optind
], &stbuf
) == 0) {
1636 newer_than
= stbuf
.st_mtime
;
1637 DEBUG(1,("Getting files newer than %s",
1638 asctime(LocalTime(&newer_than
))));
1642 DEBUG(0,("Error setting newer-than time\n"));
1655 DEBUG(0,("Only one of I,X,F must be specified\n"));
1662 DEBUG(0,("Only one of I,X,F must be specified\n"));
1669 DEBUG(0,("Only one of I,X,F must be specified\n"));
1675 DEBUG(0, ("tar_re_search set\n"));
1676 tar_re_search
= True
;
1679 if (tar_type
== 'c') {
1680 DEBUG(0, ("dry_run set\n"));
1683 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1688 DEBUG(0,("Unknown tar option\n"));
1694 printf("Option T must be followed by one of c or x.\n");
1698 /* tar_excl is true if cliplist lists files to be included.
1699 * Both 'I' and 'F' mean include. */
1700 tar_excl
=tar_clipfl
!='X';
1702 if (tar_clipfl
=='F') {
1703 if (argc
-Optind
-1 != 1) {
1704 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1709 if (! read_inclusion_file(argv
[Optind
])) {
1712 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1717 cliplist
=argv
+Optind
+1;
1718 clipn
=argc
-Optind
-1;
1721 if ((tmplist
=malloc(clipn
*sizeof(char *))) == NULL
) {
1722 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn
));
1726 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1728 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1730 if ((tmpstr
= (char *)malloc(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1731 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount
));
1735 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1736 tmplist
[clipcount
] = tmpstr
;
1737 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1739 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1743 must_free_cliplist
= True
;
1748 if (Optind
+1<argc
&& tar_re_search
) { /* Doing regular expression seaches */
1752 if ((preg
= (regex_t
*)malloc(65536)) == NULL
) {
1754 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
1758 if (errcode
= regcomp(preg
, argv
[Optind
+ 1], REG_EXTENDED
)) {
1762 errlen
= regerror(errcode
, preg
, errstr
, sizeof(errstr
) - 1);
1763 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv
[Optind
+ 1], errstr
));
1768 clipn
=argc
-Optind
-1;
1769 cliplist
=argv
+Optind
+1;
1773 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1774 /* Sets tar handle to either 0 or 1, as appropriate */
1775 tarhandle
=(tar_type
=='c');
1777 * Make sure that dbf points to stderr if we are using stdout for
1780 if (tarhandle
== 1) {
1783 if (!argv
[Optind
]) {
1784 DEBUG(0,("Must specify tar filename\n"));
1787 if (!strcmp(argv
[Optind
], "-")) {
1792 if (tar_type
=='c' && (dry_run
|| strcmp(argv
[Optind
], "/dev/null")==0)) {
1794 DEBUG(0,("Output is /dev/null, assuming dry_run\n"));
1798 } else if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1799 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0)) {
1800 DEBUG(0,("Error opening local file %s - %s\n", argv
[Optind
], strerror(errno
)));