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 :-} */
430 int skip
= get_character_len(*fp
);
436 } else if (skip
== 1) {
440 } else if (*fp
== '\\') {
451 /****************************************************************************
452 Convert from decimal to octal string
453 ****************************************************************************/
454 static void oct_it (long value
, int ndgs
, char *p
)
456 /* Converts long to octal string, pads with leading zeros */
458 /* skip final null, but do final space */
462 /* Loop does at least one digit */
464 p
[--ndgs
] = '0' + (char) (value
& 7);
467 while (ndgs
> 0 && value
!= 0);
469 /* Do leading zeros */
474 /****************************************************************************
475 Convert from octal string to long
476 ***************************************************************************/
477 static long unoct(char *p
, int ndgs
)
480 /* Converts octal string to long, ignoring any non-digit */
484 if (isdigit((int)*p
))
485 value
= (value
<< 3) | (long) (*p
- '0');
493 /****************************************************************************
494 Compare two strings in a slash insensitive way, allowing s1 to match s2
495 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
496 a file in any subdirectory of s1, declare a match.
497 ***************************************************************************/
498 static int strslashcmp(char *s1
, char *s2
)
504 || tolower(*s1
) == tolower(*s2
)
505 || (*s1
== '\\' && *s2
=='/')
506 || (*s1
== '/' && *s2
=='\\'))) {
510 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
513 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\')) return 0;
515 /* ignore trailing slash on s1 */
516 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1)) return 0;
518 /* check for s1 is an "initial" string of s2 */
519 if (*s2
== '/' || *s2
== '\\') return 0;
525 /****************************************************************************
526 Ensure a remote path exists (make if necessary)
527 ***************************************************************************/
528 static BOOL
ensurepath(char *fname
)
530 /* *must* be called with buffer ready malloc'ed */
531 /* ensures path exists */
533 char *partpath
, *ffname
;
534 char *p
=fname
, *basehack
;
536 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
538 partpath
= string_create_s(strlen(fname
));
539 ffname
= string_create_s(strlen(fname
));
541 if ((partpath
== NULL
) || (ffname
== NULL
)){
543 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
550 /* fname copied to ffname so can strtok */
552 safe_strcpy(ffname
, fname
, strlen(fname
));
554 /* do a `basename' on ffname, so don't try and make file name directory */
555 if ((basehack
=strrchr(ffname
, '\\')) == NULL
)
560 p
=strtok(ffname
, "\\");
564 safe_strcat(partpath
, p
, strlen(fname
) + 1);
566 if (!cli_chkpath(cli
, partpath
)) {
567 if (!cli_mkdir(cli
, partpath
))
569 DEBUG(0, ("Error mkdirhiering\n"));
573 DEBUG(3, ("mkdirhiering %s\n", partpath
));
577 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
578 p
= strtok(NULL
,"/\\");
584 static int padit(char *buf
, int bufsize
, int padsize
)
589 DEBUG(5, ("Padding with %d zeros\n", padsize
));
590 memset(buf
, 0, bufsize
);
591 while( !berr
&& padsize
> 0 ) {
592 bytestowrite
= MIN(bufsize
, padsize
);
593 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
594 padsize
-= bytestowrite
;
601 static void do_setrattr(char *name
, uint16 attr
, int set
)
605 if (!cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
)) return;
607 if (set
== ATTRSET
) {
610 attr
= oldattr
& ~attr
;
613 if (!cli_setatr(cli
, name
, attr
, 0)) {
614 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
619 /****************************************************************************
620 append one remote file to the tar file
621 ***************************************************************************/
622 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
628 BOOL close_done
= False
;
629 BOOL shallitime
=True
;
631 int read_size
= 65520;
634 struct timeval tp_start
;
635 GetTimeOfDay(&tp_start
);
637 ftype
= '0'; /* An ordinary file ... */
640 finfo
.size
= finfo1
-> size
;
641 finfo
.mode
= finfo1
-> mode
;
642 finfo
.uid
= finfo1
-> uid
;
643 finfo
.gid
= finfo1
-> gid
;
644 finfo
.mtime
= finfo1
-> mtime
;
645 finfo
.atime
= finfo1
-> atime
;
646 finfo
.ctime
= finfo1
-> ctime
;
649 finfo
.size
= def_finfo
.size
;
650 finfo
.mode
= def_finfo
.mode
;
651 finfo
.uid
= def_finfo
.uid
;
652 finfo
.gid
= def_finfo
.gid
;
653 finfo
.mtime
= def_finfo
.mtime
;
654 finfo
.atime
= def_finfo
.atime
;
655 finfo
.ctime
= def_finfo
.ctime
;
660 DEBUG(3,("skipping file %s of size %d bytes\n",
664 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
669 fnum
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
);
671 dos_clean_name(rname
);
674 DEBUG(0,("%s opening remote file %s (%s)\n",
675 cli_errstr(cli
),rname
, cur_dir
));
679 finfo
.name
= string_create_s(strlen(rname
));
680 if (finfo
.name
== NULL
) {
681 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
685 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
687 if (!cli_getattrE(cli
, fnum
, &finfo
.mode
, &finfo
.size
, NULL
, &finfo
.atime
, &finfo
.mtime
)) {
688 DEBUG(0, ("getattrE: %s\n", cli_errstr(cli
)));
691 finfo
.ctime
= finfo
.mtime
;
694 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
696 if (tar_inc
&& !(finfo
.mode
& aARCH
))
698 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
701 else if (!tar_system
&& (finfo
.mode
& aSYSTEM
))
703 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
706 else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
))
708 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
713 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
718 /* write a tar header, don't bother with mode - just set to 100644 */
719 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
721 while (nread
< finfo
.size
&& !close_done
) {
723 DEBUG(3,("nread=%d\n",nread
));
725 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
728 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
734 /* if file size has increased since we made file size query, truncate
735 read so tar header for this file will be correct.
738 if (nread
> finfo
.size
) {
739 datalen
-= nread
- finfo
.size
;
740 DEBUG(0,("File size change - truncating %s to %d bytes\n", finfo
.name
, (int)finfo
.size
));
743 /* add received bits of file to buffer - dotarbuf will
744 * write out in 512 byte intervals */
745 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
746 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
751 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
758 /* pad tar file with zero's if we couldn't get entire file */
759 if (nread
< finfo
.size
) {
760 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", (int)finfo
.size
, (int)nread
));
761 if (padit(data
, sizeof(data
), finfo
.size
- nread
))
762 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
765 /* round tar file to nearest block */
766 if (finfo
.size
% TBLOCK
)
767 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
769 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
773 cli_close(cli
, fnum
);
777 struct timeval tp_end
;
780 /* if shallitime is true then we didn't skip */
781 if (tar_reset
&& !dry_run
)
782 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
784 GetTimeOfDay(&tp_end
);
786 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
787 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
788 get_total_time_ms
+= this_time
;
789 get_total_size
+= finfo
.size
;
793 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
794 (int)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
798 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
799 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
800 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
801 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
805 /****************************************************************************
806 Append single file to tar file (or not)
807 ***************************************************************************/
808 static void do_tar(file_info
*finfo
)
812 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
815 /* Is it on the exclude list ? */
816 if (!tar_excl
&& clipn
) {
819 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir
)));
821 safe_strcpy(exclaim
, cur_dir
, sizeof(pstring
));
822 *(exclaim
+strlen(exclaim
)-1)='\0';
824 safe_strcat(exclaim
, "\\", sizeof(pstring
));
825 safe_strcat(exclaim
, finfo
->name
, sizeof(exclaim
));
827 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
829 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
831 (tar_re_search
&& !regexec(preg
, exclaim
, 0, NULL
, 0))) {
833 (tar_re_search
&& mask_match(exclaim
, cliplist
[0], True
))) {
835 DEBUG(3,("Skipping file %s\n", exclaim
));
840 if (finfo
->mode
& aDIR
)
842 pstring saved_curdir
;
845 safe_strcpy(saved_curdir
, cur_dir
, sizeof(saved_curdir
));
847 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
));
849 safe_strcat(cur_dir
,finfo
->name
, sizeof(cur_dir
));
850 safe_strcat(cur_dir
,"\\", sizeof(cur_dir
));
852 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
854 /* write a tar directory, don't bother with mode - just set it to
856 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
858 DEBUG(0,(" directory %s\n", cur_dir
));
860 ntarf
++; /* Make sure we have a file on there */
861 safe_strcpy(mtar_mask
,cur_dir
, sizeof(pstring
));
862 safe_strcat(mtar_mask
,"*", sizeof(pstring
));
863 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
864 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
865 safe_strcpy(cur_dir
,saved_curdir
, sizeof(pstring
));
869 safe_strcpy(rname
,cur_dir
, sizeof(pstring
));
870 safe_strcat(rname
,finfo
->name
, sizeof(pstring
));
871 do_atar(rname
,finfo
->name
,finfo
);
875 /****************************************************************************
876 Convert from UNIX to DOS file names
877 ***************************************************************************/
878 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
)
880 /* remove '.' from start of file name, convert from unix /'s to
881 * dos \'s in path. Kill any absolute path names. But only if first!
884 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
891 if (*fp
== '\\' || *fp
== '/') {
898 int skip
= get_character_len(*fp
);
904 } else if (skip
== 1) {
908 } else if (*fp
== '/') {
920 /****************************************************************************
921 Move to the next block in the buffer, which may mean read in another set of
922 blocks. FIXME, we should allow more than one block to be skipped.
923 ****************************************************************************/
924 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
926 int bufread
, total
= 0;
928 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
932 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
934 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
937 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
938 * Fixes bug where read can return short if coming from
942 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
945 while (total
< bufsiz
) {
946 if (bufread
< 0) { /* An error, return false */
947 return (total
> 0 ? -2 : bufread
);
955 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
959 DEBUG(5, ("Total bytes read ... %i\n", total
));
969 /* Skip a file, even if it includes a long file name? */
970 static int skip_file(int skipsize
)
972 int dsize
= skipsize
;
974 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
976 /* FIXME, we should skip more than one block at a time */
980 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
982 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
994 /*************************************************************
995 Get a file from the tar file and store it.
996 When this is called, tarbuf already contains the first
997 file block. This is a bit broken & needs fixing.
998 **************************************************************/
1000 static int get_file(file_info2 finfo
)
1002 int fnum
= -1, pos
= 0, dsize
= 0, rsize
= 0, bpos
= 0;
1004 DEBUG(5, ("get_file: file: %s, size %i\n", finfo
.name
, (int)finfo
.size
));
1006 if (ensurepath(finfo
.name
) &&
1007 (fnum
=cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
)) == -1) {
1008 DEBUG(0, ("abandoning restore\n"));
1012 /* read the blocks from the tar file and write to the remote file */
1014 rsize
= finfo
.size
; /* This is how much to write */
1018 /* We can only write up to the end of the buffer */
1020 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
1021 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
1022 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
1024 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
1025 DEBUG(0, ("Error writing remote file\n"));
1032 /* Now figure out how much to move in the buffer */
1034 /* FIXME, we should skip more than one block at a time */
1036 /* First, skip any initial part of the part written that is left over */
1037 /* from the end of the first TBLOCK */
1039 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1041 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1044 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1045 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1053 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1054 * If the file being extracted is an exact multiple of
1055 * TBLOCK bytes then we don't want to extract the next
1056 * block from the tarfile here, as it will be done in
1057 * the caller of get_file().
1060 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1061 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1063 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1064 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1075 /* Now close the file ... */
1077 if (!cli_close(cli
, fnum
)) {
1078 DEBUG(0, ("Error closing remote file\n"));
1082 /* Now we update the creation date ... */
1084 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1086 if (!cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime
)) {
1087 if (tar_real_noisy
) {
1088 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1089 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1095 DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo
.name
, (int)finfo
.size
));
1100 /* Create a directory. We just ensure that the path exists and return as there
1101 is no file associated with a directory
1103 static int get_dir(file_info2 finfo
)
1106 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1108 if (!ensurepath(finfo
.name
)) {
1110 DEBUG(0, ("Problems creating directory\n"));
1119 /* Get a file with a long file name ... first file has file name, next file
1120 has the data. We only want the long file name, as the loop in do_tarput
1121 will deal with the rest.
1123 static char * get_longfilename(file_info2 finfo
)
1125 int namesize
= finfo
.size
+ strlen(cur_dir
) + 2;
1126 char *longname
= malloc(namesize
);
1127 int offset
= 0, left
= finfo
.size
;
1130 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1131 DEBUG(5, ("Len = %d\n", (int)finfo
.size
));
1133 if (longname
== NULL
) {
1135 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1136 (int)(finfo
.size
+ strlen(cur_dir
) + 2)));
1140 /* First, add cur_dir to the long file name */
1142 if (strlen(cur_dir
) > 0) {
1143 strncpy(longname
, cur_dir
, namesize
);
1144 offset
= strlen(cur_dir
);
1147 /* Loop through the blocks picking up the name */
1151 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1153 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1158 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1159 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1170 static void do_tarput(void)
1173 struct timeval tp_start
;
1174 char *longfilename
= NULL
, linkflag
;
1177 GetTimeOfDay(&tp_start
);
1179 DEBUG(5, ("RJS do_tarput called ...\n"));
1181 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1183 /* Now read through those files ... */
1187 /* Get us to the next block, or the first block first time around */
1189 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1191 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1197 DEBUG(5, ("Reading the next header ...\n"));
1199 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
)) {
1201 case -2: /* Hmm, not good, but not fatal */
1202 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1203 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) &&
1204 !skip_file(finfo
.size
)) {
1206 DEBUG(0, ("Short file, bailing out...\n"));
1214 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1217 case 0: /* chksum is zero - looks like an EOF */
1218 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1219 return; /* Hmmm, bad here ... */
1228 /* Now, do we have a long file name? */
1230 if (longfilename
!= NULL
) {
1232 free(finfo
.name
); /* Free the space already allocated */
1233 finfo
.name
= longfilename
;
1234 longfilename
= NULL
;
1238 /* Well, now we have a header, process the file ... */
1240 /* Should we skip the file? We have the long name as well here */
1243 ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
)
1245 || (tar_re_search
&& !regexec(preg
, finfo
.name
, 0, NULL
, 0)));
1247 || (tar_re_search
&& mask_match(finfo
.name
, cliplist
[0], True
)));
1250 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1254 skip_file(finfo
.size
);
1259 /* We only get this far if we should process the file */
1260 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1264 case '0': /* Should use symbolic names--FIXME */
1267 * Skip to the next block first, so we can get the file, FIXME, should
1268 * be in get_file ...
1269 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1270 * Fixes bug where file size in tarfile is zero.
1273 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1274 DEBUG(0, ("Short file, bailing out...\n"));
1277 if (!get_file(finfo
)) {
1278 DEBUG(0, ("Abandoning restore\n"));
1285 if (!get_dir(finfo
)) {
1286 DEBUG(0, ("Abandoning restore \n"));
1292 longfilename
= get_longfilename(finfo
);
1293 if (!longfilename
) {
1294 DEBUG(0, ("abandoning restore\n"));
1298 DEBUG(5, ("Long file name: %s\n", longfilename
));
1302 skip_file(finfo
.size
); /* Don't handle these yet */
1314 * samba interactive commands
1317 /****************************************************************************
1319 ***************************************************************************/
1320 void cmd_block(void)
1325 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1327 DEBUG(0, ("blocksize <n>\n"));
1332 if (block
< 0 || block
> 65535)
1334 DEBUG(0, ("blocksize out of range"));
1339 DEBUG(2,("blocksize is now %d\n", blocksize
));
1342 /****************************************************************************
1343 command to set incremental / reset mode
1344 ***************************************************************************/
1345 void cmd_tarmode(void)
1349 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1350 if (strequal(buf
, "full"))
1352 else if (strequal(buf
, "inc"))
1354 else if (strequal(buf
, "reset"))
1356 else if (strequal(buf
, "noreset"))
1358 else if (strequal(buf
, "system"))
1360 else if (strequal(buf
, "nosystem"))
1362 else if (strequal(buf
, "hidden"))
1364 else if (strequal(buf
, "nohidden"))
1366 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1368 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1370 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1373 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1374 tar_inc
? "incremental" : "full",
1375 tar_system
? "system" : "nosystem",
1376 tar_hidden
? "hidden" : "nohidden",
1377 tar_reset
? "reset" : "noreset",
1378 tar_noisy
? "verbose" : "quiet"));
1382 /****************************************************************************
1383 Feeble attrib command
1384 ***************************************************************************/
1385 void cmd_setmode(void)
1393 attra
[0] = attra
[1] = 0;
1395 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1397 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1401 safe_strcpy(fname
, cur_dir
, sizeof(pstring
));
1402 safe_strcat(fname
, buf
, sizeof(pstring
));
1404 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1413 case 'r': attra
[direct
]|=aRONLY
;
1415 case 'h': attra
[direct
]|=aHIDDEN
;
1417 case 's': attra
[direct
]|=aSYSTEM
;
1419 case 'a': attra
[direct
]|=aARCH
;
1421 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1426 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0)
1428 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1432 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1433 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1434 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1437 /****************************************************************************
1438 Principal command for creating / extracting
1439 ***************************************************************************/
1446 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1448 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1452 argl
=toktocliplist(&argcl
, NULL
);
1453 if (!tar_parseargs(argcl
, argl
, buf
, 0))
1461 /****************************************************************************
1462 Command line (option) version
1463 ***************************************************************************/
1464 int process_tar(void)
1480 if (clipn
&& tar_excl
) {
1484 for (i
=0; i
<clipn
; i
++) {
1485 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1487 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1488 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1491 if (strrchr(cliplist
[i
], '\\')) {
1494 safe_strcpy(saved_dir
, cur_dir
, sizeof(pstring
));
1496 if (*cliplist
[i
]=='\\') {
1497 safe_strcpy(tarmac
, cliplist
[i
], sizeof(pstring
));
1499 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
1500 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
1502 safe_strcpy(cur_dir
, tarmac
, sizeof(pstring
));
1503 *(strrchr(cur_dir
, '\\')+1)='\0';
1505 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1506 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1507 safe_strcpy(cur_dir
,saved_dir
, sizeof(pstring
));
1509 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
1510 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
1511 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1512 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1517 safe_strcpy(mask
,cur_dir
, sizeof(pstring
));
1518 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1519 safe_strcat(mask
,"\\*", sizeof(pstring
));
1520 do_list(mask
,attribute
,do_tar
,False
, True
);
1523 if (ntarf
) dotareof(tarhandle
);
1527 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1528 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1532 if (must_free_cliplist
) {
1534 for (i
= 0; i
< clipn
; ++i
) {
1540 must_free_cliplist
= False
;
1546 /****************************************************************************
1547 Find a token (filename) in a clip list
1548 ***************************************************************************/
1549 static int clipfind(char **aret
, int ret
, char *tok
)
1551 if (aret
==NULL
) return 0;
1553 /* ignore leading slashes or dots in token */
1554 while(strchr("/\\.", *tok
)) tok
++;
1559 /* ignore leading slashes or dots in list */
1560 while(strchr("/\\.", *pkey
)) pkey
++;
1562 if (!strslashcmp(pkey
, tok
)) return 1;
1568 /****************************************************************************
1569 Read list of files to include from the file and initialize cliplist
1571 ***************************************************************************/
1572 static int read_inclusion_file(char *filename
)
1574 FILE *inclusion
= NULL
;
1575 char buf
[MAXPATHLEN
+ 1];
1576 char *inclusion_buffer
= NULL
;
1577 int inclusion_buffer_size
= 0;
1578 int inclusion_buffer_sofar
= 0;
1585 buf
[MAXPATHLEN
] = '\0'; /* guarantee null-termination */
1586 if ((inclusion
= sys_fopen(filename
, "r")) == NULL
) {
1587 /* XXX It would be better to include a reason for failure, but without
1588 * autoconf, it's hard to use strerror, sys_errlist, etc.
1590 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1594 while ((! error
) && (fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1595 if (inclusion_buffer
== NULL
) {
1596 inclusion_buffer_size
= 1024;
1597 if ((inclusion_buffer
= malloc(inclusion_buffer_size
)) == NULL
) {
1598 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1604 if (buf
[strlen(buf
)-1] == '\n') {
1605 buf
[strlen(buf
)-1] = '\0';
1608 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1609 inclusion_buffer_size
*= 2;
1610 inclusion_buffer
= Realloc(inclusion_buffer
,inclusion_buffer_size
);
1611 if (! inclusion_buffer
) {
1612 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1613 inclusion_buffer_size
));
1619 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1620 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1626 /* Allocate an array of clipn + 1 char*'s for cliplist */
1627 cliplist
= malloc((clipn
+ 1) * sizeof(char *));
1628 if (cliplist
== NULL
) {
1629 DEBUG(0,("failure allocating memory for cliplist\n"));
1632 cliplist
[clipn
] = NULL
;
1633 p
= inclusion_buffer
;
1634 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1635 /* set current item to NULL so array will be null-terminated even if
1636 * malloc fails below. */
1638 if ((tmpstr
= (char *)malloc(strlen(p
)+1)) == NULL
) {
1639 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1642 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1643 cliplist
[i
] = tmpstr
;
1644 if ((p
= strchr(p
, '\000')) == NULL
) {
1645 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1651 must_free_cliplist
= True
;
1655 if (inclusion_buffer
) {
1656 free(inclusion_buffer
);
1661 /* We know cliplist is always null-terminated */
1662 for (pp
= cliplist
; *pp
; ++pp
) {
1667 must_free_cliplist
= False
;
1672 /* cliplist and its elements are freed at the end of process_tar. */
1676 /****************************************************************************
1677 Parse tar arguments. Sets tar_type, tar_excl, etc.
1678 ***************************************************************************/
1679 int tar_parseargs(int argc
, char *argv
[], char *Optarg
, int Optind
)
1681 char tar_clipfl
='\0';
1683 /* Reset back to defaults - could be from interactive version
1684 * reset mode and archive mode left as they are though
1696 if (tar_type
=='c') {
1697 printf("Tar must be followed by only one of c or x.\n");
1703 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1704 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1715 DEBUG(0,("Option N must be followed by valid file name\n"));
1718 SMB_STRUCT_STAT stbuf
;
1719 extern time_t newer_than
;
1721 if (dos_stat(argv
[Optind
], &stbuf
) == 0) {
1722 newer_than
= stbuf
.st_mtime
;
1723 DEBUG(1,("Getting files newer than %s",
1724 asctime(LocalTime(&newer_than
))));
1727 DEBUG(0,("Error setting newer-than time\n"));
1740 DEBUG(0,("Only one of I,X,F must be specified\n"));
1747 DEBUG(0,("Only one of I,X,F must be specified\n"));
1754 DEBUG(0,("Only one of I,X,F must be specified\n"));
1760 DEBUG(0, ("tar_re_search set\n"));
1761 tar_re_search
= True
;
1764 if (tar_type
== 'c') {
1765 DEBUG(0, ("dry_run set\n"));
1768 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1773 DEBUG(0,("Unknown tar option\n"));
1778 printf("Option T must be followed by one of c or x.\n");
1782 /* tar_excl is true if cliplist lists files to be included.
1783 * Both 'I' and 'F' mean include. */
1784 tar_excl
=tar_clipfl
!='X';
1786 if (tar_clipfl
=='F') {
1787 if (argc
-Optind
-1 != 1) {
1788 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1791 if (! read_inclusion_file(argv
[Optind
+1])) {
1794 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1799 cliplist
=argv
+Optind
+1;
1800 clipn
=argc
-Optind
-1;
1803 if ((tmplist
=malloc(clipn
*sizeof(char *))) == NULL
) {
1804 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
1810 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1812 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1814 if ((tmpstr
= (char *)malloc(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1815 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
1820 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1821 tmplist
[clipcount
] = tmpstr
;
1822 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1824 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1827 must_free_cliplist
= True
;
1830 if (Optind
+1<argc
&& tar_re_search
) { /* Doing regular expression seaches */
1834 if ((preg
= (regex_t
*)malloc(65536)) == NULL
) {
1836 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
1841 if (errcode
= regcomp(preg
, argv
[Optind
+ 1], REG_EXTENDED
)) {
1845 errlen
= regerror(errcode
, preg
, errstr
, sizeof(errstr
) - 1);
1847 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv
[Optind
+ 1], errstr
));
1853 clipn
=argc
-Optind
-1;
1854 cliplist
=argv
+Optind
+1;
1858 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1859 /* Sets tar handle to either 0 or 1, as appropriate */
1860 tarhandle
=(tar_type
=='c');
1862 * Make sure that dbf points to stderr if we are using stdout for
1868 if (tar_type
=='c' && (dry_run
|| strcmp(argv
[Optind
], "/dev/null")==0))
1871 DEBUG(0,("Output is /dev/null, assuming dry_run"));
1876 if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1877 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0))
1879 DEBUG(0,("Error opening local file %s - %s\n",
1880 argv
[Optind
], strerror(errno
)));