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
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 #define SEPARATORS " \t\n\r"
70 extern struct cli_state
*cli
;
72 /* These defines are for the do_setrattr routine, to indicate
73 * setting and reseting of file attributes in the function call */
77 static uint16 attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
79 #ifndef CLIENT_TIMEOUT
80 #define CLIENT_TIMEOUT (30*1000)
83 static char *tarbuf
, *buffer_p
;
84 static int tp
, ntarf
, tbufsiz
;
86 /* Incremental mode */
87 static BOOL tar_inc
=False
;
88 /* Reset archive bit */
89 static BOOL tar_reset
=False
;
90 /* Include / exclude mode (true=include, false=exclude) */
91 static BOOL tar_excl
=True
;
92 /* use regular expressions for search on file names */
93 static BOOL tar_re_search
=False
;
97 /* Do not dump anything, just calculate sizes */
98 static BOOL dry_run
=False
;
99 /* Dump files with System attribute */
100 static BOOL tar_system
=True
;
101 /* Dump files with Hidden attribute */
102 static BOOL tar_hidden
=True
;
103 /* Be noisy - make a catalogue */
104 static BOOL tar_noisy
=True
;
105 static BOOL tar_real_noisy
=False
; /* Don't want to be really noisy by default */
108 static char **cliplist
=NULL
;
110 static BOOL must_free_cliplist
= False
;
112 extern file_info def_finfo
;
113 extern BOOL lowercase
;
115 extern BOOL readbraw_supported
;
117 extern pstring cur_dir
;
118 extern int get_total_time_ms
;
119 extern int get_total_size
;
121 static int blocksize
=20;
122 static int tarhandle
;
124 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
125 char *amode
, unsigned char ftype
);
126 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
);
127 static void do_tar(file_info
*finfo
);
128 static void oct_it(long value
, int ndgs
, char *p
);
129 static void fixtarname(char *tptr
, char *fp
, int l
);
130 static int dotarbuf(int f
, char *b
, int n
);
131 static void dozerobuf(int f
, int n
);
132 static void dotareof(int f
);
133 static void initarbuf(void);
135 /* restore functions */
136 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
);
137 static long unoct(char *p
, int ndgs
);
138 static void do_tarput(void);
139 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
);
142 * tar specific utitlities
145 /*******************************************************************
146 Create a string of size size+1 (for the null)
147 *******************************************************************/
148 static char *string_create_s(int size
)
152 tmp
= (char *)malloc(size
+1);
156 DEBUG(0, ("Out of memory in string_create_s\n"));
164 /****************************************************************************
165 Write a tar header to buffer
166 ****************************************************************************/
167 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
168 char *amode
, unsigned char ftype
)
174 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype
, size
, aname
));
176 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
179 if (l
>= NAMSIZ
- 1) {
180 /* write a GNU tar style long header */
182 b
= (char *)malloc(l
+TBLOCK
+100);
184 DEBUG(0,("out of memory\n"));
187 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
188 memset(b
, 0, l
+TBLOCK
+100);
189 fixtarname(b
, aname
, l
);
191 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
192 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
196 /* use l + 1 to do the null too */
197 fixtarname(hb
.dbuf
.name
, aname
, (l
>= NAMSIZ
) ? NAMSIZ
: l
+ 1);
200 strlower(hb
.dbuf
.name
);
202 /* write out a "standard" tar format header */
204 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
205 safe_strcpy(hb
.dbuf
.mode
, amode
, strlen(amode
));
206 oct_it(0L, 8, hb
.dbuf
.uid
);
207 oct_it(0L, 8, hb
.dbuf
.gid
);
208 oct_it((long) size
, 13, hb
.dbuf
.size
);
209 oct_it((long) mtime
, 13, hb
.dbuf
.mtime
);
210 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
211 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
212 hb
.dbuf
.linkflag
=ftype
;
214 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
216 oct_it((long) chk
, 8, hb
.dbuf
.chksum
);
217 hb
.dbuf
.chksum
[6] = '\0';
219 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
222 /****************************************************************************
223 Read a tar header into a hblock structure, and validate
224 ***************************************************************************/
225 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
)
232 * read in a "standard" tar format header - we're not that interested
233 * in that many fields, though
236 /* check the checksum */
237 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
242 /* compensate for blanks in chksum header */
243 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
246 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
248 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
250 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
251 chk
, fchk
, hb
->dbuf
.chksum
));
255 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
256 dump_data(5, (char *)hb
- TBLOCK
, TBLOCK
*3);
260 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
262 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
267 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
269 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
270 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
271 strlen(hb
->dbuf
.name
) + 1, True
);
273 /* can't handle some links at present */
274 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
275 if (hb
->dbuf
.linkflag
== 0) {
276 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
279 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
280 /* Do nothing here at the moment. do_tarput will handle this
281 as long as the longlink gets back to it, as it has to advance
282 the buffer pointer, etc */
285 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
291 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
)
292 || (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\'))
297 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
298 * just make it a regular file */
300 * Bug fix by richard@sj.co.uk
302 * REC: restore times correctly (as does tar)
303 * We only get the modification time of the file; set the creation time
304 * from the mod. time, and the access time to current time
306 finfo
->mtime
= finfo
->ctime
= strtol(hb
->dbuf
.mtime
, NULL
, 8);
307 finfo
->atime
= time(NULL
);
308 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
313 /****************************************************************************
314 Write out the tar buffer to tape or wherever
315 ****************************************************************************/
316 static int dotarbuf(int f
, char *b
, int n
)
323 /* This routine and the next one should be the only ones that do write()s */
324 if (tp
+ n
>= tbufsiz
)
329 memcpy(tarbuf
+ tp
, b
, diff
);
330 fail
=fail
&& (1+write(f
, tarbuf
, tbufsiz
));
337 fail
=fail
&& (1 + write(f
, b
, tbufsiz
));
343 memcpy(tarbuf
+tp
, b
, n
);
347 return(fail
? writ
: 0);
350 /****************************************************************************
351 Write zeros to buffer / tape
352 ****************************************************************************/
353 static void dozerobuf(int f
, int n
)
355 /* short routine just to write out n zeros to buffer -
356 * used to round files to nearest block
357 * and to do tar EOFs */
364 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
366 write(f
, tarbuf
, tbufsiz
);
367 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
371 memset(tarbuf
+tp
, 0, n
);
376 /****************************************************************************
378 ****************************************************************************/
379 static void initarbuf(void)
381 /* initialize tar buffer */
382 tbufsiz
=blocksize
*TBLOCK
;
383 tarbuf
=malloc(tbufsiz
); /* FIXME: We might not get the buffer */
385 /* reset tar buffer pointer and tar file counter and total dumped */
386 tp
=0; ntarf
=0; ttarf
=0;
389 /****************************************************************************
390 Write two zero blocks at end of file
391 ****************************************************************************/
392 static void dotareof(int f
)
394 SMB_STRUCT_STAT stbuf
;
395 /* Two zero blocks at end of file, write out full buffer */
400 (void) dozerobuf(f
, TBLOCK
);
401 (void) dozerobuf(f
, TBLOCK
);
403 if (sys_fstat(f
, &stbuf
) == -1)
405 DEBUG(0, ("Couldn't stat file handle\n"));
409 /* Could be a pipe, in which case S_ISREG should fail,
410 * and we should write out at full size */
411 if (tp
> 0) write(f
, tarbuf
, S_ISREG(stbuf
.st_mode
) ? tp
: tbufsiz
);
414 /****************************************************************************
415 (Un)mangle DOS pathname, make nonabsolute
416 ****************************************************************************/
417 static void fixtarname(char *tptr
, char *fp
, int l
)
419 /* add a '.' to start of file name, convert from ugly dos \'s in path
420 * to lovely unix /'s :-} */
423 safe_strcpy(tptr
, fp
, l
);
424 string_replace(tptr
, '\\', '/');
427 /****************************************************************************
428 Convert from decimal to octal string
429 ****************************************************************************/
430 static void oct_it (long value
, int ndgs
, char *p
)
432 /* Converts long to octal string, pads with leading zeros */
434 /* skip final null, but do final space */
438 /* Loop does at least one digit */
440 p
[--ndgs
] = '0' + (char) (value
& 7);
443 while (ndgs
> 0 && value
!= 0);
445 /* Do leading zeros */
450 /****************************************************************************
451 Convert from octal string to long
452 ***************************************************************************/
453 static long unoct(char *p
, int ndgs
)
456 /* Converts octal string to long, ignoring any non-digit */
460 if (isdigit((int)*p
))
461 value
= (value
<< 3) | (long) (*p
- '0');
469 /****************************************************************************
470 Compare two strings in a slash insensitive way, allowing s1 to match s2
471 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
472 a file in any subdirectory of s1, declare a match.
473 ***************************************************************************/
474 static int strslashcmp(char *s1
, char *s2
)
480 || tolower(*s1
) == tolower(*s2
)
481 || (*s1
== '\\' && *s2
=='/')
482 || (*s1
== '/' && *s2
=='\\'))) {
486 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
489 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\')) return 0;
491 /* ignore trailing slash on s1 */
492 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1)) return 0;
494 /* check for s1 is an "initial" string of s2 */
495 if ((*s2
== '/' || *s2
== '\\') && !*s1
) return 0;
501 /****************************************************************************
502 Ensure a remote path exists (make if necessary)
503 ***************************************************************************/
504 static BOOL
ensurepath(char *fname
)
506 /* *must* be called with buffer ready malloc'ed */
507 /* ensures path exists */
509 char *partpath
, *ffname
;
510 char *p
=fname
, *basehack
;
512 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
514 partpath
= string_create_s(strlen(fname
));
515 ffname
= string_create_s(strlen(fname
));
517 if ((partpath
== NULL
) || (ffname
== NULL
)){
519 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
526 /* fname copied to ffname so can strtok */
528 safe_strcpy(ffname
, fname
, strlen(fname
));
530 /* do a `basename' on ffname, so don't try and make file name directory */
531 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
)
536 p
=strtok(ffname
, "\\");
540 safe_strcat(partpath
, p
, strlen(fname
) + 1);
542 if (!cli_chkpath(cli
, partpath
)) {
543 if (!cli_mkdir(cli
, partpath
))
545 DEBUG(0, ("Error mkdirhiering\n"));
549 DEBUG(3, ("mkdirhiering %s\n", partpath
));
553 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
554 p
= strtok(NULL
,"/\\");
560 static int padit(char *buf
, int bufsize
, int padsize
)
565 DEBUG(5, ("Padding with %d zeros\n", padsize
));
566 memset(buf
, 0, bufsize
);
567 while( !berr
&& padsize
> 0 ) {
568 bytestowrite
= MIN(bufsize
, padsize
);
569 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
570 padsize
-= bytestowrite
;
577 static void do_setrattr(char *name
, uint16 attr
, int set
)
581 if (!cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
)) return;
583 if (set
== ATTRSET
) {
586 attr
= oldattr
& ~attr
;
589 if (!cli_setatr(cli
, name
, attr
, 0)) {
590 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
595 /****************************************************************************
596 append one remote file to the tar file
597 ***************************************************************************/
598 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
604 BOOL close_done
= False
;
605 BOOL shallitime
=True
;
607 int read_size
= 65520;
610 struct timeval tp_start
;
611 GetTimeOfDay(&tp_start
);
613 ftype
= '0'; /* An ordinary file ... */
616 finfo
.size
= finfo1
-> size
;
617 finfo
.mode
= finfo1
-> mode
;
618 finfo
.uid
= finfo1
-> uid
;
619 finfo
.gid
= finfo1
-> gid
;
620 finfo
.mtime
= finfo1
-> mtime
;
621 finfo
.atime
= finfo1
-> atime
;
622 finfo
.ctime
= finfo1
-> ctime
;
625 finfo
.size
= def_finfo
.size
;
626 finfo
.mode
= def_finfo
.mode
;
627 finfo
.uid
= def_finfo
.uid
;
628 finfo
.gid
= def_finfo
.gid
;
629 finfo
.mtime
= def_finfo
.mtime
;
630 finfo
.atime
= def_finfo
.atime
;
631 finfo
.ctime
= def_finfo
.ctime
;
636 DEBUG(3,("skipping file %s of size %d bytes\n",
640 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
645 fnum
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
);
647 dos_clean_name(rname
);
650 DEBUG(0,("%s opening remote file %s (%s)\n",
651 cli_errstr(cli
),rname
, cur_dir
));
655 finfo
.name
= string_create_s(strlen(rname
));
656 if (finfo
.name
== NULL
) {
657 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
661 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
663 if (!cli_getattrE(cli
, fnum
, &finfo
.mode
, &finfo
.size
, NULL
, &finfo
.atime
, &finfo
.mtime
)) {
664 DEBUG(0, ("getattrE: %s\n", cli_errstr(cli
)));
667 finfo
.ctime
= finfo
.mtime
;
670 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
672 if (tar_inc
&& !(finfo
.mode
& aARCH
))
674 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
677 else if (!tar_system
&& (finfo
.mode
& aSYSTEM
))
679 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
682 else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
))
684 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
689 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
694 /* write a tar header, don't bother with mode - just set to 100644 */
695 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
697 while (nread
< finfo
.size
&& !close_done
) {
699 DEBUG(3,("nread=%d\n",nread
));
701 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
704 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
710 /* if file size has increased since we made file size query, truncate
711 read so tar header for this file will be correct.
714 if (nread
> finfo
.size
) {
715 datalen
-= nread
- finfo
.size
;
716 DEBUG(0,("File size change - truncating %s to %d bytes\n", finfo
.name
, (int)finfo
.size
));
719 /* add received bits of file to buffer - dotarbuf will
720 * write out in 512 byte intervals */
721 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
722 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
727 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
734 /* pad tar file with zero's if we couldn't get entire file */
735 if (nread
< finfo
.size
) {
736 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", (int)finfo
.size
, (int)nread
));
737 if (padit(data
, sizeof(data
), finfo
.size
- nread
))
738 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
741 /* round tar file to nearest block */
742 if (finfo
.size
% TBLOCK
)
743 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
745 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
749 cli_close(cli
, fnum
);
753 struct timeval tp_end
;
756 /* if shallitime is true then we didn't skip */
757 if (tar_reset
&& !dry_run
)
758 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
760 GetTimeOfDay(&tp_end
);
762 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
763 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
764 get_total_time_ms
+= this_time
;
765 get_total_size
+= finfo
.size
;
769 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
770 (int)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
774 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
775 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
776 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
777 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
781 /****************************************************************************
782 Append single file to tar file (or not)
783 ***************************************************************************/
784 static void do_tar(file_info
*finfo
)
788 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
791 /* Is it on the exclude list ? */
792 if (!tar_excl
&& clipn
) {
795 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir
)));
797 safe_strcpy(exclaim
, cur_dir
, sizeof(pstring
));
798 *(exclaim
+strlen(exclaim
)-1)='\0';
800 safe_strcat(exclaim
, "\\", sizeof(pstring
));
801 safe_strcat(exclaim
, finfo
->name
, sizeof(exclaim
));
803 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
805 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
807 (tar_re_search
&& !regexec(preg
, exclaim
, 0, NULL
, 0))) {
809 (tar_re_search
&& mask_match(exclaim
, cliplist
[0], True
))) {
811 DEBUG(3,("Skipping file %s\n", exclaim
));
816 if (finfo
->mode
& aDIR
)
818 pstring saved_curdir
;
821 safe_strcpy(saved_curdir
, cur_dir
, sizeof(saved_curdir
));
823 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
));
825 safe_strcat(cur_dir
,finfo
->name
, sizeof(cur_dir
));
826 safe_strcat(cur_dir
,"\\", sizeof(cur_dir
));
828 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
830 /* write a tar directory, don't bother with mode - just set it to
832 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
834 DEBUG(0,(" directory %s\n", cur_dir
));
836 ntarf
++; /* Make sure we have a file on there */
837 safe_strcpy(mtar_mask
,cur_dir
, sizeof(pstring
));
838 safe_strcat(mtar_mask
,"*", sizeof(pstring
));
839 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
840 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
841 safe_strcpy(cur_dir
,saved_curdir
, sizeof(pstring
));
845 safe_strcpy(rname
,cur_dir
, sizeof(pstring
));
846 safe_strcat(rname
,finfo
->name
, sizeof(pstring
));
847 do_atar(rname
,finfo
->name
,finfo
);
851 /****************************************************************************
852 Convert from UNIX to DOS file names
853 ***************************************************************************/
854 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
)
856 /* remove '.' from start of file name, convert from unix /'s to
857 * dos \'s in path. Kill any absolute path names. But only if first!
860 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
867 if (*fp
== '\\' || *fp
== '/') {
873 safe_strcpy(tptr
, fp
, l
);
874 string_replace(tptr
, '/', '\\');
878 /****************************************************************************
879 Move to the next block in the buffer, which may mean read in another set of
880 blocks. FIXME, we should allow more than one block to be skipped.
881 ****************************************************************************/
882 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
884 int bufread
, total
= 0;
886 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
890 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
892 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
895 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
896 * Fixes bug where read can return short if coming from
900 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
903 while (total
< bufsiz
) {
904 if (bufread
< 0) { /* An error, return false */
905 return (total
> 0 ? -2 : bufread
);
913 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
917 DEBUG(5, ("Total bytes read ... %i\n", total
));
927 /* Skip a file, even if it includes a long file name? */
928 static int skip_file(int skipsize
)
930 int dsize
= skipsize
;
932 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
934 /* FIXME, we should skip more than one block at a time */
938 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
940 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
952 /*************************************************************
953 Get a file from the tar file and store it.
954 When this is called, tarbuf already contains the first
955 file block. This is a bit broken & needs fixing.
956 **************************************************************/
958 static int get_file(file_info2 finfo
)
960 int fnum
= -1, pos
= 0, dsize
= 0, rsize
= 0, bpos
= 0;
962 DEBUG(5, ("get_file: file: %s, size %i\n", finfo
.name
, (int)finfo
.size
));
964 if (ensurepath(finfo
.name
) &&
965 (fnum
=cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
)) == -1) {
966 DEBUG(0, ("abandoning restore\n"));
970 /* read the blocks from the tar file and write to the remote file */
972 rsize
= finfo
.size
; /* This is how much to write */
976 /* We can only write up to the end of the buffer */
978 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
979 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
980 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
982 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
983 DEBUG(0, ("Error writing remote file\n"));
990 /* Now figure out how much to move in the buffer */
992 /* FIXME, we should skip more than one block at a time */
994 /* First, skip any initial part of the part written that is left over */
995 /* from the end of the first TBLOCK */
997 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
999 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1002 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1003 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1011 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1012 * If the file being extracted is an exact multiple of
1013 * TBLOCK bytes then we don't want to extract the next
1014 * block from the tarfile here, as it will be done in
1015 * the caller of get_file().
1018 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1019 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1021 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1022 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1033 /* Now close the file ... */
1035 if (!cli_close(cli
, fnum
)) {
1036 DEBUG(0, ("Error closing remote file\n"));
1040 /* Now we update the creation date ... */
1042 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1044 if (!cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime
)) {
1045 if (tar_real_noisy
) {
1046 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1047 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1053 DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo
.name
, (int)finfo
.size
));
1058 /* Create a directory. We just ensure that the path exists and return as there
1059 is no file associated with a directory
1061 static int get_dir(file_info2 finfo
)
1064 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1066 if (!ensurepath(finfo
.name
)) {
1068 DEBUG(0, ("Problems creating directory\n"));
1077 /* Get a file with a long file name ... first file has file name, next file
1078 has the data. We only want the long file name, as the loop in do_tarput
1079 will deal with the rest.
1081 static char * get_longfilename(file_info2 finfo
)
1083 int namesize
= finfo
.size
+ strlen(cur_dir
) + 2;
1084 char *longname
= malloc(namesize
);
1085 int offset
= 0, left
= finfo
.size
;
1088 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1089 DEBUG(5, ("Len = %d\n", (int)finfo
.size
));
1091 if (longname
== NULL
) {
1093 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1094 (int)(finfo
.size
+ strlen(cur_dir
) + 2)));
1098 /* First, add cur_dir to the long file name */
1100 if (strlen(cur_dir
) > 0) {
1101 strncpy(longname
, cur_dir
, namesize
);
1102 offset
= strlen(cur_dir
);
1105 /* Loop through the blocks picking up the name */
1109 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1111 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1116 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1117 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1128 static void do_tarput(void)
1131 struct timeval tp_start
;
1132 char *longfilename
= NULL
, linkflag
;
1135 GetTimeOfDay(&tp_start
);
1137 DEBUG(5, ("RJS do_tarput called ...\n"));
1139 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1141 /* Now read through those files ... */
1145 /* Get us to the next block, or the first block first time around */
1147 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1149 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1155 DEBUG(5, ("Reading the next header ...\n"));
1157 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
)) {
1159 case -2: /* Hmm, not good, but not fatal */
1160 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1161 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) &&
1162 !skip_file(finfo
.size
)) {
1164 DEBUG(0, ("Short file, bailing out...\n"));
1172 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1175 case 0: /* chksum is zero - looks like an EOF */
1176 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1177 return; /* Hmmm, bad here ... */
1186 /* Now, do we have a long file name? */
1188 if (longfilename
!= NULL
) {
1190 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1191 finfo
.name
= longfilename
;
1192 longfilename
= NULL
;
1196 /* Well, now we have a header, process the file ... */
1198 /* Should we skip the file? We have the long name as well here */
1201 ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
)
1203 || (tar_re_search
&& !regexec(preg
, finfo
.name
, 0, NULL
, 0)));
1205 || (tar_re_search
&& mask_match(finfo
.name
, cliplist
[0], True
)));
1208 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1212 skip_file(finfo
.size
);
1217 /* We only get this far if we should process the file */
1218 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1222 case '0': /* Should use symbolic names--FIXME */
1225 * Skip to the next block first, so we can get the file, FIXME, should
1226 * be in get_file ...
1227 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1228 * Fixes bug where file size in tarfile is zero.
1231 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1232 DEBUG(0, ("Short file, bailing out...\n"));
1235 if (!get_file(finfo
)) {
1236 DEBUG(0, ("Abandoning restore\n"));
1243 if (!get_dir(finfo
)) {
1244 DEBUG(0, ("Abandoning restore \n"));
1250 longfilename
= get_longfilename(finfo
);
1251 if (!longfilename
) {
1252 DEBUG(0, ("abandoning restore\n"));
1256 DEBUG(5, ("Long file name: %s\n", longfilename
));
1260 skip_file(finfo
.size
); /* Don't handle these yet */
1272 * samba interactive commands
1275 /****************************************************************************
1277 ***************************************************************************/
1283 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1285 DEBUG(0, ("blocksize <n>\n"));
1290 if (block
< 0 || block
> 65535)
1292 DEBUG(0, ("blocksize out of range"));
1297 DEBUG(2,("blocksize is now %d\n", blocksize
));
1302 /****************************************************************************
1303 command to set incremental / reset mode
1304 ***************************************************************************/
1305 int cmd_tarmode(void)
1309 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1310 if (strequal(buf
, "full"))
1312 else if (strequal(buf
, "inc"))
1314 else if (strequal(buf
, "reset"))
1316 else if (strequal(buf
, "noreset"))
1318 else if (strequal(buf
, "system"))
1320 else if (strequal(buf
, "nosystem"))
1322 else if (strequal(buf
, "hidden"))
1324 else if (strequal(buf
, "nohidden"))
1326 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1328 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1330 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1333 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1334 tar_inc
? "incremental" : "full",
1335 tar_system
? "system" : "nosystem",
1336 tar_hidden
? "hidden" : "nohidden",
1337 tar_reset
? "reset" : "noreset",
1338 tar_noisy
? "verbose" : "quiet"));
1343 /****************************************************************************
1344 Feeble attrib command
1345 ***************************************************************************/
1346 int cmd_setmode(void)
1354 attra
[0] = attra
[1] = 0;
1356 if (!next_token_nr(NULL
,buf
,NULL
,sizeof(buf
)))
1358 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1362 safe_strcpy(fname
, cur_dir
, sizeof(pstring
));
1363 safe_strcat(fname
, buf
, sizeof(pstring
));
1365 while (next_token_nr(NULL
,buf
,NULL
,sizeof(buf
))) {
1374 case 'r': attra
[direct
]|=aRONLY
;
1376 case 'h': attra
[direct
]|=aHIDDEN
;
1378 case 's': attra
[direct
]|=aSYSTEM
;
1380 case 'a': attra
[direct
]|=aARCH
;
1382 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1387 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0)
1389 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1393 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1394 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1395 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))
1426 /****************************************************************************
1427 Command line (option) version
1428 ***************************************************************************/
1429 int process_tar(void)
1445 if (clipn
&& tar_excl
) {
1449 for (i
=0; i
<clipn
; i
++) {
1450 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1452 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1453 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1456 if (strrchr_m(cliplist
[i
], '\\')) {
1459 safe_strcpy(saved_dir
, cur_dir
, sizeof(pstring
));
1461 if (*cliplist
[i
]=='\\') {
1462 safe_strcpy(tarmac
, cliplist
[i
], sizeof(pstring
));
1464 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
1465 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
1467 safe_strcpy(cur_dir
, tarmac
, sizeof(pstring
));
1468 *(strrchr_m(cur_dir
, '\\')+1)='\0';
1470 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1471 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1472 safe_strcpy(cur_dir
,saved_dir
, sizeof(pstring
));
1474 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
1475 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
1476 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1477 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1482 safe_strcpy(mask
,cur_dir
, sizeof(pstring
));
1483 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1484 safe_strcat(mask
,"\\*", sizeof(pstring
));
1485 do_list(mask
,attribute
,do_tar
,False
, True
);
1488 if (ntarf
) dotareof(tarhandle
);
1492 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1493 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1497 if (must_free_cliplist
) {
1499 for (i
= 0; i
< clipn
; ++i
) {
1500 SAFE_FREE(cliplist
[i
]);
1502 SAFE_FREE(cliplist
);
1505 must_free_cliplist
= False
;
1511 /****************************************************************************
1512 Find a token (filename) in a clip list
1513 ***************************************************************************/
1514 static int clipfind(char **aret
, int ret
, char *tok
)
1516 if (aret
==NULL
) return 0;
1518 /* ignore leading slashes or dots in token */
1519 while(strchr_m("/\\.", *tok
)) tok
++;
1524 /* ignore leading slashes or dots in list */
1525 while(strchr_m("/\\.", *pkey
)) pkey
++;
1527 if (!strslashcmp(pkey
, tok
)) return 1;
1533 /****************************************************************************
1534 Read list of files to include from the file and initialize cliplist
1536 ***************************************************************************/
1537 static int read_inclusion_file(char *filename
)
1539 XFILE
*inclusion
= NULL
;
1540 char buf
[MAXPATHLEN
+ 1];
1541 char *inclusion_buffer
= NULL
;
1542 int inclusion_buffer_size
= 0;
1543 int inclusion_buffer_sofar
= 0;
1550 buf
[MAXPATHLEN
] = '\0'; /* guarantee null-termination */
1551 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1552 /* XXX It would be better to include a reason for failure, but without
1553 * autoconf, it's hard to use strerror, sys_errlist, etc.
1555 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1559 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1560 if (inclusion_buffer
== NULL
) {
1561 inclusion_buffer_size
= 1024;
1562 if ((inclusion_buffer
= malloc(inclusion_buffer_size
)) == NULL
) {
1563 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1569 if (buf
[strlen(buf
)-1] == '\n') {
1570 buf
[strlen(buf
)-1] = '\0';
1573 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1575 inclusion_buffer_size
*= 2;
1576 ib
= Realloc(inclusion_buffer
,inclusion_buffer_size
);
1578 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1579 inclusion_buffer_size
));
1583 else inclusion_buffer
= ib
;
1586 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1587 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1590 x_fclose(inclusion
);
1593 /* Allocate an array of clipn + 1 char*'s for cliplist */
1594 cliplist
= malloc((clipn
+ 1) * sizeof(char *));
1595 if (cliplist
== NULL
) {
1596 DEBUG(0,("failure allocating memory for cliplist\n"));
1599 cliplist
[clipn
] = NULL
;
1600 p
= inclusion_buffer
;
1601 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1602 /* set current item to NULL so array will be null-terminated even if
1603 * malloc fails below. */
1605 if ((tmpstr
= (char *)malloc(strlen(p
)+1)) == NULL
) {
1606 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1609 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1610 cliplist
[i
] = tmpstr
;
1611 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1612 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1618 must_free_cliplist
= True
;
1622 SAFE_FREE(inclusion_buffer
);
1626 /* We know cliplist is always null-terminated */
1627 for (pp
= cliplist
; *pp
; ++pp
) {
1630 SAFE_FREE(cliplist
);
1632 must_free_cliplist
= False
;
1637 /* cliplist and its elements are freed at the end of process_tar. */
1641 /****************************************************************************
1642 Parse tar arguments. Sets tar_type, tar_excl, etc.
1643 ***************************************************************************/
1644 int tar_parseargs(int argc
, char *argv
[], char *Optarg
, int Optind
)
1646 char tar_clipfl
='\0';
1648 /* Reset back to defaults - could be from interactive version
1649 * reset mode and archive mode left as they are though
1661 if (tar_type
=='c') {
1662 printf("Tar must be followed by only one of c or x.\n");
1668 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1669 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1680 DEBUG(0,("Option N must be followed by valid file name\n"));
1683 SMB_STRUCT_STAT stbuf
;
1684 extern time_t newer_than
;
1686 if (sys_stat(argv
[Optind
], &stbuf
) == 0) {
1687 newer_than
= stbuf
.st_mtime
;
1688 DEBUG(1,("Getting files newer than %s",
1689 asctime(LocalTime(&newer_than
))));
1692 DEBUG(0,("Error setting newer-than time\n"));
1705 DEBUG(0,("Only one of I,X,F must be specified\n"));
1712 DEBUG(0,("Only one of I,X,F must be specified\n"));
1719 DEBUG(0,("Only one of I,X,F must be specified\n"));
1725 DEBUG(0, ("tar_re_search set\n"));
1726 tar_re_search
= True
;
1729 if (tar_type
== 'c') {
1730 DEBUG(0, ("dry_run set\n"));
1733 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1738 DEBUG(0,("Unknown tar option\n"));
1743 printf("Option T must be followed by one of c or x.\n");
1747 /* tar_excl is true if cliplist lists files to be included.
1748 * Both 'I' and 'F' mean include. */
1749 tar_excl
=tar_clipfl
!='X';
1751 if (tar_clipfl
=='F') {
1752 if (argc
-Optind
-1 != 1) {
1753 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1756 if (! read_inclusion_file(argv
[Optind
+1])) {
1759 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1764 cliplist
=argv
+Optind
+1;
1765 clipn
=argc
-Optind
-1;
1768 if ((tmplist
=malloc(clipn
*sizeof(char *))) == NULL
) {
1769 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
1775 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1777 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1779 if ((tmpstr
= (char *)malloc(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1780 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
1785 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1786 tmplist
[clipcount
] = tmpstr
;
1787 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1789 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1792 must_free_cliplist
= True
;
1795 if (Optind
+1<argc
&& tar_re_search
) { /* Doing regular expression seaches */
1799 if ((preg
= (regex_t
*)malloc(65536)) == NULL
) {
1801 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
1806 if (errcode
= regcomp(preg
, argv
[Optind
+ 1], REG_EXTENDED
)) {
1810 errlen
= regerror(errcode
, preg
, errstr
, sizeof(errstr
) - 1);
1812 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv
[Optind
+ 1], errstr
));
1818 clipn
=argc
-Optind
-1;
1819 cliplist
=argv
+Optind
+1;
1823 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1824 /* Sets tar handle to either 0 or 1, as appropriate */
1825 tarhandle
=(tar_type
=='c');
1827 * Make sure that dbf points to stderr if we are using stdout for
1833 if (tar_type
=='c' && (dry_run
|| strcmp(argv
[Optind
], "/dev/null")==0))
1836 DEBUG(0,("Output is /dev/null, assuming dry_run"));
1841 if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1842 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0))
1844 DEBUG(0,("Error opening local file %s - %s\n",
1845 argv
[Optind
], strerror(errno
)));