2 Unix SMB/Netbios implementation.
5 Copyright (C) Ricky Poulten 1995-1998
6 Copyright (C) Richard Sharpe 1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* The following changes developed by Richard Sharpe for Canon Information
23 Systems Research Australia (CISRA)
25 1. Restore can now restore files with long file names
26 2. Save now saves directory information so that we can restore
27 directory creation times
28 3. tar now accepts both UNIX path names and DOS path names. I prefer
29 those lovely /'s to those UGLY \'s :-)
30 4. the files to exclude can be specified as a regular expression by adding
31 an r flag to the other tar flags. Eg:
33 -TcrX file.tar "*.(obj|exe)"
35 will skip all .obj and .exe files
42 static int clipfind(char **aret
, int ret
, char *tok
);
44 typedef struct file_info_struct file_info2
;
46 struct file_info_struct
52 /* These times are normally kept in GMT */
56 char *name
; /* This is dynamically allocate */
58 file_info2
*next
, *prev
; /* Used in the stack ... */
69 stack dir_stack
= {NULL
, 0}; /* Want an empty stack */
71 #define SEPARATORS " \t\n\r"
72 extern int DEBUGLEVEL
;
73 extern struct cli_state
*cli
;
76 /* These defines are for the do_setrattr routine, to indicate
77 * setting and reseting of file attributes in the function call */
81 static uint16 attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
83 #ifndef CLIENT_TIMEOUT
84 #define CLIENT_TIMEOUT (30*1000)
87 static char *tarbuf
, *buffer_p
;
88 static int tp
, ntarf
, tbufsiz
;
90 /* Incremental mode */
92 /* Reset archive bit */
94 /* Include / exclude mode (true=include, false=exclude) */
96 /* use regular expressions for search on file names */
97 BOOL tar_re_search
=False
;
101 /* Do not dump anything, just calculate sizes */
103 /* Dump files with System attribute */
104 BOOL tar_system
=True
;
105 /* Dump files with Hidden attribute */
106 BOOL tar_hidden
=True
;
107 /* Be noisy - make a catalogue */
109 BOOL tar_real_noisy
=False
; /* Don't want to be really noisy by default */
112 static char **cliplist
=NULL
;
114 static BOOL must_free_cliplist
= False
;
116 extern file_info def_finfo
;
117 extern BOOL lowercase
;
119 extern BOOL readbraw_supported
;
121 extern pstring cur_dir
;
122 extern int get_total_time_ms
;
123 extern int get_total_size
;
129 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
130 char *amode
, unsigned char ftype
);
131 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
);
132 static void do_tar(file_info
*finfo
);
133 static void oct_it(long value
, int ndgs
, char *p
);
134 static void fixtarname(char *tptr
, char *fp
, int l
);
135 static int dotarbuf(int f
, char *b
, int n
);
136 static void dozerobuf(int f
, int n
);
137 static void dotareof(int f
);
138 static void initarbuf(void);
140 /* restore functions */
141 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
);
142 static long unoct(char *p
, int ndgs
);
143 static void do_tarput(void);
144 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
);
147 * tar specific utitlities
150 /*******************************************************************
151 Create a string of size size+1 (for the null)
152 *******************************************************************/
153 static char *string_create_s(int size
)
157 tmp
= (char *)malloc(size
+1);
161 DEBUG(0, ("Out of memory in string_create_s\n"));
169 /****************************************************************************
170 Write a tar header to buffer
171 ****************************************************************************/
172 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
173 char *amode
, unsigned char ftype
)
179 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype
, size
, aname
));
181 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
184 if (l
>= NAMSIZ
- 1) {
185 /* write a GNU tar style long header */
187 b
= (char *)malloc(l
+TBLOCK
+100);
189 DEBUG(0,("out of memory\n"));
192 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
193 memset(b
, 0, l
+TBLOCK
+100);
194 fixtarname(b
, aname
, l
);
196 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
197 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
201 /* use l + 1 to do the null too */
202 fixtarname(hb
.dbuf
.name
, aname
, (l
>= NAMSIZ
) ? NAMSIZ
: l
+ 1);
205 strlower(hb
.dbuf
.name
);
207 /* write out a "standard" tar format header */
209 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
210 safe_strcpy(hb
.dbuf
.mode
, amode
, strlen(amode
));
211 oct_it(0L, 8, hb
.dbuf
.uid
);
212 oct_it(0L, 8, hb
.dbuf
.gid
);
213 oct_it((long) size
, 13, hb
.dbuf
.size
);
214 oct_it((long) 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;) chk
+=(0xFF & *jp
++);
221 oct_it((long) chk
, 8, hb
.dbuf
.chksum
);
222 hb
.dbuf
.chksum
[6] = '\0';
224 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
227 /****************************************************************************
228 Read a tar header into a hblock structure, and validate
229 ***************************************************************************/
230 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
)
237 * read in a "standard" tar format header - we're not that interested
238 * in that many fields, though
241 /* check the checksum */
242 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
247 /* compensate for blanks in chksum header */
248 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
251 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
253 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
255 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
256 chk
, fchk
, hb
->dbuf
.chksum
));
260 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
261 dump_data(5, (char *)hb
- TBLOCK
, TBLOCK
*3);
265 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
267 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 */
290 DEBUG(0, ("this tar file appears to contain some kind 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) == '\\'))
302 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
303 * 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 ****************************************************************************/
321 static int dotarbuf(int f
, char *b
, int n
)
328 /* This routine and the next one should be the only ones that do write()s */
329 if (tp
+ n
>= tbufsiz
)
334 memcpy(tarbuf
+ tp
, b
, diff
);
335 fail
=fail
&& (1+write(f
, tarbuf
, tbufsiz
));
342 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 ****************************************************************************/
358 static void dozerobuf(int f
, int n
)
360 /* short routine just to write out n zeros to buffer -
361 * used to round files to nearest block
362 * and to do tar EOFs */
369 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
371 write(f
, tarbuf
, tbufsiz
);
372 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
376 memset(tarbuf
+tp
, 0, n
);
381 /****************************************************************************
383 ****************************************************************************/
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 ****************************************************************************/
397 static void dotareof(int f
)
399 SMB_STRUCT_STAT stbuf
;
400 /* Two zero blocks at end of file, write out full buffer */
405 (void) dozerobuf(f
, TBLOCK
);
406 (void) dozerobuf(f
, TBLOCK
);
408 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 */
416 if (tp
> 0) write(f
, tarbuf
, S_ISREG(stbuf
.st_mode
) ? tp
: tbufsiz
);
419 /****************************************************************************
420 (Un)mangle DOS pathname, make nonabsolute
421 ****************************************************************************/
422 static void fixtarname(char *tptr
, char *fp
, int l
)
424 /* add a '.' to start of file name, convert from ugly dos \'s in path
425 * to lovely unix /'s :-} */
428 safe_strcpy(tptr
, fp
, l
);
429 string_replace(tptr
, '\\', '/');
432 /****************************************************************************
433 Convert from decimal to octal string
434 ****************************************************************************/
435 static void oct_it (long value
, int ndgs
, char *p
)
437 /* Converts long to octal string, pads with leading zeros */
439 /* skip final null, but do final space */
443 /* Loop does at least one digit */
445 p
[--ndgs
] = '0' + (char) (value
& 7);
448 while (ndgs
> 0 && value
!= 0);
450 /* Do leading zeros */
455 /****************************************************************************
456 Convert from octal string to long
457 ***************************************************************************/
458 static long unoct(char *p
, int ndgs
)
461 /* Converts octal string to long, ignoring any non-digit */
465 if (isdigit((int)*p
))
466 value
= (value
<< 3) | (long) (*p
- '0');
474 /****************************************************************************
475 Compare two strings in a slash insensitive way, allowing s1 to match s2
476 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
477 a file in any subdirectory of s1, declare a match.
478 ***************************************************************************/
479 static int strslashcmp(char *s1
, char *s2
)
485 || tolower(*s1
) == tolower(*s2
)
486 || (*s1
== '\\' && *s2
=='/')
487 || (*s1
== '/' && *s2
=='\\'))) {
491 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
494 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\')) return 0;
496 /* ignore trailing slash on s1 */
497 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1)) return 0;
499 /* check for s1 is an "initial" string of s2 */
500 if (*s2
== '/' || *s2
== '\\') return 0;
506 /****************************************************************************
507 Ensure a remote path exists (make if necessary)
508 ***************************************************************************/
509 static BOOL
ensurepath(char *fname
)
511 /* *must* be called with buffer ready malloc'ed */
512 /* ensures path exists */
514 char *partpath
, *ffname
;
515 char *p
=fname
, *basehack
;
517 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
519 partpath
= string_create_s(strlen(fname
));
520 ffname
= string_create_s(strlen(fname
));
522 if ((partpath
== NULL
) || (ffname
== NULL
)){
524 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
, "\\");
545 safe_strcat(partpath
, p
, strlen(fname
) + 1);
547 if (!cli_chkpath(cli
, partpath
)) {
548 if (!cli_mkdir(cli
, partpath
))
550 DEBUG(0, ("Error mkdirhiering\n"));
554 DEBUG(3, ("mkdirhiering %s\n", partpath
));
558 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
559 p
= strtok(NULL
,"/\\");
565 static int padit(char *buf
, int bufsize
, int padsize
)
570 DEBUG(5, ("Padding with %d zeros\n", padsize
));
571 memset(buf
, 0, bufsize
);
572 while( !berr
&& padsize
> 0 ) {
573 bytestowrite
= MIN(bufsize
, padsize
);
574 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
575 padsize
-= bytestowrite
;
582 static void do_setrattr(char *name
, uint16 attr
, int set
)
586 if (!cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
)) return;
588 if (set
== ATTRSET
) {
591 attr
= oldattr
& ~attr
;
594 if (!cli_setatr(cli
, name
, attr
, 0)) {
595 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
600 /****************************************************************************
601 append one remote file to the tar file
602 ***************************************************************************/
603 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
609 BOOL close_done
= False
;
610 BOOL shallitime
=True
;
612 int read_size
= 65520;
615 struct timeval tp_start
;
616 GetTimeOfDay(&tp_start
);
618 ftype
= '0'; /* An ordinary file ... */
621 finfo
.size
= finfo1
-> size
;
622 finfo
.mode
= finfo1
-> mode
;
623 finfo
.uid
= finfo1
-> uid
;
624 finfo
.gid
= finfo1
-> gid
;
625 finfo
.mtime
= finfo1
-> mtime
;
626 finfo
.atime
= finfo1
-> atime
;
627 finfo
.ctime
= finfo1
-> ctime
;
630 finfo
.size
= def_finfo
.size
;
631 finfo
.mode
= def_finfo
.mode
;
632 finfo
.uid
= def_finfo
.uid
;
633 finfo
.gid
= def_finfo
.gid
;
634 finfo
.mtime
= def_finfo
.mtime
;
635 finfo
.atime
= def_finfo
.atime
;
636 finfo
.ctime
= def_finfo
.ctime
;
641 DEBUG(3,("skipping file %s of size %d bytes\n",
645 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
650 fnum
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
);
652 dos_clean_name(rname
);
655 DEBUG(0,("%s opening remote file %s (%s)\n",
656 cli_errstr(cli
),rname
, cur_dir
));
660 finfo
.name
= string_create_s(strlen(rname
));
661 if (finfo
.name
== NULL
) {
662 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
666 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
668 if (!cli_getattrE(cli
, fnum
, &finfo
.mode
, &finfo
.size
, NULL
, &finfo
.atime
, &finfo
.mtime
)) {
669 DEBUG(0, ("getattrE: %s\n", cli_errstr(cli
)));
672 finfo
.ctime
= finfo
.mtime
;
675 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
677 if (tar_inc
&& !(finfo
.mode
& aARCH
))
679 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
682 else if (!tar_system
&& (finfo
.mode
& aSYSTEM
))
684 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
687 else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
))
689 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
694 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
699 /* write a tar header, don't bother with mode - just set to 100644 */
700 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
702 while (nread
< finfo
.size
&& !close_done
) {
704 DEBUG(3,("nread=%d\n",nread
));
706 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
709 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
715 /* if file size has increased since we made file size query, truncate
716 read so tar header for this file will be correct.
719 if (nread
> finfo
.size
) {
720 datalen
-= nread
- finfo
.size
;
721 DEBUG(0,("File size change - truncating %s to %d bytes\n", finfo
.name
, (int)finfo
.size
));
724 /* add received bits of file to buffer - dotarbuf will
725 * write out in 512 byte intervals */
726 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
727 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
732 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
739 /* pad tar file with zero's if we couldn't get entire file */
740 if (nread
< finfo
.size
) {
741 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", (int)finfo
.size
, (int)nread
));
742 if (padit(data
, sizeof(data
), finfo
.size
- nread
))
743 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
746 /* round tar file to nearest block */
747 if (finfo
.size
% TBLOCK
)
748 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
750 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
754 cli_close(cli
, fnum
);
758 struct timeval tp_end
;
761 /* if shallitime is true then we didn't skip */
762 if (tar_reset
&& !dry_run
)
763 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
765 GetTimeOfDay(&tp_end
);
767 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
768 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
769 get_total_time_ms
+= this_time
;
770 get_total_size
+= finfo
.size
;
774 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
775 (int)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
779 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
780 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
781 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
782 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
786 /****************************************************************************
787 Append single file to tar file (or not)
788 ***************************************************************************/
789 static void do_tar(file_info
*finfo
)
793 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
796 /* Is it on the exclude list ? */
797 if (!tar_excl
&& clipn
) {
800 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir
)));
802 safe_strcpy(exclaim
, cur_dir
, sizeof(pstring
));
803 *(exclaim
+strlen(exclaim
)-1)='\0';
805 safe_strcat(exclaim
, "\\", sizeof(pstring
));
806 safe_strcat(exclaim
, finfo
->name
, sizeof(exclaim
));
808 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
810 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
812 (tar_re_search
&& !regexec(preg
, exclaim
, 0, NULL
, 0))) {
814 (tar_re_search
&& mask_match(exclaim
, cliplist
[0], True
))) {
816 DEBUG(3,("Skipping file %s\n", exclaim
));
821 if (finfo
->mode
& aDIR
)
823 pstring saved_curdir
;
826 safe_strcpy(saved_curdir
, cur_dir
, sizeof(saved_curdir
));
828 DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n", (int)sizeof(cur_dir
), (int)strlen(cur_dir
), (int)strlen(finfo
->name
), finfo
->name
, cur_dir
));
830 safe_strcat(cur_dir
,finfo
->name
, sizeof(cur_dir
));
831 safe_strcat(cur_dir
,"\\", sizeof(cur_dir
));
833 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
835 /* write a tar directory, don't bother with mode - just set it to
837 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
839 DEBUG(0,(" directory %s\n", cur_dir
));
841 ntarf
++; /* Make sure we have a file on there */
842 safe_strcpy(mtar_mask
,cur_dir
, sizeof(pstring
));
843 safe_strcat(mtar_mask
,"*", sizeof(pstring
));
844 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
845 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
846 safe_strcpy(cur_dir
,saved_curdir
, sizeof(pstring
));
850 safe_strcpy(rname
,cur_dir
, sizeof(pstring
));
851 safe_strcat(rname
,finfo
->name
, sizeof(pstring
));
852 do_atar(rname
,finfo
->name
,finfo
);
856 /****************************************************************************
857 Convert from UNIX to DOS file names
858 ***************************************************************************/
859 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
)
861 /* remove '.' from start of file name, convert from unix /'s to
862 * dos \'s in path. Kill any absolute path names. But only if first!
865 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
872 if (*fp
== '\\' || *fp
== '/') {
878 safe_strcpy(tptr
, fp
, l
);
879 string_replace(tptr
, '/', '\\');
883 /****************************************************************************
884 Move to the next block in the buffer, which may mean read in another set of
885 blocks. FIXME, we should allow more than one block to be skipped.
886 ****************************************************************************/
887 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
889 int bufread
, total
= 0;
891 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
895 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
897 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
900 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
901 * Fixes bug where read can return short if coming from
905 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
908 while (total
< bufsiz
) {
909 if (bufread
< 0) { /* An error, return false */
910 return (total
> 0 ? -2 : bufread
);
918 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
922 DEBUG(5, ("Total bytes read ... %i\n", total
));
932 /* Skip a file, even if it includes a long file name? */
933 static int skip_file(int skipsize
)
935 int dsize
= skipsize
;
937 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
939 /* FIXME, we should skip more than one block at a time */
943 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
945 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
957 /*************************************************************
958 Get a file from the tar file and store it.
959 When this is called, tarbuf already contains the first
960 file block. This is a bit broken & needs fixing.
961 **************************************************************/
963 static int get_file(file_info2 finfo
)
965 int fnum
= -1, pos
= 0, dsize
= 0, rsize
= 0, bpos
= 0;
967 DEBUG(5, ("get_file: file: %s, size %i\n", finfo
.name
, (int)finfo
.size
));
969 if (ensurepath(finfo
.name
) &&
970 (fnum
=cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
)) == -1) {
971 DEBUG(0, ("abandoning restore\n"));
975 /* read the blocks from the tar file and write to the remote file */
977 rsize
= finfo
.size
; /* This is how much to write */
981 /* We can only write up to the end of the buffer */
983 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
984 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
985 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
987 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
988 DEBUG(0, ("Error writing remote file\n"));
995 /* Now figure out how much to move in the buffer */
997 /* FIXME, we should skip more than one block at a time */
999 /* First, skip any initial part of the part written that is left over */
1000 /* from the end of the first TBLOCK */
1002 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1004 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1007 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1008 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1016 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1017 * If the file being extracted is an exact multiple of
1018 * TBLOCK bytes then we don't want to extract the next
1019 * block from the tarfile here, as it will be done in
1020 * the caller of get_file().
1023 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1024 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1026 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1027 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1038 /* Now close the file ... */
1040 if (!cli_close(cli
, fnum
)) {
1041 DEBUG(0, ("Error closing remote file\n"));
1045 /* Now we update the creation date ... */
1047 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1049 if (!cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime
)) {
1050 if (tar_real_noisy
) {
1051 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1052 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1058 DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo
.name
, (int)finfo
.size
));
1063 /* Create a directory. We just ensure that the path exists and return as there
1064 is no file associated with a directory
1066 static int get_dir(file_info2 finfo
)
1069 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1071 if (!ensurepath(finfo
.name
)) {
1073 DEBUG(0, ("Problems creating directory\n"));
1082 /* Get a file with a long file name ... first file has file name, next file
1083 has the data. We only want the long file name, as the loop in do_tarput
1084 will deal with the rest.
1086 static char * get_longfilename(file_info2 finfo
)
1088 int namesize
= finfo
.size
+ strlen(cur_dir
) + 2;
1089 char *longname
= malloc(namesize
);
1090 int offset
= 0, left
= finfo
.size
;
1093 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1094 DEBUG(5, ("Len = %d\n", (int)finfo
.size
));
1096 if (longname
== NULL
) {
1098 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1099 (int)(finfo
.size
+ strlen(cur_dir
) + 2)));
1103 /* First, add cur_dir to the long file name */
1105 if (strlen(cur_dir
) > 0) {
1106 strncpy(longname
, cur_dir
, namesize
);
1107 offset
= strlen(cur_dir
);
1110 /* Loop through the blocks picking up the name */
1114 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1116 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1121 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1122 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1133 static void do_tarput(void)
1136 struct timeval tp_start
;
1137 char *longfilename
= NULL
, linkflag
;
1140 GetTimeOfDay(&tp_start
);
1142 DEBUG(5, ("RJS do_tarput called ...\n"));
1144 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1146 /* Now read through those files ... */
1150 /* Get us to the next block, or the first block first time around */
1152 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1154 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1160 DEBUG(5, ("Reading the next header ...\n"));
1162 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
)) {
1164 case -2: /* Hmm, not good, but not fatal */
1165 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1166 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) &&
1167 !skip_file(finfo
.size
)) {
1169 DEBUG(0, ("Short file, bailing out...\n"));
1177 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1180 case 0: /* chksum is zero - looks like an EOF */
1181 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1182 return; /* Hmmm, bad here ... */
1191 /* Now, do we have a long file name? */
1193 if (longfilename
!= NULL
) {
1195 free(finfo
.name
); /* Free the space already allocated */
1196 finfo
.name
= longfilename
;
1197 longfilename
= NULL
;
1201 /* Well, now we have a header, process the file ... */
1203 /* Should we skip the file? We have the long name as well here */
1206 ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
)
1208 || (tar_re_search
&& !regexec(preg
, finfo
.name
, 0, NULL
, 0)));
1210 || (tar_re_search
&& mask_match(finfo
.name
, cliplist
[0], True
)));
1213 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1217 skip_file(finfo
.size
);
1222 /* We only get this far if we should process the file */
1223 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1227 case '0': /* Should use symbolic names--FIXME */
1230 * Skip to the next block first, so we can get the file, FIXME, should
1231 * be in get_file ...
1232 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1233 * Fixes bug where file size in tarfile is zero.
1236 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1237 DEBUG(0, ("Short file, bailing out...\n"));
1240 if (!get_file(finfo
)) {
1241 DEBUG(0, ("Abandoning restore\n"));
1248 if (!get_dir(finfo
)) {
1249 DEBUG(0, ("Abandoning restore \n"));
1255 longfilename
= get_longfilename(finfo
);
1256 if (!longfilename
) {
1257 DEBUG(0, ("abandoning restore\n"));
1261 DEBUG(5, ("Long file name: %s\n", longfilename
));
1265 skip_file(finfo
.size
); /* Don't handle these yet */
1277 * samba interactive commands
1280 /****************************************************************************
1282 ***************************************************************************/
1283 void cmd_block(void)
1288 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1290 DEBUG(0, ("blocksize <n>\n"));
1295 if (block
< 0 || block
> 65535)
1297 DEBUG(0, ("blocksize out of range"));
1302 DEBUG(2,("blocksize is now %d\n", blocksize
));
1305 /****************************************************************************
1306 command to set incremental / reset mode
1307 ***************************************************************************/
1308 void cmd_tarmode(void)
1312 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1313 if (strequal(buf
, "full"))
1315 else if (strequal(buf
, "inc"))
1317 else if (strequal(buf
, "reset"))
1319 else if (strequal(buf
, "noreset"))
1321 else if (strequal(buf
, "system"))
1323 else if (strequal(buf
, "nosystem"))
1325 else if (strequal(buf
, "hidden"))
1327 else if (strequal(buf
, "nohidden"))
1329 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1331 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1333 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1336 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1337 tar_inc
? "incremental" : "full",
1338 tar_system
? "system" : "nosystem",
1339 tar_hidden
? "hidden" : "nohidden",
1340 tar_reset
? "reset" : "noreset",
1341 tar_noisy
? "verbose" : "quiet"));
1345 /****************************************************************************
1346 Feeble attrib command
1347 ***************************************************************************/
1348 void cmd_setmode(void)
1356 attra
[0] = attra
[1] = 0;
1358 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1360 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1364 safe_strcpy(fname
, cur_dir
, sizeof(pstring
));
1365 safe_strcat(fname
, buf
, sizeof(pstring
));
1367 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1376 case 'r': attra
[direct
]|=aRONLY
;
1378 case 'h': attra
[direct
]|=aHIDDEN
;
1380 case 's': attra
[direct
]|=aSYSTEM
;
1382 case 'a': attra
[direct
]|=aARCH
;
1384 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1389 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0)
1391 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1395 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1396 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1397 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1400 /****************************************************************************
1401 Principal command for creating / extracting
1402 ***************************************************************************/
1409 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1411 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1415 argl
=toktocliplist(&argcl
, NULL
);
1416 if (!tar_parseargs(argcl
, argl
, buf
, 0))
1424 /****************************************************************************
1425 Command line (option) version
1426 ***************************************************************************/
1427 int process_tar(void)
1443 if (clipn
&& tar_excl
) {
1447 for (i
=0; i
<clipn
; i
++) {
1448 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1450 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1451 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1454 if (strrchr_m(cliplist
[i
], '\\')) {
1457 safe_strcpy(saved_dir
, cur_dir
, sizeof(pstring
));
1459 if (*cliplist
[i
]=='\\') {
1460 safe_strcpy(tarmac
, cliplist
[i
], sizeof(pstring
));
1462 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
1463 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
1465 safe_strcpy(cur_dir
, tarmac
, sizeof(pstring
));
1466 *(strrchr_m(cur_dir
, '\\')+1)='\0';
1468 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1469 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1470 safe_strcpy(cur_dir
,saved_dir
, sizeof(pstring
));
1472 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
1473 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
1474 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1475 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1480 safe_strcpy(mask
,cur_dir
, sizeof(pstring
));
1481 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1482 safe_strcat(mask
,"\\*", sizeof(pstring
));
1483 do_list(mask
,attribute
,do_tar
,False
, True
);
1486 if (ntarf
) dotareof(tarhandle
);
1490 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1491 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1495 if (must_free_cliplist
) {
1497 for (i
= 0; i
< clipn
; ++i
) {
1503 must_free_cliplist
= False
;
1509 /****************************************************************************
1510 Find a token (filename) in a clip list
1511 ***************************************************************************/
1512 static int clipfind(char **aret
, int ret
, char *tok
)
1514 if (aret
==NULL
) return 0;
1516 /* ignore leading slashes or dots in token */
1517 while(strchr_m("/\\.", *tok
)) tok
++;
1522 /* ignore leading slashes or dots in list */
1523 while(strchr_m("/\\.", *pkey
)) pkey
++;
1525 if (!strslashcmp(pkey
, tok
)) return 1;
1531 /****************************************************************************
1532 Read list of files to include from the file and initialize cliplist
1534 ***************************************************************************/
1535 static int read_inclusion_file(char *filename
)
1537 FILE *inclusion
= NULL
;
1538 char buf
[MAXPATHLEN
+ 1];
1539 char *inclusion_buffer
= NULL
;
1540 int inclusion_buffer_size
= 0;
1541 int inclusion_buffer_sofar
= 0;
1548 buf
[MAXPATHLEN
] = '\0'; /* guarantee null-termination */
1549 if ((inclusion
= sys_fopen(filename
, "r")) == NULL
) {
1550 /* XXX It would be better to include a reason for failure, but without
1551 * autoconf, it's hard to use strerror, sys_errlist, etc.
1553 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1557 while ((! error
) && (fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1558 if (inclusion_buffer
== NULL
) {
1559 inclusion_buffer_size
= 1024;
1560 if ((inclusion_buffer
= malloc(inclusion_buffer_size
)) == NULL
) {
1561 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1567 if (buf
[strlen(buf
)-1] == '\n') {
1568 buf
[strlen(buf
)-1] = '\0';
1571 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1572 inclusion_buffer_size
*= 2;
1573 inclusion_buffer
= Realloc(inclusion_buffer
,inclusion_buffer_size
);
1574 if (! inclusion_buffer
) {
1575 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1576 inclusion_buffer_size
));
1582 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1583 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1589 /* Allocate an array of clipn + 1 char*'s for cliplist */
1590 cliplist
= malloc((clipn
+ 1) * sizeof(char *));
1591 if (cliplist
== NULL
) {
1592 DEBUG(0,("failure allocating memory for cliplist\n"));
1595 cliplist
[clipn
] = NULL
;
1596 p
= inclusion_buffer
;
1597 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1598 /* set current item to NULL so array will be null-terminated even if
1599 * malloc fails below. */
1601 if ((tmpstr
= (char *)malloc(strlen(p
)+1)) == NULL
) {
1602 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1605 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1606 cliplist
[i
] = tmpstr
;
1607 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1608 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1614 must_free_cliplist
= True
;
1618 if (inclusion_buffer
) {
1619 free(inclusion_buffer
);
1624 /* We know cliplist is always null-terminated */
1625 for (pp
= cliplist
; *pp
; ++pp
) {
1630 must_free_cliplist
= False
;
1635 /* cliplist and its elements are freed at the end of process_tar. */
1639 /****************************************************************************
1640 Parse tar arguments. Sets tar_type, tar_excl, etc.
1641 ***************************************************************************/
1642 int tar_parseargs(int argc
, char *argv
[], char *Optarg
, int Optind
)
1644 char tar_clipfl
='\0';
1646 /* Reset back to defaults - could be from interactive version
1647 * reset mode and archive mode left as they are though
1659 if (tar_type
=='c') {
1660 printf("Tar must be followed by only one of c or x.\n");
1666 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1667 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1678 DEBUG(0,("Option N must be followed by valid file name\n"));
1681 SMB_STRUCT_STAT stbuf
;
1682 extern time_t newer_than
;
1684 if (sys_stat(argv
[Optind
], &stbuf
) == 0) {
1685 newer_than
= stbuf
.st_mtime
;
1686 DEBUG(1,("Getting files newer than %s",
1687 asctime(LocalTime(&newer_than
))));
1690 DEBUG(0,("Error setting newer-than time\n"));
1703 DEBUG(0,("Only one of I,X,F must be specified\n"));
1710 DEBUG(0,("Only one of I,X,F must be specified\n"));
1717 DEBUG(0,("Only one of I,X,F must be specified\n"));
1723 DEBUG(0, ("tar_re_search set\n"));
1724 tar_re_search
= True
;
1727 if (tar_type
== 'c') {
1728 DEBUG(0, ("dry_run set\n"));
1731 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1736 DEBUG(0,("Unknown tar option\n"));
1741 printf("Option T must be followed by one of c or x.\n");
1745 /* tar_excl is true if cliplist lists files to be included.
1746 * Both 'I' and 'F' mean include. */
1747 tar_excl
=tar_clipfl
!='X';
1749 if (tar_clipfl
=='F') {
1750 if (argc
-Optind
-1 != 1) {
1751 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1754 if (! read_inclusion_file(argv
[Optind
+1])) {
1757 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1762 cliplist
=argv
+Optind
+1;
1763 clipn
=argc
-Optind
-1;
1766 if ((tmplist
=malloc(clipn
*sizeof(char *))) == NULL
) {
1767 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
1773 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1775 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1777 if ((tmpstr
= (char *)malloc(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1778 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
1783 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1784 tmplist
[clipcount
] = tmpstr
;
1785 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1787 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1790 must_free_cliplist
= True
;
1793 if (Optind
+1<argc
&& tar_re_search
) { /* Doing regular expression seaches */
1797 if ((preg
= (regex_t
*)malloc(65536)) == NULL
) {
1799 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
1804 if (errcode
= regcomp(preg
, argv
[Optind
+ 1], REG_EXTENDED
)) {
1808 errlen
= regerror(errcode
, preg
, errstr
, sizeof(errstr
) - 1);
1810 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv
[Optind
+ 1], errstr
));
1816 clipn
=argc
-Optind
-1;
1817 cliplist
=argv
+Optind
+1;
1821 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1822 /* Sets tar handle to either 0 or 1, as appropriate */
1823 tarhandle
=(tar_type
=='c');
1825 * Make sure that dbf points to stderr if we are using stdout for
1831 if (tar_type
=='c' && (dry_run
|| strcmp(argv
[Optind
], "/dev/null")==0))
1834 DEBUG(0,("Output is /dev/null, assuming dry_run"));
1839 if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1840 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0))
1842 DEBUG(0,("Error opening local file %s - %s\n",
1843 argv
[Optind
], strerror(errno
)));