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 3 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, see <http://www.gnu.org/licenses/>.
20 /* The following changes developed by Richard Sharpe for Canon Information
21 Systems Research Australia (CISRA)
23 1. Restore can now restore files with long file names
24 2. Save now saves directory information so that we can restore
25 directory creation times
26 3. tar now accepts both UNIX path names and DOS path names. I prefer
27 those lovely /'s to those UGLY \'s :-)
28 4. the files to exclude can be specified as a regular expression by adding
29 an r flag to the other tar flags. Eg:
31 -TcrX file.tar "*.(obj|exe)"
33 will skip all .obj and .exe files
39 #include "client/client_proto.h"
41 static int clipfind(char **aret
, int ret
, char *tok
);
43 typedef struct file_info_struct file_info2
;
45 struct file_info_struct
{
50 /* These times are normally kept in GMT */
51 struct timespec mtime_ts
;
52 struct timespec atime_ts
;
53 struct timespec ctime_ts
;
54 char *name
; /* This is dynamically allocated */
55 file_info2
*next
, *prev
; /* Used in the stack ... */
63 #define SEPARATORS " \t\n\r"
64 extern time_t newer_than
;
65 extern struct cli_state
*cli
;
67 /* These defines are for the do_setrattr routine, to indicate
68 * setting and reseting of file attributes in the function call */
72 static uint16 attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
74 #ifndef CLIENT_TIMEOUT
75 #define CLIENT_TIMEOUT (30*1000)
78 static char *tarbuf
, *buffer_p
;
79 static int tp
, ntarf
, tbufsiz
;
81 /* Incremental mode */
82 static bool tar_inc
=False
;
83 /* Reset archive bit */
84 static bool tar_reset
=False
;
85 /* Include / exclude mode (true=include, false=exclude) */
86 static bool tar_excl
=True
;
87 /* use regular expressions for search on file names */
88 static bool tar_re_search
=False
;
89 /* Do not dump anything, just calculate sizes */
90 static bool dry_run
=False
;
91 /* Dump files with System attribute */
92 static bool tar_system
=True
;
93 /* Dump files with Hidden attribute */
94 static bool tar_hidden
=True
;
95 /* Be noisy - make a catalogue */
96 static bool tar_noisy
=True
;
97 static bool tar_real_noisy
=False
; /* Don't want to be really noisy by default */
100 static char **cliplist
=NULL
;
102 static bool must_free_cliplist
= False
;
103 extern const char *cmd_ptr
;
105 extern bool lowercase
;
107 extern bool readbraw_supported
;
109 extern int get_total_time_ms
;
110 extern int get_total_size
;
112 static int blocksize
=20;
113 static int tarhandle
;
115 static void writetarheader(int f
, const char *aname
, uint64_t size
, time_t mtime
,
116 const char *amode
, unsigned char ftype
);
117 static void do_atar(const char *rname_in
,char *lname
,file_info
*finfo1
);
118 static void do_tar(file_info
*finfo
, const char *dir
);
119 static void oct_it(uint64_t value
, int ndgs
, char *p
);
120 static void fixtarname(char *tptr
, const char *fp
, size_t l
);
121 static int dotarbuf(int f
, char *b
, int n
);
122 static void dozerobuf(int f
, int n
);
123 static void dotareof(int f
);
124 static void initarbuf(void);
126 /* restore functions */
127 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, const char *prefix
);
128 static long unoct(char *p
, int ndgs
);
129 static void do_tarput(void);
130 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
);
133 * tar specific utitlities
136 /*******************************************************************
137 Create a string of size size+1 (for the null)
138 *******************************************************************/
140 static char *string_create_s(int size
)
144 tmp
= (char *)SMB_MALLOC(size
+1);
147 DEBUG(0, ("Out of memory in string_create_s\n"));
153 /****************************************************************************
154 Write a tar header to buffer
155 ****************************************************************************/
157 static void writetarheader(int f
, const char *aname
, uint64_t size
, time_t mtime
,
158 const char *amode
, unsigned char ftype
)
164 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype
, (double)size
, aname
));
166 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
169 /* We will be prepending a '.' in fixtarheader so use +2 to
170 * take care of the . and terminating zero. JRA.
173 /* write a GNU tar style long header */
175 b
= (char *)SMB_MALLOC(l
+TBLOCK
+100);
177 DEBUG(0,("out of memory\n"));
180 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
181 memset(b
, 0, l
+TBLOCK
+100);
182 fixtarname(b
, aname
, l
+2);
184 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
185 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
189 fixtarname(hb
.dbuf
.name
, aname
, (l
+2 >= NAMSIZ
) ? NAMSIZ
: l
+ 2);
192 strlower_m(hb
.dbuf
.name
);
194 /* write out a "standard" tar format header */
196 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
197 safe_strcpy(hb
.dbuf
.mode
, amode
, sizeof(hb
.dbuf
.mode
)-1);
198 oct_it((uint64_t)0, 8, hb
.dbuf
.uid
);
199 oct_it((uint64_t)0, 8, hb
.dbuf
.gid
);
200 oct_it((uint64_t) size
, 13, hb
.dbuf
.size
);
201 if (size
> (uint64_t)077777777777LL) {
202 /* This is a non-POSIX compatible extention to store files
205 memset(hb
.dbuf
.size
, 0, 4);
207 for (i
= 8; i
; i
--) {
208 hb
.dbuf
.size
[i
+3] = size
& 0xff;
212 oct_it((uint64_t) mtime
, 13, hb
.dbuf
.mtime
);
213 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
214 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
215 hb
.dbuf
.linkflag
=ftype
;
217 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;)
220 oct_it((uint64_t) chk
, 8, hb
.dbuf
.chksum
);
221 hb
.dbuf
.chksum
[6] = '\0';
223 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
226 /****************************************************************************
227 Read a tar header into a hblock structure, and validate
228 ***************************************************************************/
230 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, const 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;)
248 /* compensate for blanks in chksum header */
249 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
252 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
254 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
256 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
257 chk
, fchk
, hb
->dbuf
.chksum
));
260 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
261 dump_data(5, (uint8
*)hb
- TBLOCK
, TBLOCK
*3);
265 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
266 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
270 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
272 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
273 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
274 strlen(hb
->dbuf
.name
) + 1, True
);
276 /* can't handle some links at present */
277 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
278 if (hb
->dbuf
.linkflag
== 0) {
279 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
282 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
283 /* Do nothing here at the moment. do_tarput will handle this
284 as long as the longlink gets back to it, as it has to advance
285 the buffer pointer, etc */
287 DEBUG(0, ("this tar file appears to contain some kind \
288 of link other than a GNUtar Longlink - ignoring\n"));
294 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
) ||
295 (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\')) {
298 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
299 * just make it a regular file */
303 * Bug fix by richard@sj.co.uk
305 * REC: restore times correctly (as does tar)
306 * We only get the modification time of the file; set the creation time
307 * from the mod. time, and the access time to current time
309 finfo
->mtime_ts
= finfo
->ctime_ts
=
310 convert_time_t_to_timespec((time_t)strtol(hb
->dbuf
.mtime
, NULL
, 8));
311 finfo
->atime_ts
= convert_time_t_to_timespec(time(NULL
));
312 if ((hb
->dbuf
.size
[0] & 0xff) == 0x80) {
313 /* This is a non-POSIX compatible extention to extract files
316 for (i
= 0; i
< 8; i
++) {
318 finfo
->size
|= hb
->dbuf
.size
[i
+4] & 0xff;
321 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
327 /****************************************************************************
328 Write out the tar buffer to tape or wherever
329 ****************************************************************************/
331 static int dotarbuf(int f
, char *b
, int n
)
338 /* This routine and the next one should be the only ones that do write()s */
339 if (tp
+ n
>= tbufsiz
) {
343 memcpy(tarbuf
+ tp
, b
, diff
);
344 fail
=fail
&& (1+sys_write(f
, tarbuf
, tbufsiz
));
349 while (n
>= tbufsiz
) {
350 fail
=fail
&& (1 + sys_write(f
, b
, tbufsiz
));
357 memcpy(tarbuf
+tp
, b
, n
);
361 return(fail
? writ
: 0);
364 /****************************************************************************
365 Write zeros to buffer / tape
366 ****************************************************************************/
368 static void dozerobuf(int f
, int n
)
370 /* short routine just to write out n zeros to buffer -
371 * used to round files to nearest block
372 * and to do tar EOFs */
377 if (n
+tp
>= tbufsiz
) {
378 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
379 if (sys_write(f
, tarbuf
, tbufsiz
) != tbufsiz
) {
380 DEBUG(0, ("dozerobuf: sys_write fail\n"));
383 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
385 memset(tarbuf
+tp
, 0, n
);
390 /****************************************************************************
392 ****************************************************************************/
394 static void initarbuf(void)
396 /* initialize tar buffer */
397 tbufsiz
=blocksize
*TBLOCK
;
398 tarbuf
=(char *)SMB_MALLOC(tbufsiz
); /* FIXME: We might not get the buffer */
400 /* reset tar buffer pointer and tar file counter and total dumped */
401 tp
=0; ntarf
=0; ttarf
=0;
404 /****************************************************************************
405 Write two zero blocks at end of file
406 ****************************************************************************/
408 static void dotareof(int f
)
410 SMB_STRUCT_STAT stbuf
;
411 /* Two zero blocks at end of file, write out full buffer */
416 (void) dozerobuf(f
, TBLOCK
);
417 (void) dozerobuf(f
, TBLOCK
);
419 if (sys_fstat(f
, &stbuf
, false) == -1) {
420 DEBUG(0, ("Couldn't stat file handle\n"));
424 /* Could be a pipe, in which case S_ISREG should fail,
425 * and we should write out at full size */
427 size_t towrite
= S_ISREG(stbuf
.st_ex_mode
) ? tp
: tbufsiz
;
428 if (sys_write(f
, tarbuf
, towrite
) != towrite
) {
429 DEBUG(0,("dotareof: sys_write fail\n"));
434 /****************************************************************************
435 (Un)mangle DOS pathname, make nonabsolute
436 ****************************************************************************/
438 static void fixtarname(char *tptr
, const char *fp
, size_t l
)
440 /* add a '.' to start of file name, convert from ugly dos \'s in path
441 * to lovely unix /'s :-} */
445 StrnCpy(tptr
, fp
, l
-1);
446 string_replace(tptr
, '\\', '/');
449 /****************************************************************************
450 Convert from decimal to octal string
451 ****************************************************************************/
453 static void oct_it (uint64_t value
, int ndgs
, char *p
)
455 /* Converts long to octal string, pads with leading zeros */
457 /* skip final null, but do final space */
461 /* Loop does at least one digit */
463 p
[--ndgs
] = '0' + (char) (value
& 7);
465 } while (ndgs
> 0 && value
!= 0);
467 /* Do leading zeros */
472 /****************************************************************************
473 Convert from octal string to long
474 ***************************************************************************/
476 static long unoct(char *p
, int ndgs
)
479 /* Converts octal string to long, ignoring any non-digit */
482 if (isdigit((int)*p
))
483 value
= (value
<< 3) | (long) (*p
- '0');
491 /****************************************************************************
492 Compare two strings in a slash insensitive way, allowing s1 to match s2
493 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
494 a file in any subdirectory of s1, declare a match.
495 ***************************************************************************/
497 static int strslashcmp(char *s1
, char *s2
)
501 while(*s1
&& *s2
&& (*s1
== *s2
|| tolower_ascii(*s1
) == tolower_ascii(*s2
) ||
502 (*s1
== '\\' && *s2
=='/') || (*s1
== '/' && *s2
=='\\'))) {
506 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
509 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\'))
512 /* ignore trailing slash on s1 */
513 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1))
516 /* check for s1 is an "initial" string of s2 */
517 if ((*s2
== '/' || *s2
== '\\') && !*s1
)
523 /****************************************************************************
524 Ensure a remote path exists (make if necessary)
525 ***************************************************************************/
527 static bool ensurepath(const char *fname
)
529 /* *must* be called with buffer ready malloc'ed */
530 /* ensures path exists */
532 char *partpath
, *ffname
;
537 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
539 partpath
= string_create_s(strlen(fname
));
540 ffname
= string_create_s(strlen(fname
));
542 if ((partpath
== NULL
) || (ffname
== NULL
)){
543 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
551 /* fname copied to ffname so can strtok_r */
553 safe_strcpy(ffname
, fname
, strlen(fname
));
555 /* do a `basename' on ffname, so don't try and make file name directory */
556 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
) {
564 p
=strtok_r(ffname
, "\\", &saveptr
);
567 safe_strcat(partpath
, p
, strlen(fname
) + 1);
569 if (!NT_STATUS_IS_OK(cli_chkpath(cli
, partpath
))) {
570 if (!NT_STATUS_IS_OK(cli_mkdir(cli
, partpath
))) {
573 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli
)));
576 DEBUG(3, ("mkdirhiering %s\n", partpath
));
580 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
581 p
= strtok_r(NULL
, "/\\", &saveptr
);
589 static int padit(char *buf
, uint64_t bufsize
, uint64_t padsize
)
594 DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize
));
595 memset(buf
, 0, (size_t)bufsize
);
596 while( !berr
&& padsize
> 0 ) {
597 bytestowrite
= (int)MIN(bufsize
, padsize
);
598 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
599 padsize
-= bytestowrite
;
605 static void do_setrattr(char *name
, uint16 attr
, int set
)
609 if (!NT_STATUS_IS_OK(cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
))) {
613 if (set
== ATTRSET
) {
616 attr
= oldattr
& ~attr
;
619 if (!NT_STATUS_IS_OK(cli_setatr(cli
, name
, attr
, 0))) {
620 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
624 /****************************************************************************
625 append one remote file to the tar file
626 ***************************************************************************/
628 static void do_atar(const char *rname_in
,char *lname
,file_info
*finfo1
)
630 uint16_t fnum
= (uint16_t)-1;
634 bool shallitime
=True
;
636 int read_size
= 65520;
639 TALLOC_CTX
*ctx
= talloc_stackframe();
641 struct timeval tp_start
;
643 GetTimeOfDay(&tp_start
);
645 data
= SMB_MALLOC_ARRAY(char, read_size
);
647 DEBUG(0,("do_atar: out of memory.\n"));
651 ftype
= '0'; /* An ordinary file ... */
655 finfo
.size
= finfo1
-> size
;
656 finfo
.mode
= finfo1
-> mode
;
657 finfo
.uid
= finfo1
-> uid
;
658 finfo
.gid
= finfo1
-> gid
;
659 finfo
.mtime_ts
= finfo1
-> mtime_ts
;
660 finfo
.atime_ts
= finfo1
-> atime_ts
;
661 finfo
.ctime_ts
= finfo1
-> ctime_ts
;
664 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1
->name
,
665 (double)finfo
.size
));
667 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
672 rname
= clean_name(ctx
, rname_in
);
677 if (!NT_STATUS_IS_OK(cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
, &fnum
))) {
678 DEBUG(0,("%s opening remote file %s (%s)\n",
679 cli_errstr(cli
),rname
, client_get_cur_dir()));
683 finfo
.name
= string_create_s(strlen(rname
));
684 if (finfo
.name
== NULL
) {
685 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
689 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
691 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
693 if (tar_inc
&& !(finfo
.mode
& aARCH
)) {
694 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
696 } else if (!tar_system
&& (finfo
.mode
& aSYSTEM
)) {
697 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
699 } else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
)) {
700 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
703 bool wrote_tar_header
= False
;
705 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
706 finfo
.name
, (double)finfo
.size
, lname
));
710 DEBUG(3,("nread=%.0f\n",(double)nread
));
712 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
715 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
721 /* Only if the first read succeeds, write out the tar header. */
722 if (!wrote_tar_header
) {
723 /* write a tar header, don't bother with mode - just set to 100644 */
724 writetarheader(tarhandle
, rname
, finfo
.size
,
725 finfo
.mtime_ts
.tv_sec
, "100644 \0", ftype
);
726 wrote_tar_header
= True
;
729 /* if file size has increased since we made file size query, truncate
730 read so tar header for this file will be correct.
733 if (nread
> finfo
.size
) {
734 datalen
-= nread
- finfo
.size
;
735 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
736 finfo
.name
, (double)finfo
.size
));
739 /* add received bits of file to buffer - dotarbuf will
740 * write out in 512 byte intervals */
742 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
743 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
747 if ( (datalen
== 0) && (finfo
.size
!= 0) ) {
748 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
753 } while ( nread
< finfo
.size
);
755 if (wrote_tar_header
) {
756 /* pad tar file with zero's if we couldn't get entire file */
757 if (nread
< finfo
.size
) {
758 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
759 (double)finfo
.size
, (int)nread
));
760 if (padit(data
, (uint64_t)sizeof(data
), finfo
.size
- nread
))
761 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
764 /* round tar file to nearest block */
765 if (finfo
.size
% TBLOCK
)
766 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
768 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
771 DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo
.name
));
776 cli_close(cli
, fnum
);
780 struct timeval tp_end
;
783 /* if shallitime is true then we didn't skip */
784 if (tar_reset
&& !dry_run
)
785 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
787 GetTimeOfDay(&tp_end
);
788 this_time
= (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 + (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
789 get_total_time_ms
+= this_time
;
790 get_total_size
+= finfo
.size
;
793 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
794 (double)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
))));
806 if (fnum
!= (uint16_t)-1) {
807 cli_close(cli
, fnum
);
814 /****************************************************************************
815 Append single file to tar file (or not)
816 ***************************************************************************/
818 static void do_tar(file_info
*finfo
, const char *dir
)
820 TALLOC_CTX
*ctx
= talloc_stackframe();
822 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
825 /* Is it on the exclude list ? */
826 if (!tar_excl
&& clipn
) {
829 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir())));
831 exclaim
= talloc_asprintf(ctx
,
833 client_get_cur_dir(),
839 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
841 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
842 (tar_re_search
&& mask_match_list(exclaim
, cliplist
, clipn
, True
))) {
843 DEBUG(3,("Skipping file %s\n", exclaim
));
844 TALLOC_FREE(exclaim
);
847 TALLOC_FREE(exclaim
);
850 if (finfo
->mode
& aDIR
) {
851 char *saved_curdir
= NULL
;
853 char *mtar_mask
= NULL
;
855 saved_curdir
= talloc_strdup(ctx
, client_get_cur_dir());
860 DEBUG(5, ("strlen(cur_dir)=%d, \
861 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
862 (int)strlen(saved_curdir
),
863 (int)strlen(finfo
->name
), finfo
->name
, saved_curdir
));
865 new_cd
= talloc_asprintf(ctx
,
867 client_get_cur_dir(),
872 client_set_cur_dir(new_cd
);
874 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir()));
876 /* write a tar directory, don't bother with mode - just
878 writetarheader(tarhandle
, client_get_cur_dir(), 0,
879 finfo
->mtime_ts
.tv_sec
, "040755 \0", '5');
881 DEBUG(0,(" directory %s\n",
882 client_get_cur_dir()));
884 ntarf
++; /* Make sure we have a file on there */
885 mtar_mask
= talloc_asprintf(ctx
,
887 client_get_cur_dir());
891 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
892 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
893 client_set_cur_dir(saved_curdir
);
894 TALLOC_FREE(saved_curdir
);
896 TALLOC_FREE(mtar_mask
);
898 char *rname
= talloc_asprintf(ctx
,
900 client_get_cur_dir(),
905 do_atar(rname
,finfo
->name
,finfo
);
910 /****************************************************************************
911 Convert from UNIX to DOS file names
912 ***************************************************************************/
914 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
)
916 /* remove '.' from start of file name, convert from unix /'s to
917 * dos \'s in path. Kill any absolute path names. But only if first!
920 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
927 if (*fp
== '\\' || *fp
== '/') {
933 safe_strcpy(tptr
, fp
, l
);
934 string_replace(tptr
, '/', '\\');
937 /****************************************************************************
938 Move to the next block in the buffer, which may mean read in another set of
939 blocks. FIXME, we should allow more than one block to be skipped.
940 ****************************************************************************/
942 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
944 int bufread
, total
= 0;
946 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
950 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
952 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
955 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
956 * Fixes bug where read can return short if coming from
960 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
963 while (total
< bufsiz
) {
964 if (bufread
< 0) { /* An error, return false */
965 return (total
> 0 ? -2 : bufread
);
973 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
977 DEBUG(5, ("Total bytes read ... %i\n", total
));
985 /* Skip a file, even if it includes a long file name? */
986 static int skip_file(int skipsize
)
988 int dsize
= skipsize
;
990 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
992 /* FIXME, we should skip more than one block at a time */
995 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
996 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1005 /*************************************************************
1006 Get a file from the tar file and store it.
1007 When this is called, tarbuf already contains the first
1008 file block. This is a bit broken & needs fixing.
1009 **************************************************************/
1011 static int get_file(file_info2 finfo
)
1014 int dsize
= 0, bpos
= 0;
1015 uint64_t rsize
= 0, pos
= 0;
1017 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo
.name
, (double)finfo
.size
));
1019 if (ensurepath(finfo
.name
) &&
1020 (!NT_STATUS_IS_OK(cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
,&fnum
)))) {
1021 DEBUG(0, ("abandoning restore\n"));
1025 /* read the blocks from the tar file and write to the remote file */
1027 rsize
= finfo
.size
; /* This is how much to write */
1031 /* We can only write up to the end of the buffer */
1032 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
1033 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
1034 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
1036 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
1037 DEBUG(0, ("Error writing remote file\n"));
1044 /* Now figure out how much to move in the buffer */
1046 /* FIXME, we should skip more than one block at a time */
1048 /* First, skip any initial part of the part written that is left over */
1049 /* from the end of the first TBLOCK */
1051 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1052 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1055 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1056 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1062 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1063 * If the file being extracted is an exact multiple of
1064 * TBLOCK bytes then we don't want to extract the next
1065 * block from the tarfile here, as it will be done in
1066 * the caller of get_file().
1069 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1070 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1072 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1073 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1082 /* Now close the file ... */
1084 if (!NT_STATUS_IS_OK(cli_close(cli
, fnum
))) {
1085 DEBUG(0, ("Error %s closing remote file\n",
1090 /* Now we update the creation date ... */
1091 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1093 if (!NT_STATUS_IS_OK(cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime_ts
.tv_sec
))) {
1094 if (tar_real_noisy
) {
1095 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1096 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1101 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo
.name
, (double)finfo
.size
));
1105 /* Create a directory. We just ensure that the path exists and return as there
1106 is no file associated with a directory
1108 static int get_dir(file_info2 finfo
)
1110 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1112 if (!ensurepath(finfo
.name
)) {
1113 DEBUG(0, ("Problems creating directory\n"));
1120 /* Get a file with a long file name ... first file has file name, next file
1121 has the data. We only want the long file name, as the loop in do_tarput
1122 will deal with the rest.
1124 static char *get_longfilename(file_info2 finfo
)
1126 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1128 int namesize
= finfo
.size
+ strlen(client_get_cur_dir()) + 2;
1129 char *longname
= (char *)SMB_MALLOC(namesize
);
1130 int offset
= 0, left
= finfo
.size
;
1133 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1134 DEBUG(5, ("Len = %.0f\n", (double)finfo
.size
));
1136 if (longname
== NULL
) {
1137 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize
));
1141 /* First, add cur_dir to the long file name */
1143 if (strlen(client_get_cur_dir()) > 0) {
1144 strncpy(longname
, client_get_cur_dir(), namesize
);
1145 offset
= strlen(client_get_cur_dir());
1148 /* Loop through the blocks picking up the name */
1151 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1152 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1153 SAFE_FREE(longname
);
1157 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1158 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1167 static void do_tarput(void)
1170 struct timeval tp_start
;
1171 char *longfilename
= NULL
, linkflag
;
1176 GetTimeOfDay(&tp_start
);
1177 DEBUG(5, ("RJS do_tarput called ...\n"));
1179 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1181 /* Now read through those files ... */
1183 /* Get us to the next block, or the first block first time around */
1184 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1185 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1186 SAFE_FREE(longfilename
);
1190 DEBUG(5, ("Reading the next header ...\n"));
1192 switch (readtarheader((union hblock
*) buffer_p
,
1193 &finfo
, client_get_cur_dir())) {
1194 case -2: /* Hmm, not good, but not fatal */
1195 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1196 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) && !skip_file(finfo
.size
)) {
1197 DEBUG(0, ("Short file, bailing out...\n"));
1203 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1206 case 0: /* chksum is zero - looks like an EOF */
1207 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1208 return; /* Hmmm, bad here ... */
1215 /* Now, do we have a long file name? */
1216 if (longfilename
!= NULL
) {
1217 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1218 finfo
.name
= longfilename
;
1219 longfilename
= NULL
;
1222 /* Well, now we have a header, process the file ... */
1223 /* Should we skip the file? We have the long name as well here */
1224 skip
= clipn
&& ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
) ||
1225 (tar_re_search
&& mask_match_list(finfo
.name
, cliplist
, clipn
, True
)));
1227 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1229 skip_file(finfo
.size
);
1233 /* We only get this far if we should process the file */
1234 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1236 case '0': /* Should use symbolic names--FIXME */
1238 * Skip to the next block first, so we can get the file, FIXME, should
1239 * be in get_file ...
1240 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1241 * Fixes bug where file size in tarfile is zero.
1243 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1244 DEBUG(0, ("Short file, bailing out...\n"));
1247 if (!get_file(finfo
)) {
1248 DEBUG(0, ("Abandoning restore\n"));
1253 if (!get_dir(finfo
)) {
1254 DEBUG(0, ("Abandoning restore \n"));
1259 SAFE_FREE(longfilename
);
1260 longfilename
= get_longfilename(finfo
);
1261 if (!longfilename
) {
1262 DEBUG(0, ("abandoning restore\n"));
1265 DEBUG(5, ("Long file name: %s\n", longfilename
));
1269 skip_file(finfo
.size
); /* Don't handle these yet */
1276 * samba interactive commands
1279 /****************************************************************************
1281 ***************************************************************************/
1285 TALLOC_CTX
*ctx
= talloc_tos();
1289 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1290 DEBUG(0, ("blocksize <n>\n"));
1295 if (block
< 0 || block
> 65535) {
1296 DEBUG(0, ("blocksize out of range"));
1301 DEBUG(2,("blocksize is now %d\n", blocksize
));
1305 /****************************************************************************
1306 command to set incremental / reset mode
1307 ***************************************************************************/
1309 int cmd_tarmode(void)
1311 TALLOC_CTX
*ctx
= talloc_tos();
1314 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1315 if (strequal(buf
, "full"))
1317 else if (strequal(buf
, "inc"))
1319 else if (strequal(buf
, "reset"))
1321 else if (strequal(buf
, "noreset"))
1323 else if (strequal(buf
, "system"))
1325 else if (strequal(buf
, "nosystem"))
1327 else if (strequal(buf
, "hidden"))
1329 else if (strequal(buf
, "nohidden"))
1331 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1333 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1336 DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1340 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1341 tar_inc
? "incremental" : "full",
1342 tar_system
? "system" : "nosystem",
1343 tar_hidden
? "hidden" : "nohidden",
1344 tar_reset
? "reset" : "noreset",
1345 tar_noisy
? "verbose" : "quiet"));
1349 /****************************************************************************
1350 Feeble attrib command
1351 ***************************************************************************/
1353 int cmd_setmode(void)
1355 TALLOC_CTX
*ctx
= talloc_tos();
1362 attra
[0] = attra
[1] = 0;
1364 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1365 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1369 fname
= talloc_asprintf(ctx
,
1371 client_get_cur_dir(),
1377 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1389 attra
[direct
]|=aRONLY
;
1392 attra
[direct
]|=aHIDDEN
;
1395 attra
[direct
]|=aSYSTEM
;
1398 attra
[direct
]|=aARCH
;
1401 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1407 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0) {
1408 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1412 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1413 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1414 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1419 Convert list of tokens to array; dependent on above routine.
1420 Uses the global cmd_ptr from above - bit of a hack.
1423 static char **toktocliplist(int *ctok
, const char *sep
)
1425 char *s
=(char *)cmd_ptr
;
1432 while(*s
&& strchr_m(sep
,*s
))
1441 while(*s
&& (!strchr_m(sep
,*s
)))
1443 while(*s
&& strchr_m(sep
,*s
))
1450 if (!(ret
=iret
=SMB_MALLOC_ARRAY(char *,ictok
+1)))
1467 /****************************************************************************
1468 Principal command for creating / extracting
1469 ***************************************************************************/
1473 TALLOC_CTX
*ctx
= talloc_tos();
1479 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1480 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1484 argl
=toktocliplist(&argcl
, NULL
);
1485 if (!tar_parseargs(argcl
, argl
, buf
, 0)) {
1490 ret
= process_tar();
1495 /****************************************************************************
1496 Command line (option) version
1497 ***************************************************************************/
1499 int process_tar(void)
1501 TALLOC_CTX
*ctx
= talloc_tos();
1517 if (clipn
&& tar_excl
) {
1519 char *tarmac
= NULL
;
1521 for (i
=0; i
<clipn
; i
++) {
1522 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1524 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1525 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1528 if (strrchr_m(cliplist
[i
], '\\')) {
1531 char *saved_dir
= talloc_strdup(ctx
,
1532 client_get_cur_dir());
1537 if (*cliplist
[i
]=='\\') {
1538 tarmac
= talloc_strdup(ctx
,
1541 tarmac
= talloc_asprintf(ctx
,
1543 client_get_cur_dir(),
1550 * Strip off the last \\xxx
1551 * xxx element of tarmac to set
1552 * it as current directory.
1554 p
= strrchr_m(tarmac
, '\\');
1561 client_set_cur_dir(tarmac
);
1564 * Restore the character we
1571 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1572 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1574 client_set_cur_dir(saved_dir
);
1576 TALLOC_FREE(saved_dir
);
1577 TALLOC_FREE(tarmac
);
1579 tarmac
= talloc_asprintf(ctx
,
1581 client_get_cur_dir(),
1586 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1587 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1588 TALLOC_FREE(tarmac
);
1592 char *mask
= talloc_asprintf(ctx
,
1594 client_get_cur_dir());
1598 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1599 do_list(mask
,attribute
,do_tar
,False
, True
);
1604 dotareof(tarhandle
);
1609 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1610 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1614 if (must_free_cliplist
) {
1616 for (i
= 0; i
< clipn
; ++i
) {
1617 SAFE_FREE(cliplist
[i
]);
1619 SAFE_FREE(cliplist
);
1622 must_free_cliplist
= False
;
1627 /****************************************************************************
1628 Find a token (filename) in a clip list
1629 ***************************************************************************/
1631 static int clipfind(char **aret
, int ret
, char *tok
)
1636 /* ignore leading slashes or dots in token */
1637 while(strchr_m("/\\.", *tok
))
1643 /* ignore leading slashes or dots in list */
1644 while(strchr_m("/\\.", *pkey
))
1647 if (!strslashcmp(pkey
, tok
))
1653 /****************************************************************************
1654 Read list of files to include from the file and initialize cliplist
1656 ***************************************************************************/
1658 static int read_inclusion_file(char *filename
)
1660 XFILE
*inclusion
= NULL
;
1661 char buf
[PATH_MAX
+ 1];
1662 char *inclusion_buffer
= NULL
;
1663 int inclusion_buffer_size
= 0;
1664 int inclusion_buffer_sofar
= 0;
1671 buf
[PATH_MAX
] = '\0'; /* guarantee null-termination */
1672 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1673 /* XXX It would be better to include a reason for failure, but without
1674 * autoconf, it's hard to use strerror, sys_errlist, etc.
1676 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1680 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1681 if (inclusion_buffer
== NULL
) {
1682 inclusion_buffer_size
= 1024;
1683 if ((inclusion_buffer
= (char *)SMB_MALLOC(inclusion_buffer_size
)) == NULL
) {
1684 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1690 if (buf
[strlen(buf
)-1] == '\n') {
1691 buf
[strlen(buf
)-1] = '\0';
1694 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1695 inclusion_buffer_size
*= 2;
1696 inclusion_buffer
= (char *)SMB_REALLOC(inclusion_buffer
,inclusion_buffer_size
);
1697 if (!inclusion_buffer
) {
1698 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1699 inclusion_buffer_size
));
1705 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1706 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1709 x_fclose(inclusion
);
1712 /* Allocate an array of clipn + 1 char*'s for cliplist */
1713 cliplist
= SMB_MALLOC_ARRAY(char *, clipn
+ 1);
1714 if (cliplist
== NULL
) {
1715 DEBUG(0,("failure allocating memory for cliplist\n"));
1718 cliplist
[clipn
] = NULL
;
1719 p
= inclusion_buffer
;
1720 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1721 /* set current item to NULL so array will be null-terminated even if
1722 * malloc fails below. */
1724 if ((tmpstr
= (char *)SMB_MALLOC(strlen(p
)+1)) == NULL
) {
1725 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1728 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1729 cliplist
[i
] = tmpstr
;
1730 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1731 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1737 must_free_cliplist
= True
;
1741 SAFE_FREE(inclusion_buffer
);
1745 /* We know cliplist is always null-terminated */
1746 for (pp
= cliplist
; *pp
; ++pp
) {
1749 SAFE_FREE(cliplist
);
1751 must_free_cliplist
= False
;
1756 /* cliplist and its elements are freed at the end of process_tar. */
1760 /****************************************************************************
1761 Parse tar arguments. Sets tar_type, tar_excl, etc.
1762 ***************************************************************************/
1764 int tar_parseargs(int argc
, char *argv
[], const char *Optarg
, int Optind
)
1766 int newOptind
= Optind
;
1767 char tar_clipfl
='\0';
1769 /* Reset back to defaults - could be from interactive version
1770 * reset mode and archive mode left as they are though
1782 if (tar_type
=='c') {
1783 printf("Tar must be followed by only one of c or x.\n");
1789 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1790 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1802 DEBUG(0,("Option N must be followed by valid file name\n"));
1805 SMB_STRUCT_STAT stbuf
;
1807 if (sys_stat(argv
[Optind
], &stbuf
,
1809 newer_than
= convert_timespec_to_time_t(
1811 DEBUG(1,("Getting files newer than %s",
1812 time_to_asc(newer_than
)));
1816 DEBUG(0,("Error setting newer-than time\n"));
1829 DEBUG(0,("Only one of I,X,F must be specified\n"));
1836 DEBUG(0,("Only one of I,X,F must be specified\n"));
1843 DEBUG(0,("Only one of I,X,F must be specified\n"));
1849 DEBUG(0, ("tar_re_search set\n"));
1850 tar_re_search
= True
;
1853 if (tar_type
== 'c') {
1854 DEBUG(0, ("dry_run set\n"));
1857 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1862 DEBUG(0,("Unknown tar option\n"));
1868 printf("Option T must be followed by one of c or x.\n");
1872 /* tar_excl is true if cliplist lists files to be included.
1873 * Both 'I' and 'F' mean include. */
1874 tar_excl
=tar_clipfl
!='X';
1876 if (tar_clipfl
=='F') {
1877 if (argc
-Optind
-1 != 1) {
1878 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1882 /* Optind points at the tar output file, Optind+1 at the inclusion file. */
1883 if (! read_inclusion_file(argv
[Optind
+1])) {
1886 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1891 cliplist
=argv
+Optind
+1;
1892 clipn
=argc
-Optind
-1;
1895 if ((tmplist
=SMB_MALLOC_ARRAY(char *,clipn
)) == NULL
) {
1896 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn
));
1900 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1902 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1904 if ((tmpstr
= (char *)SMB_MALLOC(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1905 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount
));
1910 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1911 tmplist
[clipcount
] = tmpstr
;
1912 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1914 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1918 must_free_cliplist
= True
;
1923 if (Optind
+1<argc
&& tar_re_search
&& tar_clipfl
!= 'F') {
1924 /* Doing regular expression seaches not from an inclusion file. */
1925 clipn
=argc
-Optind
-1;
1926 cliplist
=argv
+Optind
+1;
1930 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1931 /* Sets tar handle to either 0 or 1, as appropriate */
1932 tarhandle
=(tar_type
=='c');
1934 * Make sure that dbf points to stderr if we are using stdout for
1937 if (tarhandle
== 1) {
1940 if (!argv
[Optind
]) {
1941 DEBUG(0,("Must specify tar filename\n"));
1944 if (!strcmp(argv
[Optind
], "-")) {
1949 if (tar_type
=='c' && dry_run
) {
1951 } else if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1952 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0)) {
1953 DEBUG(0,("Error opening local file %s - %s\n", argv
[Optind
], strerror(errno
)));