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 time_t newer_than
;
67 extern struct cli_state
*cli
;
69 /* These defines are for the do_setrattr routine, to indicate
70 * setting and reseting of file attributes in the function call */
74 static uint16 attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
76 #ifndef CLIENT_TIMEOUT
77 #define CLIENT_TIMEOUT (30*1000)
80 static char *tarbuf
, *buffer_p
;
81 static int tp
, ntarf
, tbufsiz
;
83 /* Incremental mode */
84 static BOOL tar_inc
=False
;
85 /* Reset archive bit */
86 static BOOL tar_reset
=False
;
87 /* Include / exclude mode (true=include, false=exclude) */
88 static BOOL tar_excl
=True
;
89 /* use regular expressions for search on file names */
90 static BOOL tar_re_search
=False
;
91 /* Do not dump anything, just calculate sizes */
92 static BOOL dry_run
=False
;
93 /* Dump files with System attribute */
94 static BOOL tar_system
=True
;
95 /* Dump files with Hidden attribute */
96 static BOOL tar_hidden
=True
;
97 /* Be noisy - make a catalogue */
98 static BOOL tar_noisy
=True
;
99 static BOOL tar_real_noisy
=False
; /* Don't want to be really noisy by default */
102 static char **cliplist
=NULL
;
104 static BOOL must_free_cliplist
= False
;
106 extern file_info def_finfo
;
107 extern BOOL lowercase
;
109 extern BOOL readbraw_supported
;
111 extern pstring cur_dir
;
112 extern int get_total_time_ms
;
113 extern int get_total_size
;
115 static int blocksize
=20;
116 static int tarhandle
;
118 static void writetarheader(int f
, const char *aname
, SMB_BIG_UINT size
, time_t mtime
,
119 const char *amode
, unsigned char ftype
);
120 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
);
121 static void do_tar(file_info
*finfo
);
122 static void oct_it(SMB_BIG_UINT value
, int ndgs
, char *p
);
123 static void fixtarname(char *tptr
, const char *fp
, size_t l
);
124 static int dotarbuf(int f
, char *b
, int n
);
125 static void dozerobuf(int f
, int n
);
126 static void dotareof(int f
);
127 static void initarbuf(void);
129 /* restore functions */
130 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
);
131 static long unoct(char *p
, int ndgs
);
132 static void do_tarput(void);
133 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
);
136 * tar specific utitlities
139 /*******************************************************************
140 Create a string of size size+1 (for the null)
141 *******************************************************************/
143 static char *string_create_s(int size
)
147 tmp
= (char *)SMB_MALLOC(size
+1);
150 DEBUG(0, ("Out of memory in string_create_s\n"));
156 /****************************************************************************
157 Write a tar header to buffer
158 ****************************************************************************/
160 static void writetarheader(int f
, const char *aname
, SMB_BIG_UINT size
, time_t mtime
,
161 const char *amode
, unsigned char ftype
)
167 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype
, (double)size
, aname
));
169 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
172 /* We will be prepending a '.' in fixtarheader so use +2 to
173 * take care of the . and terminating zero. JRA.
176 /* write a GNU tar style long header */
178 b
= (char *)SMB_MALLOC(l
+TBLOCK
+100);
180 DEBUG(0,("out of memory\n"));
183 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
184 memset(b
, 0, l
+TBLOCK
+100);
185 fixtarname(b
, aname
, l
+2);
187 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
188 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
192 fixtarname(hb
.dbuf
.name
, aname
, (l
+2 >= NAMSIZ
) ? NAMSIZ
: l
+ 2);
195 strlower_m(hb
.dbuf
.name
);
197 /* write out a "standard" tar format header */
199 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
200 safe_strcpy(hb
.dbuf
.mode
, amode
, sizeof(hb
.dbuf
.mode
)-1);
201 oct_it((SMB_BIG_UINT
)0, 8, hb
.dbuf
.uid
);
202 oct_it((SMB_BIG_UINT
)0, 8, hb
.dbuf
.gid
);
203 oct_it((SMB_BIG_UINT
) size
, 13, hb
.dbuf
.size
);
204 if (size
> (SMB_BIG_UINT
)077777777777LL) {
206 /* This is a non-POSIX compatible extention to store files
209 memset(hb
.dbuf
.size
, 0, 4);
211 for (i
= 8, jp
=(char*)&size
; i
; i
--)
212 hb
.dbuf
.size
[i
+3] = *(jp
++);
214 oct_it((SMB_BIG_UINT
) mtime
, 13, hb
.dbuf
.mtime
);
215 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
216 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
217 hb
.dbuf
.linkflag
=ftype
;
219 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;)
222 oct_it((SMB_BIG_UINT
) chk
, 8, hb
.dbuf
.chksum
);
223 hb
.dbuf
.chksum
[6] = '\0';
225 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
228 /****************************************************************************
229 Read a tar header into a hblock structure, and validate
230 ***************************************************************************/
232 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
)
239 * read in a "standard" tar format header - we're not that interested
240 * in that many fields, though
243 /* check the checksum */
244 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;)
250 /* compensate for blanks in chksum header */
251 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
254 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
256 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
258 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
259 chk
, fchk
, hb
->dbuf
.chksum
));
262 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
263 dump_data(5, (char *)hb
- TBLOCK
, TBLOCK
*3);
267 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
268 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
272 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
274 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
275 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
276 strlen(hb
->dbuf
.name
) + 1, True
);
278 /* can't handle some links at present */
279 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
280 if (hb
->dbuf
.linkflag
== 0) {
281 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
284 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
285 /* Do nothing here at the moment. do_tarput will handle this
286 as long as the longlink gets back to it, as it has to advance
287 the buffer pointer, etc */
289 DEBUG(0, ("this tar file appears to contain some kind \
290 of link other than a GNUtar Longlink - ignoring\n"));
296 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
) ||
297 (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\')) {
300 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
301 * just make it a regular file */
305 * Bug fix by richard@sj.co.uk
307 * REC: restore times correctly (as does tar)
308 * We only get the modification time of the file; set the creation time
309 * from the mod. time, and the access time to current time
311 finfo
->mtime
= finfo
->ctime
= strtol(hb
->dbuf
.mtime
, NULL
, 8);
312 finfo
->atime
= time(NULL
);
313 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
318 /****************************************************************************
319 Write out the tar buffer to tape or wherever
320 ****************************************************************************/
322 static int dotarbuf(int f
, char *b
, int n
)
329 /* This routine and the next one should be the only ones that do write()s */
330 if (tp
+ n
>= tbufsiz
) {
334 memcpy(tarbuf
+ tp
, b
, diff
);
335 fail
=fail
&& (1+write(f
, tarbuf
, tbufsiz
));
340 while (n
>= tbufsiz
) {
341 fail
=fail
&& (1 + write(f
, b
, tbufsiz
));
348 memcpy(tarbuf
+tp
, b
, n
);
352 return(fail
? writ
: 0);
355 /****************************************************************************
356 Write zeros to buffer / tape
357 ****************************************************************************/
359 static void dozerobuf(int f
, int n
)
361 /* short routine just to write out n zeros to buffer -
362 * used to round files to nearest block
363 * and to do tar EOFs */
368 if (n
+tp
>= tbufsiz
) {
369 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
370 write(f
, tarbuf
, tbufsiz
);
371 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
373 memset(tarbuf
+tp
, 0, n
);
378 /****************************************************************************
380 ****************************************************************************/
382 static void initarbuf(void)
384 /* initialize tar buffer */
385 tbufsiz
=blocksize
*TBLOCK
;
386 tarbuf
=SMB_MALLOC(tbufsiz
); /* FIXME: We might not get the buffer */
388 /* reset tar buffer pointer and tar file counter and total dumped */
389 tp
=0; ntarf
=0; ttarf
=0;
392 /****************************************************************************
393 Write two zero blocks at end of file
394 ****************************************************************************/
396 static void dotareof(int f
)
398 SMB_STRUCT_STAT stbuf
;
399 /* Two zero blocks at end of file, write out full buffer */
404 (void) dozerobuf(f
, TBLOCK
);
405 (void) dozerobuf(f
, TBLOCK
);
407 if (sys_fstat(f
, &stbuf
) == -1) {
408 DEBUG(0, ("Couldn't stat file handle\n"));
412 /* Could be a pipe, in which case S_ISREG should fail,
413 * and we should write out at full size */
415 write(f
, tarbuf
, S_ISREG(stbuf
.st_mode
) ? tp
: tbufsiz
);
418 /****************************************************************************
419 (Un)mangle DOS pathname, make nonabsolute
420 ****************************************************************************/
422 static void fixtarname(char *tptr
, const char *fp
, size_t l
)
424 /* add a '.' to start of file name, convert from ugly dos \'s in path
425 * to lovely unix /'s :-} */
429 StrnCpy(tptr
, fp
, l
-1);
430 string_replace(tptr
, '\\', '/');
433 /****************************************************************************
434 Convert from decimal to octal string
435 ****************************************************************************/
437 static void oct_it (SMB_BIG_UINT value
, int ndgs
, char *p
)
439 /* Converts long to octal string, pads with leading zeros */
441 /* skip final null, but do final space */
445 /* Loop does at least one digit */
447 p
[--ndgs
] = '0' + (char) (value
& 7);
449 } while (ndgs
> 0 && value
!= 0);
451 /* Do leading zeros */
456 /****************************************************************************
457 Convert from octal string to long
458 ***************************************************************************/
460 static long unoct(char *p
, int ndgs
)
463 /* Converts octal string to long, ignoring any non-digit */
466 if (isdigit((int)*p
))
467 value
= (value
<< 3) | (long) (*p
- '0');
475 /****************************************************************************
476 Compare two strings in a slash insensitive way, allowing s1 to match s2
477 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
478 a file in any subdirectory of s1, declare a match.
479 ***************************************************************************/
481 static int strslashcmp(char *s1
, char *s2
)
485 while(*s1
&& *s2
&& (*s1
== *s2
|| tolower(*s1
) == tolower(*s2
) ||
486 (*s1
== '\\' && *s2
=='/') || (*s1
== '/' && *s2
=='\\'))) {
490 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
493 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\'))
496 /* ignore trailing slash on s1 */
497 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1))
500 /* check for s1 is an "initial" string of s2 */
501 if ((*s2
== '/' || *s2
== '\\') && !*s1
)
507 /****************************************************************************
508 Ensure a remote path exists (make if necessary)
509 ***************************************************************************/
511 static BOOL
ensurepath(char *fname
)
513 /* *must* be called with buffer ready malloc'ed */
514 /* ensures path exists */
516 char *partpath
, *ffname
;
517 char *p
=fname
, *basehack
;
519 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
521 partpath
= string_create_s(strlen(fname
));
522 ffname
= string_create_s(strlen(fname
));
524 if ((partpath
== NULL
) || (ffname
== NULL
)){
525 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
531 /* fname copied to ffname so can strtok */
533 safe_strcpy(ffname
, fname
, strlen(fname
));
535 /* do a `basename' on ffname, so don't try and make file name directory */
536 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
)
541 p
=strtok(ffname
, "\\");
544 safe_strcat(partpath
, p
, strlen(fname
) + 1);
546 if (!cli_chkpath(cli
, partpath
)) {
547 if (!cli_mkdir(cli
, partpath
)) {
548 DEBUG(0, ("Error mkdirhiering\n"));
551 DEBUG(3, ("mkdirhiering %s\n", partpath
));
555 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
556 p
= strtok(NULL
,"/\\");
562 static int padit(char *buf
, int bufsize
, int padsize
)
567 DEBUG(5, ("Padding with %d zeros\n", padsize
));
568 memset(buf
, 0, bufsize
);
569 while( !berr
&& padsize
> 0 ) {
570 bytestowrite
= MIN(bufsize
, padsize
);
571 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
572 padsize
-= bytestowrite
;
578 static void do_setrattr(char *name
, uint16 attr
, int set
)
582 if (!cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
)) return;
584 if (set
== ATTRSET
) {
587 attr
= oldattr
& ~attr
;
590 if (!cli_setatr(cli
, name
, attr
, 0)) {
591 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
595 /****************************************************************************
596 append one remote file to the tar file
597 ***************************************************************************/
599 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
602 SMB_BIG_UINT nread
=0;
605 BOOL close_done
= False
;
606 BOOL shallitime
=True
;
608 int read_size
= 65520;
611 struct timeval tp_start
;
613 GetTimeOfDay(&tp_start
);
615 ftype
= '0'; /* An ordinary file ... */
618 finfo
.size
= finfo1
-> size
;
619 finfo
.mode
= finfo1
-> mode
;
620 finfo
.uid
= finfo1
-> uid
;
621 finfo
.gid
= finfo1
-> gid
;
622 finfo
.mtime
= finfo1
-> mtime
;
623 finfo
.atime
= finfo1
-> atime
;
624 finfo
.ctime
= finfo1
-> ctime
;
625 finfo
.name
= finfo1
-> name
;
627 finfo
.size
= def_finfo
.size
;
628 finfo
.mode
= def_finfo
.mode
;
629 finfo
.uid
= def_finfo
.uid
;
630 finfo
.gid
= def_finfo
.gid
;
631 finfo
.mtime
= def_finfo
.mtime
;
632 finfo
.atime
= def_finfo
.atime
;
633 finfo
.ctime
= def_finfo
.ctime
;
634 finfo
.name
= def_finfo
.name
;
638 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo
.name
,
639 (double)finfo
.size
));
641 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
646 fnum
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
);
648 dos_clean_name(rname
);
651 DEBUG(0,("%s opening remote file %s (%s)\n",
652 cli_errstr(cli
),rname
, cur_dir
));
656 finfo
.name
= string_create_s(strlen(rname
));
657 if (finfo
.name
== NULL
) {
658 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
662 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
664 if (!cli_getattrE(cli
, fnum
, &finfo
.mode
, &finfo
.size
, NULL
, &finfo
.atime
, &finfo
.mtime
)) {
665 DEBUG(0, ("getattrE: %s\n", cli_errstr(cli
)));
668 finfo
.ctime
= finfo
.mtime
;
671 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
673 if (tar_inc
&& !(finfo
.mode
& aARCH
)) {
674 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
676 } else if (!tar_system
&& (finfo
.mode
& aSYSTEM
)) {
677 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
679 } else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
)) {
680 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
683 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
684 finfo
.name
, (double)finfo
.size
, lname
));
686 /* write a tar header, don't bother with mode - just set to 100644 */
687 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
689 while (nread
< finfo
.size
&& !close_done
) {
691 DEBUG(3,("nread=%.0f\n",(double)nread
));
693 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
696 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
702 /* if file size has increased since we made file size query, truncate
703 read so tar header for this file will be correct.
706 if (nread
> finfo
.size
) {
707 datalen
-= nread
- finfo
.size
;
708 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
709 finfo
.name
, (double)finfo
.size
));
712 /* add received bits of file to buffer - dotarbuf will
713 * write out in 512 byte intervals */
715 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
716 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
721 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
728 /* pad tar file with zero's if we couldn't get entire file */
729 if (nread
< finfo
.size
) {
730 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
731 (double)finfo
.size
, (int)nread
));
732 if (padit(data
, sizeof(data
), finfo
.size
- nread
))
733 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
736 /* round tar file to nearest block */
737 if (finfo
.size
% TBLOCK
)
738 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
740 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
744 cli_close(cli
, fnum
);
747 struct timeval tp_end
;
750 /* if shallitime is true then we didn't skip */
751 if (tar_reset
&& !dry_run
)
752 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
754 GetTimeOfDay(&tp_end
);
755 this_time
= (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 + (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
756 get_total_time_ms
+= this_time
;
757 get_total_size
+= finfo
.size
;
760 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
761 (double)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
765 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
766 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
767 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
768 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
772 /****************************************************************************
773 Append single file to tar file (or not)
774 ***************************************************************************/
776 static void do_tar(file_info
*finfo
)
780 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
783 /* Is it on the exclude list ? */
784 if (!tar_excl
&& clipn
) {
787 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir
)));
789 pstrcpy(exclaim
, cur_dir
);
790 *(exclaim
+strlen(exclaim
)-1)='\0';
792 pstrcat(exclaim
, "\\");
793 pstrcat(exclaim
, finfo
->name
);
795 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
797 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
798 (tar_re_search
&& mask_match_list(exclaim
, cliplist
, clipn
, True
))) {
799 DEBUG(3,("Skipping file %s\n", exclaim
));
804 if (finfo
->mode
& aDIR
) {
805 pstring saved_curdir
;
808 pstrcpy(saved_curdir
, cur_dir
);
810 DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, \
811 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
812 (int)sizeof(cur_dir
), (int)strlen(cur_dir
),
813 (int)strlen(finfo
->name
), finfo
->name
, cur_dir
));
815 pstrcat(cur_dir
,finfo
->name
);
816 pstrcat(cur_dir
,"\\");
818 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
820 /* write a tar directory, don't bother with mode - just set it to
822 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
824 DEBUG(0,(" directory %s\n", cur_dir
));
826 ntarf
++; /* Make sure we have a file on there */
827 pstrcpy(mtar_mask
,cur_dir
);
828 pstrcat(mtar_mask
,"*");
829 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
830 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
831 pstrcpy(cur_dir
,saved_curdir
);
833 pstrcpy(rname
,cur_dir
);
834 pstrcat(rname
,finfo
->name
);
835 do_atar(rname
,finfo
->name
,finfo
);
839 /****************************************************************************
840 Convert from UNIX to DOS file names
841 ***************************************************************************/
843 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
)
845 /* remove '.' from start of file name, convert from unix /'s to
846 * dos \'s in path. Kill any absolute path names. But only if first!
849 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
856 if (*fp
== '\\' || *fp
== '/') {
862 safe_strcpy(tptr
, fp
, l
);
863 string_replace(tptr
, '/', '\\');
866 /****************************************************************************
867 Move to the next block in the buffer, which may mean read in another set of
868 blocks. FIXME, we should allow more than one block to be skipped.
869 ****************************************************************************/
871 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
873 int bufread
, total
= 0;
875 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
879 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
881 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
884 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
885 * Fixes bug where read can return short if coming from
889 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
892 while (total
< bufsiz
) {
893 if (bufread
< 0) { /* An error, return false */
894 return (total
> 0 ? -2 : bufread
);
902 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
906 DEBUG(5, ("Total bytes read ... %i\n", total
));
914 /* Skip a file, even if it includes a long file name? */
915 static int skip_file(int skipsize
)
917 int dsize
= skipsize
;
919 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
921 /* FIXME, we should skip more than one block at a time */
924 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
925 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
934 /*************************************************************
935 Get a file from the tar file and store it.
936 When this is called, tarbuf already contains the first
937 file block. This is a bit broken & needs fixing.
938 **************************************************************/
940 static int get_file(file_info2 finfo
)
942 int fnum
= -1, pos
= 0, dsize
= 0, bpos
= 0;
943 SMB_BIG_UINT rsize
= 0;
945 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo
.name
, (double)finfo
.size
));
947 if (ensurepath(finfo
.name
) &&
948 (fnum
=cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
)) == -1) {
949 DEBUG(0, ("abandoning restore\n"));
953 /* read the blocks from the tar file and write to the remote file */
955 rsize
= finfo
.size
; /* This is how much to write */
959 /* We can only write up to the end of the buffer */
960 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
961 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
962 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
964 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
965 DEBUG(0, ("Error writing remote file\n"));
972 /* Now figure out how much to move in the buffer */
974 /* FIXME, we should skip more than one block at a time */
976 /* First, skip any initial part of the part written that is left over */
977 /* from the end of the first TBLOCK */
979 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
980 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
983 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
984 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
990 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
991 * If the file being extracted is an exact multiple of
992 * TBLOCK bytes then we don't want to extract the next
993 * block from the tarfile here, as it will be done in
994 * the caller of get_file().
997 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
998 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1000 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1001 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1010 /* Now close the file ... */
1012 if (!cli_close(cli
, fnum
)) {
1013 DEBUG(0, ("Error closing remote file\n"));
1017 /* Now we update the creation date ... */
1018 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1020 if (!cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime
)) {
1021 if (tar_real_noisy
) {
1022 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1023 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1028 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo
.name
, (double)finfo
.size
));
1032 /* Create a directory. We just ensure that the path exists and return as there
1033 is no file associated with a directory
1035 static int get_dir(file_info2 finfo
)
1037 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1039 if (!ensurepath(finfo
.name
)) {
1040 DEBUG(0, ("Problems creating directory\n"));
1047 /* Get a file with a long file name ... first file has file name, next file
1048 has the data. We only want the long file name, as the loop in do_tarput
1049 will deal with the rest.
1051 static char *get_longfilename(file_info2 finfo
)
1053 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1055 int namesize
= finfo
.size
+ strlen(cur_dir
) + 2;
1056 char *longname
= SMB_MALLOC(namesize
);
1057 int offset
= 0, left
= finfo
.size
;
1060 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1061 DEBUG(5, ("Len = %.0f\n", (double)finfo
.size
));
1063 if (longname
== NULL
) {
1064 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize
));
1068 /* First, add cur_dir to the long file name */
1070 if (strlen(cur_dir
) > 0) {
1071 strncpy(longname
, cur_dir
, namesize
);
1072 offset
= strlen(cur_dir
);
1075 /* Loop through the blocks picking up the name */
1078 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1079 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1083 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1084 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1093 static void do_tarput(void)
1096 struct timeval tp_start
;
1097 char *longfilename
= NULL
, linkflag
;
1100 GetTimeOfDay(&tp_start
);
1101 DEBUG(5, ("RJS do_tarput called ...\n"));
1103 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1105 /* Now read through those files ... */
1107 /* Get us to the next block, or the first block first time around */
1108 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1109 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1113 DEBUG(5, ("Reading the next header ...\n"));
1115 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
)) {
1116 case -2: /* Hmm, not good, but not fatal */
1117 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1118 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) && !skip_file(finfo
.size
)) {
1119 DEBUG(0, ("Short file, bailing out...\n"));
1125 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1128 case 0: /* chksum is zero - looks like an EOF */
1129 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1130 return; /* Hmmm, bad here ... */
1137 /* Now, do we have a long file name? */
1138 if (longfilename
!= NULL
) {
1139 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1140 finfo
.name
= longfilename
;
1141 longfilename
= NULL
;
1144 /* Well, now we have a header, process the file ... */
1145 /* Should we skip the file? We have the long name as well here */
1146 skip
= clipn
&& ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
) ||
1147 (tar_re_search
&& mask_match_list(finfo
.name
, cliplist
, clipn
, True
)));
1149 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1151 skip_file(finfo
.size
);
1155 /* We only get this far if we should process the file */
1156 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1158 case '0': /* Should use symbolic names--FIXME */
1160 * Skip to the next block first, so we can get the file, FIXME, should
1161 * be in get_file ...
1162 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1163 * Fixes bug where file size in tarfile is zero.
1165 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1166 DEBUG(0, ("Short file, bailing out...\n"));
1169 if (!get_file(finfo
)) {
1170 DEBUG(0, ("Abandoning restore\n"));
1175 if (!get_dir(finfo
)) {
1176 DEBUG(0, ("Abandoning restore \n"));
1181 longfilename
= get_longfilename(finfo
);
1182 if (!longfilename
) {
1183 DEBUG(0, ("abandoning restore\n"));
1186 DEBUG(5, ("Long file name: %s\n", longfilename
));
1190 skip_file(finfo
.size
); /* Don't handle these yet */
1197 * samba interactive commands
1200 /****************************************************************************
1202 ***************************************************************************/
1209 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1210 DEBUG(0, ("blocksize <n>\n"));
1215 if (block
< 0 || block
> 65535) {
1216 DEBUG(0, ("blocksize out of range"));
1221 DEBUG(2,("blocksize is now %d\n", blocksize
));
1226 /****************************************************************************
1227 command to set incremental / reset mode
1228 ***************************************************************************/
1230 int cmd_tarmode(void)
1234 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1235 if (strequal(buf
, "full"))
1237 else if (strequal(buf
, "inc"))
1239 else if (strequal(buf
, "reset"))
1241 else if (strequal(buf
, "noreset"))
1243 else if (strequal(buf
, "system"))
1245 else if (strequal(buf
, "nosystem"))
1247 else if (strequal(buf
, "hidden"))
1249 else if (strequal(buf
, "nohidden"))
1251 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1253 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1256 DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1259 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1260 tar_inc
? "incremental" : "full",
1261 tar_system
? "system" : "nosystem",
1262 tar_hidden
? "hidden" : "nohidden",
1263 tar_reset
? "reset" : "noreset",
1264 tar_noisy
? "verbose" : "quiet"));
1268 /****************************************************************************
1269 Feeble attrib command
1270 ***************************************************************************/
1272 int cmd_setmode(void)
1280 attra
[0] = attra
[1] = 0;
1282 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1283 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1287 pstrcpy(fname
, cur_dir
);
1288 pstrcat(fname
, buf
);
1290 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1302 attra
[direct
]|=aRONLY
;
1305 attra
[direct
]|=aHIDDEN
;
1308 attra
[direct
]|=aSYSTEM
;
1311 attra
[direct
]|=aARCH
;
1314 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1320 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0) {
1321 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1325 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1326 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1327 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1331 /****************************************************************************
1332 Principal command for creating / extracting
1333 ***************************************************************************/
1342 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1343 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1347 argl
=toktocliplist(&argcl
, NULL
);
1348 if (!tar_parseargs(argcl
, argl
, buf
, 0))
1351 ret
= process_tar();
1356 /****************************************************************************
1357 Command line (option) version
1358 ***************************************************************************/
1360 int process_tar(void)
1377 if (clipn
&& tar_excl
) {
1381 for (i
=0; i
<clipn
; i
++) {
1382 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1384 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1385 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1388 if (strrchr_m(cliplist
[i
], '\\')) {
1391 pstrcpy(saved_dir
, cur_dir
);
1393 if (*cliplist
[i
]=='\\') {
1394 pstrcpy(tarmac
, cliplist
[i
]);
1396 pstrcpy(tarmac
, cur_dir
);
1397 pstrcat(tarmac
, cliplist
[i
]);
1399 pstrcpy(cur_dir
, tarmac
);
1400 *(strrchr_m(cur_dir
, '\\')+1)='\0';
1402 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1403 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1404 pstrcpy(cur_dir
,saved_dir
);
1406 pstrcpy(tarmac
, cur_dir
);
1407 pstrcat(tarmac
, cliplist
[i
]);
1408 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1409 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1414 pstrcpy(mask
,cur_dir
);
1415 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1416 pstrcat(mask
,"\\*");
1417 do_list(mask
,attribute
,do_tar
,False
, True
);
1421 dotareof(tarhandle
);
1425 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1426 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1430 if (must_free_cliplist
) {
1432 for (i
= 0; i
< clipn
; ++i
) {
1433 SAFE_FREE(cliplist
[i
]);
1435 SAFE_FREE(cliplist
);
1438 must_free_cliplist
= False
;
1443 /****************************************************************************
1444 Find a token (filename) in a clip list
1445 ***************************************************************************/
1447 static int clipfind(char **aret
, int ret
, char *tok
)
1452 /* ignore leading slashes or dots in token */
1453 while(strchr_m("/\\.", *tok
))
1459 /* ignore leading slashes or dots in list */
1460 while(strchr_m("/\\.", *pkey
))
1463 if (!strslashcmp(pkey
, tok
))
1469 /****************************************************************************
1470 Read list of files to include from the file and initialize cliplist
1472 ***************************************************************************/
1474 static int read_inclusion_file(char *filename
)
1476 XFILE
*inclusion
= NULL
;
1477 char buf
[PATH_MAX
+ 1];
1478 char *inclusion_buffer
= NULL
;
1479 int inclusion_buffer_size
= 0;
1480 int inclusion_buffer_sofar
= 0;
1487 buf
[PATH_MAX
] = '\0'; /* guarantee null-termination */
1488 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1489 /* XXX It would be better to include a reason for failure, but without
1490 * autoconf, it's hard to use strerror, sys_errlist, etc.
1492 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1496 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1497 if (inclusion_buffer
== NULL
) {
1498 inclusion_buffer_size
= 1024;
1499 if ((inclusion_buffer
= SMB_MALLOC(inclusion_buffer_size
)) == NULL
) {
1500 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1506 if (buf
[strlen(buf
)-1] == '\n') {
1507 buf
[strlen(buf
)-1] = '\0';
1510 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1512 inclusion_buffer_size
*= 2;
1513 ib
= SMB_REALLOC(inclusion_buffer
,inclusion_buffer_size
);
1515 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1516 inclusion_buffer_size
));
1520 inclusion_buffer
= ib
;
1524 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1525 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1528 x_fclose(inclusion
);
1531 /* Allocate an array of clipn + 1 char*'s for cliplist */
1532 cliplist
= SMB_MALLOC_ARRAY(char *, clipn
+ 1);
1533 if (cliplist
== NULL
) {
1534 DEBUG(0,("failure allocating memory for cliplist\n"));
1537 cliplist
[clipn
] = NULL
;
1538 p
= inclusion_buffer
;
1539 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1540 /* set current item to NULL so array will be null-terminated even if
1541 * malloc fails below. */
1543 if ((tmpstr
= (char *)SMB_MALLOC(strlen(p
)+1)) == NULL
) {
1544 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1547 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1548 cliplist
[i
] = tmpstr
;
1549 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1550 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1556 must_free_cliplist
= True
;
1560 SAFE_FREE(inclusion_buffer
);
1564 /* We know cliplist is always null-terminated */
1565 for (pp
= cliplist
; *pp
; ++pp
) {
1568 SAFE_FREE(cliplist
);
1570 must_free_cliplist
= False
;
1575 /* cliplist and its elements are freed at the end of process_tar. */
1579 /****************************************************************************
1580 Parse tar arguments. Sets tar_type, tar_excl, etc.
1581 ***************************************************************************/
1583 int tar_parseargs(int argc
, char *argv
[], const char *Optarg
, int Optind
)
1585 int newOptind
= Optind
;
1586 char tar_clipfl
='\0';
1588 /* Reset back to defaults - could be from interactive version
1589 * reset mode and archive mode left as they are though
1601 if (tar_type
=='c') {
1602 printf("Tar must be followed by only one of c or x.\n");
1608 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1609 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1621 DEBUG(0,("Option N must be followed by valid file name\n"));
1624 SMB_STRUCT_STAT stbuf
;
1626 if (sys_stat(argv
[Optind
], &stbuf
) == 0) {
1627 newer_than
= stbuf
.st_mtime
;
1628 DEBUG(1,("Getting files newer than %s",
1629 asctime(LocalTime(&newer_than
))));
1633 DEBUG(0,("Error setting newer-than time\n"));
1646 DEBUG(0,("Only one of I,X,F must be specified\n"));
1653 DEBUG(0,("Only one of I,X,F must be specified\n"));
1660 DEBUG(0,("Only one of I,X,F must be specified\n"));
1666 DEBUG(0, ("tar_re_search set\n"));
1667 tar_re_search
= True
;
1670 if (tar_type
== 'c') {
1671 DEBUG(0, ("dry_run set\n"));
1674 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1679 DEBUG(0,("Unknown tar option\n"));
1685 printf("Option T must be followed by one of c or x.\n");
1689 /* tar_excl is true if cliplist lists files to be included.
1690 * Both 'I' and 'F' mean include. */
1691 tar_excl
=tar_clipfl
!='X';
1693 if (tar_clipfl
=='F') {
1694 if (argc
-Optind
-1 != 1) {
1695 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1700 if (! read_inclusion_file(argv
[Optind
])) {
1703 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1708 cliplist
=argv
+Optind
+1;
1709 clipn
=argc
-Optind
-1;
1712 if ((tmplist
=SMB_MALLOC_ARRAY(char *,clipn
)) == NULL
) {
1713 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn
));
1717 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1719 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1721 if ((tmpstr
= (char *)SMB_MALLOC(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1722 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount
));
1726 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1727 tmplist
[clipcount
] = tmpstr
;
1728 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1730 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1734 must_free_cliplist
= True
;
1739 if (Optind
+1<argc
&& tar_re_search
) { /* Doing regular expression seaches */
1740 clipn
=argc
-Optind
-1;
1741 cliplist
=argv
+Optind
+1;
1745 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1746 /* Sets tar handle to either 0 or 1, as appropriate */
1747 tarhandle
=(tar_type
=='c');
1749 * Make sure that dbf points to stderr if we are using stdout for
1752 if (tarhandle
== 1) {
1755 if (!argv
[Optind
]) {
1756 DEBUG(0,("Must specify tar filename\n"));
1759 if (!strcmp(argv
[Optind
], "-")) {
1764 if (tar_type
=='c' && dry_run
) {
1766 } else if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1767 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0)) {
1768 DEBUG(0,("Error opening local file %s - %s\n", argv
[Optind
], strerror(errno
)));