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
38 #include "system/filesys.h"
40 #include "client/client_proto.h"
41 #include "libsmb/libsmb.h"
43 static int clipfind(char **aret
, int ret
, char *tok
);
45 typedef struct file_info_struct file_info2
;
47 struct file_info_struct
{
52 /* These times are normally kept in GMT */
53 struct timespec mtime_ts
;
54 struct timespec atime_ts
;
55 struct timespec ctime_ts
;
56 char *name
; /* This is dynamically allocated */
57 file_info2
*next
, *prev
; /* Used in the stack ... */
65 #define SEPARATORS " \t\n\r"
66 extern time_t newer_than
;
67 extern struct cli_state
*cli
;
69 /* These defines are for the do_setrattr routine, to indicate
70 * setting and reseting of file attributes in the function call */
74 static uint16 attribute
= FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
76 #ifndef CLIENT_TIMEOUT
77 #define CLIENT_TIMEOUT (30*1000)
80 static char *tarbuf
, *buffer_p
;
81 static int tp
, ntarf
, tbufsiz
;
83 /* Incremental mode */
84 static bool tar_inc
=False
;
85 /* Reset archive bit */
86 static bool tar_reset
=False
;
87 /* Include / exclude mode (true=include, false=exclude) */
88 static bool tar_excl
=True
;
89 /* use regular expressions for search on file names */
90 static bool tar_re_search
=False
;
91 /* Do not dump anything, just calculate sizes */
92 static bool dry_run
=False
;
93 /* Dump files with System attribute */
94 static bool tar_system
=True
;
95 /* Dump files with Hidden attribute */
96 static bool tar_hidden
=True
;
97 /* Be noisy - make a catalogue */
98 static bool tar_noisy
=True
;
99 static bool tar_real_noisy
=False
; /* Don't want to be really noisy by default */
102 static char **cliplist
=NULL
;
104 static bool must_free_cliplist
= False
;
105 extern const char *cmd_ptr
;
107 extern bool lowercase
;
109 extern bool readbraw_supported
;
111 extern int get_total_time_ms
;
112 extern int get_total_size
;
114 static int blocksize
=20;
115 static int tarhandle
;
117 static void writetarheader(int f
, const char *aname
, uint64_t size
, time_t mtime
,
118 const char *amode
, unsigned char ftype
);
119 static NTSTATUS
do_atar(const char *rname_in
, char *lname
,
120 struct file_info
*finfo1
);
121 static NTSTATUS
do_tar(struct cli_state
*cli_state
, struct file_info
*finfo
,
123 static void oct_it(uint64_t value
, int ndgs
, char *p
);
124 static void fixtarname(char *tptr
, const char *fp
, size_t l
);
125 static int dotarbuf(int f
, char *b
, int n
);
126 static void dozerobuf(int f
, int n
);
127 static void dotareof(int f
);
128 static void initarbuf(void);
130 /* restore functions */
131 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, const char *prefix
);
132 static long unoct(char *p
, int ndgs
);
133 static void do_tarput(void);
134 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
);
137 * tar specific utitlities
140 /*******************************************************************
141 Create a string of size size+1 (for the null)
142 *******************************************************************/
144 static char *string_create_s(int size
)
148 tmp
= (char *)SMB_MALLOC(size
+1);
151 DEBUG(0, ("Out of memory in string_create_s\n"));
157 /****************************************************************************
158 Write a tar header to buffer
159 ****************************************************************************/
161 static void writetarheader(int f
, const char *aname
, uint64_t size
, time_t mtime
,
162 const char *amode
, unsigned char ftype
)
168 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype
, (double)size
, aname
));
170 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
173 /* We will be prepending a '.' in fixtarheader so use +2 to
174 * take care of the . and terminating zero. JRA.
177 /* write a GNU tar style long header */
179 b
= (char *)SMB_MALLOC(l
+TBLOCK
+100);
181 DEBUG(0,("out of memory\n"));
184 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
185 memset(b
, 0, l
+TBLOCK
+100);
186 fixtarname(b
, aname
, l
+2);
188 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
189 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
193 fixtarname(hb
.dbuf
.name
, aname
, (l
+2 >= NAMSIZ
) ? NAMSIZ
: l
+ 2);
196 strlower_m(hb
.dbuf
.name
);
198 /* write out a "standard" tar format header */
200 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
201 safe_strcpy(hb
.dbuf
.mode
, amode
, sizeof(hb
.dbuf
.mode
)-1);
202 oct_it((uint64_t)0, 8, hb
.dbuf
.uid
);
203 oct_it((uint64_t)0, 8, hb
.dbuf
.gid
);
204 oct_it((uint64_t) size
, 13, hb
.dbuf
.size
);
205 if (size
> (uint64_t)077777777777LL) {
206 /* This is a non-POSIX compatible extention to store files
209 memset(hb
.dbuf
.size
, 0, 4);
211 for (i
= 8; i
; i
--) {
212 hb
.dbuf
.size
[i
+3] = size
& 0xff;
216 oct_it((uint64_t) mtime
, 13, hb
.dbuf
.mtime
);
217 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
218 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
219 hb
.dbuf
.linkflag
=ftype
;
221 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;)
224 oct_it((uint64_t) chk
, 8, hb
.dbuf
.chksum
);
225 hb
.dbuf
.chksum
[6] = '\0';
227 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
230 /****************************************************************************
231 Read a tar header into a hblock structure, and validate
232 ***************************************************************************/
234 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, const char *prefix
)
241 * read in a "standard" tar format header - we're not that interested
242 * in that many fields, though
245 /* check the checksum */
246 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;)
252 /* compensate for blanks in chksum header */
253 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
256 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
258 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
260 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
261 chk
, fchk
, hb
->dbuf
.chksum
));
264 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
265 dump_data(5, (uint8
*)hb
- TBLOCK
, TBLOCK
*3);
269 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
270 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
274 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
276 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
277 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
278 strlen(hb
->dbuf
.name
) + 1, True
);
280 /* can't handle some links at present */
281 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
282 if (hb
->dbuf
.linkflag
== 0) {
283 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
286 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
287 /* Do nothing here at the moment. do_tarput will handle this
288 as long as the longlink gets back to it, as it has to advance
289 the buffer pointer, etc */
291 DEBUG(0, ("this tar file appears to contain some kind \
292 of link other than a GNUtar Longlink - ignoring\n"));
298 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
) ||
299 (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\')) {
300 finfo
->mode
=FILE_ATTRIBUTE_DIRECTORY
;
302 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
303 * just make it a regular file */
307 * Bug fix by richard@sj.co.uk
309 * REC: restore times correctly (as does tar)
310 * We only get the modification time of the file; set the creation time
311 * from the mod. time, and the access time to current time
313 finfo
->mtime_ts
= finfo
->ctime_ts
=
314 convert_time_t_to_timespec((time_t)strtol(hb
->dbuf
.mtime
, NULL
, 8));
315 finfo
->atime_ts
= convert_time_t_to_timespec(time(NULL
));
316 if ((hb
->dbuf
.size
[0] & 0xff) == 0x80) {
317 /* This is a non-POSIX compatible extention to extract files
320 for (i
= 0; i
< 8; i
++) {
322 finfo
->size
|= hb
->dbuf
.size
[i
+4] & 0xff;
325 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
331 /****************************************************************************
332 Write out the tar buffer to tape or wherever
333 ****************************************************************************/
335 static int dotarbuf(int f
, char *b
, int n
)
342 /* This routine and the next one should be the only ones that do write()s */
343 if (tp
+ n
>= tbufsiz
) {
347 memcpy(tarbuf
+ tp
, b
, diff
);
348 fail
=fail
&& (1+sys_write(f
, tarbuf
, tbufsiz
));
353 while (n
>= tbufsiz
) {
354 fail
=fail
&& (1 + sys_write(f
, b
, tbufsiz
));
361 memcpy(tarbuf
+tp
, b
, n
);
365 return(fail
? writ
: 0);
368 /****************************************************************************
369 Write zeros to buffer / tape
370 ****************************************************************************/
372 static void dozerobuf(int f
, int n
)
374 /* short routine just to write out n zeros to buffer -
375 * used to round files to nearest block
376 * and to do tar EOFs */
381 if (n
+tp
>= tbufsiz
) {
382 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
383 if (sys_write(f
, tarbuf
, tbufsiz
) != tbufsiz
) {
384 DEBUG(0, ("dozerobuf: sys_write fail\n"));
387 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
389 memset(tarbuf
+tp
, 0, n
);
394 /****************************************************************************
396 ****************************************************************************/
398 static void initarbuf(void)
400 /* initialize tar buffer */
401 tbufsiz
=blocksize
*TBLOCK
;
402 tarbuf
=(char *)SMB_MALLOC(tbufsiz
); /* FIXME: We might not get the buffer */
404 /* reset tar buffer pointer and tar file counter and total dumped */
405 tp
=0; ntarf
=0; ttarf
=0;
408 /****************************************************************************
409 Write two zero blocks at end of file
410 ****************************************************************************/
412 static void dotareof(int f
)
414 SMB_STRUCT_STAT stbuf
;
415 /* Two zero blocks at end of file, write out full buffer */
420 (void) dozerobuf(f
, TBLOCK
);
421 (void) dozerobuf(f
, TBLOCK
);
423 if (sys_fstat(f
, &stbuf
, false) == -1) {
424 DEBUG(0, ("Couldn't stat file handle\n"));
428 /* Could be a pipe, in which case S_ISREG should fail,
429 * and we should write out at full size */
431 size_t towrite
= S_ISREG(stbuf
.st_ex_mode
) ? tp
: tbufsiz
;
432 if (sys_write(f
, tarbuf
, towrite
) != towrite
) {
433 DEBUG(0,("dotareof: sys_write fail\n"));
438 /****************************************************************************
439 (Un)mangle DOS pathname, make nonabsolute
440 ****************************************************************************/
442 static void fixtarname(char *tptr
, const char *fp
, size_t l
)
444 /* add a '.' to start of file name, convert from ugly dos \'s in path
445 * to lovely unix /'s :-} */
449 StrnCpy(tptr
, fp
, l
-1);
450 string_replace(tptr
, '\\', '/');
453 /****************************************************************************
454 Convert from decimal to octal string
455 ****************************************************************************/
457 static void oct_it (uint64_t value
, int ndgs
, char *p
)
459 /* Converts long to octal string, pads with leading zeros */
461 /* skip final null, but do final space */
465 /* Loop does at least one digit */
467 p
[--ndgs
] = '0' + (char) (value
& 7);
469 } while (ndgs
> 0 && value
!= 0);
471 /* Do leading zeros */
476 /****************************************************************************
477 Convert from octal string to long
478 ***************************************************************************/
480 static long unoct(char *p
, int ndgs
)
483 /* Converts octal string to long, ignoring any non-digit */
486 if (isdigit((int)*p
))
487 value
= (value
<< 3) | (long) (*p
- '0');
495 /****************************************************************************
496 Compare two strings in a slash insensitive way, allowing s1 to match s2
497 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
498 a file in any subdirectory of s1, declare a match.
499 ***************************************************************************/
501 static int strslashcmp(char *s1
, char *s2
)
505 while(*s1
&& *s2
&& (*s1
== *s2
|| tolower_m(*s1
) == tolower_m(*s2
) ||
506 (*s1
== '\\' && *s2
=='/') || (*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) == '\\'))
516 /* ignore trailing slash on s1 */
517 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1))
520 /* check for s1 is an "initial" string of s2 */
521 if ((*s2
== '/' || *s2
== '\\') && !*s1
)
527 /****************************************************************************
528 Ensure a remote path exists (make if necessary)
529 ***************************************************************************/
531 static bool ensurepath(const char *fname
)
533 /* *must* be called with buffer ready malloc'ed */
534 /* ensures path exists */
536 char *partpath
, *ffname
;
541 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
543 partpath
= string_create_s(strlen(fname
));
544 ffname
= string_create_s(strlen(fname
));
546 if ((partpath
== NULL
) || (ffname
== NULL
)){
547 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
555 /* fname copied to ffname so can strtok_r */
557 safe_strcpy(ffname
, fname
, strlen(fname
));
559 /* do a `basename' on ffname, so don't try and make file name directory */
560 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
) {
568 p
=strtok_r(ffname
, "\\", &saveptr
);
571 safe_strcat(partpath
, p
, strlen(fname
) + 1);
573 if (!NT_STATUS_IS_OK(cli_chkpath(cli
, partpath
))) {
574 if (!NT_STATUS_IS_OK(cli_mkdir(cli
, partpath
))) {
577 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli
)));
580 DEBUG(3, ("mkdirhiering %s\n", partpath
));
584 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
585 p
= strtok_r(NULL
, "/\\", &saveptr
);
593 static int padit(char *buf
, uint64_t bufsize
, uint64_t padsize
)
598 DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize
));
599 memset(buf
, 0, (size_t)bufsize
);
600 while( !berr
&& padsize
> 0 ) {
601 bytestowrite
= (int)MIN(bufsize
, padsize
);
602 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
603 padsize
-= bytestowrite
;
609 static void do_setrattr(char *name
, uint16 attr
, int set
)
613 if (!NT_STATUS_IS_OK(cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
))) {
617 if (set
== ATTRSET
) {
620 attr
= oldattr
& ~attr
;
623 if (!NT_STATUS_IS_OK(cli_setatr(cli
, name
, attr
, 0))) {
624 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
628 /****************************************************************************
629 append one remote file to the tar file
630 ***************************************************************************/
632 static NTSTATUS
do_atar(const char *rname_in
, char *lname
,
633 struct file_info
*finfo1
)
635 uint16_t fnum
= (uint16_t)-1;
639 bool shallitime
=True
;
641 int read_size
= 65520;
644 TALLOC_CTX
*ctx
= talloc_stackframe();
645 NTSTATUS status
= NT_STATUS_OK
;
646 struct timespec tp_start
;
648 clock_gettime_mono(&tp_start
);
650 data
= SMB_MALLOC_ARRAY(char, read_size
);
652 DEBUG(0,("do_atar: out of memory.\n"));
653 status
= NT_STATUS_NO_MEMORY
;
657 ftype
= '0'; /* An ordinary file ... */
661 finfo
.size
= finfo1
-> size
;
662 finfo
.mode
= finfo1
-> mode
;
663 finfo
.uid
= finfo1
-> uid
;
664 finfo
.gid
= finfo1
-> gid
;
665 finfo
.mtime_ts
= finfo1
-> mtime_ts
;
666 finfo
.atime_ts
= finfo1
-> atime_ts
;
667 finfo
.ctime_ts
= finfo1
-> ctime_ts
;
670 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1
->name
,
671 (double)finfo
.size
));
673 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
678 rname
= clean_name(ctx
, rname_in
);
680 status
= NT_STATUS_NO_MEMORY
;
684 status
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
, &fnum
);
685 if (!NT_STATUS_IS_OK(status
)) {
686 DEBUG(0,("%s opening remote file %s (%s)\n",
687 cli_errstr(cli
),rname
, client_get_cur_dir()));
691 finfo
.name
= string_create_s(strlen(rname
));
692 if (finfo
.name
== NULL
) {
693 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
694 status
= NT_STATUS_NO_MEMORY
;
698 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
700 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
702 if (tar_inc
&& !(finfo
.mode
& FILE_ATTRIBUTE_ARCHIVE
)) {
703 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
705 } else if (!tar_system
&& (finfo
.mode
& FILE_ATTRIBUTE_SYSTEM
)) {
706 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
708 } else if (!tar_hidden
&& (finfo
.mode
& FILE_ATTRIBUTE_HIDDEN
)) {
709 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
712 bool wrote_tar_header
= False
;
714 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
715 finfo
.name
, (double)finfo
.size
, lname
));
719 DEBUG(3,("nread=%.0f\n",(double)nread
));
721 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
724 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
725 status
= cli_nt_error(cli
);
731 /* Only if the first read succeeds, write out the tar header. */
732 if (!wrote_tar_header
) {
733 /* write a tar header, don't bother with mode - just set to 100644 */
734 writetarheader(tarhandle
, rname
, finfo
.size
,
735 finfo
.mtime_ts
.tv_sec
, "100644 \0", ftype
);
736 wrote_tar_header
= True
;
739 /* if file size has increased since we made file size query, truncate
740 read so tar header for this file will be correct.
743 if (nread
> finfo
.size
) {
744 datalen
-= nread
- finfo
.size
;
745 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
746 finfo
.name
, (double)finfo
.size
));
749 /* add received bits of file to buffer - dotarbuf will
750 * write out in 512 byte intervals */
752 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
753 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
754 status
= map_nt_error_from_unix(errno
);
758 if ( (datalen
== 0) && (finfo
.size
!= 0) ) {
759 status
= NT_STATUS_UNSUCCESSFUL
;
760 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
765 } while ( nread
< finfo
.size
);
767 if (wrote_tar_header
) {
768 /* pad tar file with zero's if we couldn't get entire file */
769 if (nread
< finfo
.size
) {
770 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
771 (double)finfo
.size
, (int)nread
));
772 if (padit(data
, (uint64_t)sizeof(data
), finfo
.size
- nread
)) {
773 status
= map_nt_error_from_unix(errno
);
774 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
778 /* round tar file to nearest block */
779 if (finfo
.size
% TBLOCK
)
780 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
782 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
785 DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo
.name
));
787 status
= NT_STATUS_UNSUCCESSFUL
;
791 cli_close(cli
, fnum
);
795 struct timespec tp_end
;
798 /* if shallitime is true then we didn't skip */
799 if (tar_reset
&& !dry_run
)
800 (void) do_setrattr(finfo
.name
, FILE_ATTRIBUTE_ARCHIVE
, ATTRRESET
);
802 clock_gettime_mono(&tp_end
);
803 this_time
= (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 + (tp_end
.tv_nsec
- tp_start
.tv_nsec
)/1000000;
804 get_total_time_ms
+= this_time
;
805 get_total_size
+= finfo
.size
;
808 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
809 (double)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
813 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
814 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
815 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
816 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
821 if (fnum
!= (uint16_t)-1) {
822 cli_close(cli
, fnum
);
830 /****************************************************************************
831 Append single file to tar file (or not)
832 ***************************************************************************/
834 static NTSTATUS
do_tar(struct cli_state
*cli_state
, struct file_info
*finfo
,
837 TALLOC_CTX
*ctx
= talloc_stackframe();
838 NTSTATUS status
= NT_STATUS_OK
;
840 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,".")) {
841 status
= NT_STATUS_OK
;
845 /* Is it on the exclude list ? */
846 if (!tar_excl
&& clipn
) {
849 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir())));
851 exclaim
= talloc_asprintf(ctx
,
853 client_get_cur_dir(),
856 status
= NT_STATUS_NO_MEMORY
;
860 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
862 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
863 (tar_re_search
&& mask_match_list(exclaim
, cliplist
, clipn
, True
))) {
864 DEBUG(3,("Skipping file %s\n", exclaim
));
865 TALLOC_FREE(exclaim
);
866 status
= NT_STATUS_OK
;
869 TALLOC_FREE(exclaim
);
872 if (finfo
->mode
& FILE_ATTRIBUTE_DIRECTORY
) {
873 char *saved_curdir
= NULL
;
875 char *mtar_mask
= NULL
;
877 saved_curdir
= talloc_strdup(ctx
, client_get_cur_dir());
879 status
= NT_STATUS_NO_MEMORY
;
883 DEBUG(5, ("strlen(cur_dir)=%d, \
884 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
885 (int)strlen(saved_curdir
),
886 (int)strlen(finfo
->name
), finfo
->name
, saved_curdir
));
888 new_cd
= talloc_asprintf(ctx
,
890 client_get_cur_dir(),
893 status
= NT_STATUS_NO_MEMORY
;
896 client_set_cur_dir(new_cd
);
898 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir()));
900 /* write a tar directory, don't bother with mode - just
902 writetarheader(tarhandle
, client_get_cur_dir(), 0,
903 finfo
->mtime_ts
.tv_sec
, "040755 \0", '5');
905 DEBUG(0,(" directory %s\n",
906 client_get_cur_dir()));
908 ntarf
++; /* Make sure we have a file on there */
909 mtar_mask
= talloc_asprintf(ctx
,
911 client_get_cur_dir());
913 status
= NT_STATUS_NO_MEMORY
;
916 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
917 do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
918 client_set_cur_dir(saved_curdir
);
919 TALLOC_FREE(saved_curdir
);
921 TALLOC_FREE(mtar_mask
);
923 char *rname
= talloc_asprintf(ctx
,
925 client_get_cur_dir(),
928 status
= NT_STATUS_NO_MEMORY
;
931 status
= do_atar(rname
,finfo
->name
,finfo
);
940 /****************************************************************************
941 Convert from UNIX to DOS file names
942 ***************************************************************************/
944 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
)
946 /* remove '.' from start of file name, convert from unix /'s to
947 * dos \'s in path. Kill any absolute path names. But only if first!
950 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
957 if (*fp
== '\\' || *fp
== '/') {
963 safe_strcpy(tptr
, fp
, l
);
964 string_replace(tptr
, '/', '\\');
967 /****************************************************************************
968 Move to the next block in the buffer, which may mean read in another set of
969 blocks. FIXME, we should allow more than one block to be skipped.
970 ****************************************************************************/
972 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
974 int bufread
, total
= 0;
976 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
980 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
982 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
985 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
986 * Fixes bug where read can return short if coming from
990 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
993 while (total
< bufsiz
) {
994 if (bufread
< 0) { /* An error, return false */
995 return (total
> 0 ? -2 : bufread
);
1003 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
1007 DEBUG(5, ("Total bytes read ... %i\n", total
));
1015 /* Skip a file, even if it includes a long file name? */
1016 static int skip_file(int skipsize
)
1018 int dsize
= skipsize
;
1020 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
1022 /* FIXME, we should skip more than one block at a time */
1025 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1026 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1035 /*************************************************************
1036 Get a file from the tar file and store it.
1037 When this is called, tarbuf already contains the first
1038 file block. This is a bit broken & needs fixing.
1039 **************************************************************/
1041 static int get_file(file_info2 finfo
)
1043 uint16_t fnum
= (uint16_t) -1;
1044 int dsize
= 0, bpos
= 0;
1045 uint64_t rsize
= 0, pos
= 0;
1048 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo
.name
, (double)finfo
.size
));
1050 if (!ensurepath(finfo
.name
)) {
1051 DEBUG(0, ("abandoning restore\n"));
1055 status
= cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
, &fnum
);
1056 if (!NT_STATUS_IS_OK(status
)) {
1057 DEBUG(0, ("abandoning restore\n"));
1061 /* read the blocks from the tar file and write to the remote file */
1063 rsize
= finfo
.size
; /* This is how much to write */
1067 /* We can only write up to the end of the buffer */
1068 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
1069 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
1070 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
1072 status
= cli_writeall(cli
, fnum
, 0,
1073 (uint8_t *)(buffer_p
+ bpos
), pos
,
1075 if (!NT_STATUS_IS_OK(status
)) {
1076 DEBUG(0, ("Error writing remote file: %s\n",
1077 nt_errstr(status
)));
1084 /* Now figure out how much to move in the buffer */
1086 /* FIXME, we should skip more than one block at a time */
1088 /* First, skip any initial part of the part written that is left over */
1089 /* from the end of the first TBLOCK */
1091 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1092 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1095 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1096 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1102 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1103 * If the file being extracted is an exact multiple of
1104 * TBLOCK bytes then we don't want to extract the next
1105 * block from the tarfile here, as it will be done in
1106 * the caller of get_file().
1109 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1110 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1112 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1113 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1122 /* Now close the file ... */
1124 if (!NT_STATUS_IS_OK(cli_close(cli
, fnum
))) {
1125 DEBUG(0, ("Error %s closing remote file\n",
1130 /* Now we update the creation date ... */
1131 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1133 if (!NT_STATUS_IS_OK(cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime_ts
.tv_sec
))) {
1134 if (tar_real_noisy
) {
1135 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1136 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1141 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo
.name
, (double)finfo
.size
));
1145 /* Create a directory. We just ensure that the path exists and return as there
1146 is no file associated with a directory
1148 static int get_dir(file_info2 finfo
)
1150 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1152 if (!ensurepath(finfo
.name
)) {
1153 DEBUG(0, ("Problems creating directory\n"));
1160 /* Get a file with a long file name ... first file has file name, next file
1161 has the data. We only want the long file name, as the loop in do_tarput
1162 will deal with the rest.
1164 static char *get_longfilename(file_info2 finfo
)
1166 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1168 int namesize
= finfo
.size
+ strlen(client_get_cur_dir()) + 2;
1169 char *longname
= (char *)SMB_MALLOC(namesize
);
1170 int offset
= 0, left
= finfo
.size
;
1173 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1174 DEBUG(5, ("Len = %.0f\n", (double)finfo
.size
));
1176 if (longname
== NULL
) {
1177 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize
));
1181 /* First, add cur_dir to the long file name */
1183 if (strlen(client_get_cur_dir()) > 0) {
1184 strncpy(longname
, client_get_cur_dir(), namesize
);
1185 offset
= strlen(client_get_cur_dir());
1188 /* Loop through the blocks picking up the name */
1191 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1192 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1193 SAFE_FREE(longname
);
1197 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1198 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1207 static void do_tarput(void)
1210 struct timespec tp_start
;
1211 char *longfilename
= NULL
, linkflag
;
1216 clock_gettime_mono(&tp_start
);
1217 DEBUG(5, ("RJS do_tarput called ...\n"));
1219 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1221 /* Now read through those files ... */
1223 /* Get us to the next block, or the first block first time around */
1224 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1225 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1226 SAFE_FREE(longfilename
);
1230 DEBUG(5, ("Reading the next header ...\n"));
1232 switch (readtarheader((union hblock
*) buffer_p
,
1233 &finfo
, client_get_cur_dir())) {
1234 case -2: /* Hmm, not good, but not fatal */
1235 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1236 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) && !skip_file(finfo
.size
)) {
1237 DEBUG(0, ("Short file, bailing out...\n"));
1238 SAFE_FREE(longfilename
);
1244 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1245 SAFE_FREE(longfilename
);
1248 case 0: /* chksum is zero - looks like an EOF */
1249 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1250 SAFE_FREE(longfilename
);
1251 return; /* Hmmm, bad here ... */
1258 /* Now, do we have a long file name? */
1259 if (longfilename
!= NULL
) {
1260 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1261 finfo
.name
= longfilename
;
1262 longfilename
= NULL
;
1265 /* Well, now we have a header, process the file ... */
1266 /* Should we skip the file? We have the long name as well here */
1267 skip
= clipn
&& ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
) ||
1268 (tar_re_search
&& mask_match_list(finfo
.name
, cliplist
, clipn
, True
)));
1270 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1272 skip_file(finfo
.size
);
1276 /* We only get this far if we should process the file */
1277 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1279 case '0': /* Should use symbolic names--FIXME */
1281 * Skip to the next block first, so we can get the file, FIXME, should
1282 * be in get_file ...
1283 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1284 * Fixes bug where file size in tarfile is zero.
1286 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1287 DEBUG(0, ("Short file, bailing out...\n"));
1290 if (!get_file(finfo
)) {
1291 DEBUG(0, ("Abandoning restore\n"));
1296 if (!get_dir(finfo
)) {
1297 DEBUG(0, ("Abandoning restore \n"));
1302 SAFE_FREE(longfilename
);
1303 longfilename
= get_longfilename(finfo
);
1304 if (!longfilename
) {
1305 DEBUG(0, ("abandoning restore\n"));
1308 DEBUG(5, ("Long file name: %s\n", longfilename
));
1312 skip_file(finfo
.size
); /* Don't handle these yet */
1319 * samba interactive commands
1322 /****************************************************************************
1324 ***************************************************************************/
1328 TALLOC_CTX
*ctx
= talloc_tos();
1332 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1333 DEBUG(0, ("blocksize <n>\n"));
1338 if (block
< 0 || block
> 65535) {
1339 DEBUG(0, ("blocksize out of range"));
1344 DEBUG(2,("blocksize is now %d\n", blocksize
));
1348 /****************************************************************************
1349 command to set incremental / reset mode
1350 ***************************************************************************/
1352 int cmd_tarmode(void)
1354 TALLOC_CTX
*ctx
= talloc_tos();
1357 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1358 if (strequal(buf
, "full"))
1360 else if (strequal(buf
, "inc"))
1362 else if (strequal(buf
, "reset"))
1364 else if (strequal(buf
, "noreset"))
1366 else if (strequal(buf
, "system"))
1368 else if (strequal(buf
, "nosystem"))
1370 else if (strequal(buf
, "hidden"))
1372 else if (strequal(buf
, "nohidden"))
1374 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1376 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1379 DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1383 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1384 tar_inc
? "incremental" : "full",
1385 tar_system
? "system" : "nosystem",
1386 tar_hidden
? "hidden" : "nohidden",
1387 tar_reset
? "reset" : "noreset",
1388 tar_noisy
? "verbose" : "quiet"));
1392 /****************************************************************************
1393 Feeble attrib command
1394 ***************************************************************************/
1396 int cmd_setmode(void)
1398 TALLOC_CTX
*ctx
= talloc_tos();
1405 attra
[0] = attra
[1] = 0;
1407 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1408 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1412 fname
= talloc_asprintf(ctx
,
1414 client_get_cur_dir(),
1420 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1432 attra
[direct
]|=FILE_ATTRIBUTE_READONLY
;
1435 attra
[direct
]|=FILE_ATTRIBUTE_HIDDEN
;
1438 attra
[direct
]|=FILE_ATTRIBUTE_SYSTEM
;
1441 attra
[direct
]|=FILE_ATTRIBUTE_ARCHIVE
;
1444 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1450 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0) {
1451 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1455 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1456 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1457 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1462 Convert list of tokens to array; dependent on above routine.
1463 Uses the global cmd_ptr from above - bit of a hack.
1466 static char **toktocliplist(int *ctok
, const char *sep
)
1468 char *s
=(char *)cmd_ptr
;
1475 while(*s
&& strchr_m(sep
,*s
))
1484 while(*s
&& (!strchr_m(sep
,*s
)))
1486 while(*s
&& strchr_m(sep
,*s
))
1493 if (!(ret
=iret
=SMB_MALLOC_ARRAY(char *,ictok
+1)))
1510 /****************************************************************************
1511 Principal command for creating / extracting
1512 ***************************************************************************/
1516 TALLOC_CTX
*ctx
= talloc_tos();
1522 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1523 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1527 argl
=toktocliplist(&argcl
, NULL
);
1528 if (!tar_parseargs(argcl
, argl
, buf
, 0)) {
1533 ret
= process_tar();
1538 /****************************************************************************
1539 Command line (option) version
1540 ***************************************************************************/
1542 int process_tar(void)
1544 TALLOC_CTX
*ctx
= talloc_tos();
1560 if (clipn
&& tar_excl
) {
1562 char *tarmac
= NULL
;
1564 for (i
=0; i
<clipn
; i
++) {
1565 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1567 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1568 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1571 if (strrchr_m(cliplist
[i
], '\\')) {
1574 char *saved_dir
= talloc_strdup(ctx
,
1575 client_get_cur_dir());
1580 if (*cliplist
[i
]=='\\') {
1581 tarmac
= talloc_strdup(ctx
,
1584 tarmac
= talloc_asprintf(ctx
,
1586 client_get_cur_dir(),
1593 * Strip off the last \\xxx
1594 * xxx element of tarmac to set
1595 * it as current directory.
1597 p
= strrchr_m(tarmac
, '\\');
1604 client_set_cur_dir(tarmac
);
1607 * Restore the character we
1614 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1615 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1617 client_set_cur_dir(saved_dir
);
1619 TALLOC_FREE(saved_dir
);
1620 TALLOC_FREE(tarmac
);
1622 tarmac
= talloc_asprintf(ctx
,
1624 client_get_cur_dir(),
1629 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1630 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1631 TALLOC_FREE(tarmac
);
1635 char *mask
= talloc_asprintf(ctx
,
1637 client_get_cur_dir());
1641 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1642 do_list(mask
,attribute
,do_tar
,False
, True
);
1647 dotareof(tarhandle
);
1652 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1653 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1657 if (must_free_cliplist
) {
1659 for (i
= 0; i
< clipn
; ++i
) {
1660 SAFE_FREE(cliplist
[i
]);
1662 SAFE_FREE(cliplist
);
1665 must_free_cliplist
= False
;
1670 /****************************************************************************
1671 Find a token (filename) in a clip list
1672 ***************************************************************************/
1674 static int clipfind(char **aret
, int ret
, char *tok
)
1679 /* ignore leading slashes or dots in token */
1680 while(strchr_m("/\\.", *tok
))
1686 /* ignore leading slashes or dots in list */
1687 while(strchr_m("/\\.", *pkey
))
1690 if (!strslashcmp(pkey
, tok
))
1696 /****************************************************************************
1697 Read list of files to include from the file and initialize cliplist
1699 ***************************************************************************/
1701 static int read_inclusion_file(char *filename
)
1703 XFILE
*inclusion
= NULL
;
1704 char buf
[PATH_MAX
+ 1];
1705 char *inclusion_buffer
= NULL
;
1706 int inclusion_buffer_size
= 0;
1707 int inclusion_buffer_sofar
= 0;
1714 buf
[PATH_MAX
] = '\0'; /* guarantee null-termination */
1715 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1716 /* XXX It would be better to include a reason for failure, but without
1717 * autoconf, it's hard to use strerror, sys_errlist, etc.
1719 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1723 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1724 if (inclusion_buffer
== NULL
) {
1725 inclusion_buffer_size
= 1024;
1726 if ((inclusion_buffer
= (char *)SMB_MALLOC(inclusion_buffer_size
)) == NULL
) {
1727 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1733 if (buf
[strlen(buf
)-1] == '\n') {
1734 buf
[strlen(buf
)-1] = '\0';
1737 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1738 inclusion_buffer_size
*= 2;
1739 inclusion_buffer
= (char *)SMB_REALLOC(inclusion_buffer
,inclusion_buffer_size
);
1740 if (!inclusion_buffer
) {
1741 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1742 inclusion_buffer_size
));
1748 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1749 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1752 x_fclose(inclusion
);
1755 /* Allocate an array of clipn + 1 char*'s for cliplist */
1756 cliplist
= SMB_MALLOC_ARRAY(char *, clipn
+ 1);
1757 if (cliplist
== NULL
) {
1758 DEBUG(0,("failure allocating memory for cliplist\n"));
1761 cliplist
[clipn
] = NULL
;
1762 p
= inclusion_buffer
;
1763 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1764 /* set current item to NULL so array will be null-terminated even if
1765 * malloc fails below. */
1767 if ((tmpstr
= (char *)SMB_MALLOC(strlen(p
)+1)) == NULL
) {
1768 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1771 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1772 cliplist
[i
] = tmpstr
;
1773 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1774 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1780 must_free_cliplist
= True
;
1784 SAFE_FREE(inclusion_buffer
);
1788 /* We know cliplist is always null-terminated */
1789 for (pp
= cliplist
; *pp
; ++pp
) {
1792 SAFE_FREE(cliplist
);
1794 must_free_cliplist
= False
;
1799 /* cliplist and its elements are freed at the end of process_tar. */
1803 /****************************************************************************
1804 Parse tar arguments. Sets tar_type, tar_excl, etc.
1805 ***************************************************************************/
1807 int tar_parseargs(int argc
, char *argv
[], const char *Optarg
, int Optind
)
1809 int newOptind
= Optind
;
1810 char tar_clipfl
='\0';
1812 /* Reset back to defaults - could be from interactive version
1813 * reset mode and archive mode left as they are though
1825 if (tar_type
=='c') {
1826 printf("Tar must be followed by only one of c or x.\n");
1832 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1833 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1845 DEBUG(0,("Option N must be followed by valid file name\n"));
1848 SMB_STRUCT_STAT stbuf
;
1850 if (sys_stat(argv
[Optind
], &stbuf
,
1852 newer_than
= convert_timespec_to_time_t(
1854 DEBUG(1,("Getting files newer than %s",
1855 time_to_asc(newer_than
)));
1859 DEBUG(0,("Error setting newer-than time\n"));
1872 DEBUG(0,("Only one of I,X,F must be specified\n"));
1879 DEBUG(0,("Only one of I,X,F must be specified\n"));
1886 DEBUG(0,("Only one of I,X,F must be specified\n"));
1892 DEBUG(0, ("tar_re_search set\n"));
1893 tar_re_search
= True
;
1896 if (tar_type
== 'c') {
1897 DEBUG(0, ("dry_run set\n"));
1900 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1905 DEBUG(0,("Unknown tar option\n"));
1911 printf("Option T must be followed by one of c or x.\n");
1915 /* tar_excl is true if cliplist lists files to be included.
1916 * Both 'I' and 'F' mean include. */
1917 tar_excl
=tar_clipfl
!='X';
1919 if (tar_clipfl
=='F') {
1920 if (argc
-Optind
-1 != 1) {
1921 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1925 /* Optind points at the tar output file, Optind+1 at the inclusion file. */
1926 if (! read_inclusion_file(argv
[Optind
+1])) {
1929 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1934 cliplist
=argv
+Optind
+1;
1935 clipn
=argc
-Optind
-1;
1938 if ((tmplist
=SMB_MALLOC_ARRAY(char *,clipn
)) == NULL
) {
1939 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn
));
1943 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1945 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1947 if ((tmpstr
= (char *)SMB_MALLOC(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1948 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount
));
1953 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1954 tmplist
[clipcount
] = tmpstr
;
1955 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1957 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1961 must_free_cliplist
= True
;
1966 if (Optind
+1<argc
&& tar_re_search
&& tar_clipfl
!= 'F') {
1967 /* Doing regular expression seaches not from an inclusion file. */
1968 clipn
=argc
-Optind
-1;
1969 cliplist
=argv
+Optind
+1;
1973 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1974 /* Sets tar handle to either 0 or 1, as appropriate */
1975 tarhandle
=(tar_type
=='c');
1977 * Make sure that dbf points to stderr if we are using stdout for
1980 if (tarhandle
== 1) {
1981 setup_logging("smbclient", DEBUG_STDERR
);
1983 if (!argv
[Optind
]) {
1984 DEBUG(0,("Must specify tar filename\n"));
1987 if (!strcmp(argv
[Optind
], "-")) {
1992 if (tar_type
=='c' && dry_run
) {
1994 } else if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1995 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0)) {
1996 DEBUG(0,("Error opening local file %s - %s\n", argv
[Optind
], strerror(errno
)));