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, jp
=(char*)&size
; i
; i
--)
212 hb
.dbuf
.size
[i
+3] = *(jp
++);
214 oct_it((uint64_t) mtime
, 13, hb
.dbuf
.mtime
);
215 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
216 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
217 hb
.dbuf
.linkflag
=ftype
;
219 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;)
222 oct_it((uint64_t) chk
, 8, hb
.dbuf
.chksum
);
223 hb
.dbuf
.chksum
[6] = '\0';
225 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
228 /****************************************************************************
229 Read a tar header into a hblock structure, and validate
230 ***************************************************************************/
232 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, const char *prefix
)
239 * read in a "standard" tar format header - we're not that interested
240 * in that many fields, though
243 /* check the checksum */
244 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;)
250 /* compensate for blanks in chksum header */
251 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
254 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
256 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
258 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
259 chk
, fchk
, hb
->dbuf
.chksum
));
262 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
263 dump_data(5, (uint8
*)hb
- TBLOCK
, TBLOCK
*3);
267 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
268 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
272 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
274 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
275 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
276 strlen(hb
->dbuf
.name
) + 1, True
);
278 /* can't handle some links at present */
279 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
280 if (hb
->dbuf
.linkflag
== 0) {
281 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
284 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
285 /* Do nothing here at the moment. do_tarput will handle this
286 as long as the longlink gets back to it, as it has to advance
287 the buffer pointer, etc */
289 DEBUG(0, ("this tar file appears to contain some kind \
290 of link other than a GNUtar Longlink - ignoring\n"));
296 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
) ||
297 (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\')) {
298 finfo
->mode
=FILE_ATTRIBUTE_DIRECTORY
;
300 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
301 * just make it a regular file */
305 * Bug fix by richard@sj.co.uk
307 * REC: restore times correctly (as does tar)
308 * We only get the modification time of the file; set the creation time
309 * from the mod. time, and the access time to current time
311 finfo
->mtime_ts
= finfo
->ctime_ts
=
312 convert_time_t_to_timespec((time_t)strtol(hb
->dbuf
.mtime
, NULL
, 8));
313 finfo
->atime_ts
= convert_time_t_to_timespec(time(NULL
));
314 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
319 /****************************************************************************
320 Write out the tar buffer to tape or wherever
321 ****************************************************************************/
323 static int dotarbuf(int f
, char *b
, int n
)
330 /* This routine and the next one should be the only ones that do write()s */
331 if (tp
+ n
>= tbufsiz
) {
335 memcpy(tarbuf
+ tp
, b
, diff
);
336 fail
=fail
&& (1+sys_write(f
, tarbuf
, tbufsiz
));
341 while (n
>= tbufsiz
) {
342 fail
=fail
&& (1 + sys_write(f
, b
, tbufsiz
));
349 memcpy(tarbuf
+tp
, b
, n
);
353 return(fail
? writ
: 0);
356 /****************************************************************************
357 Write zeros to buffer / tape
358 ****************************************************************************/
360 static void dozerobuf(int f
, int n
)
362 /* short routine just to write out n zeros to buffer -
363 * used to round files to nearest block
364 * and to do tar EOFs */
369 if (n
+tp
>= tbufsiz
) {
370 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
371 if (sys_write(f
, tarbuf
, tbufsiz
) != tbufsiz
) {
372 DEBUG(0, ("dozerobuf: sys_write fail\n"));
375 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
377 memset(tarbuf
+tp
, 0, n
);
382 /****************************************************************************
384 ****************************************************************************/
386 static void initarbuf(void)
388 /* initialize tar buffer */
389 tbufsiz
=blocksize
*TBLOCK
;
390 tarbuf
=(char *)SMB_MALLOC(tbufsiz
); /* FIXME: We might not get the buffer */
392 /* reset tar buffer pointer and tar file counter and total dumped */
393 tp
=0; ntarf
=0; ttarf
=0;
396 /****************************************************************************
397 Write two zero blocks at end of file
398 ****************************************************************************/
400 static void dotareof(int f
)
402 SMB_STRUCT_STAT stbuf
;
403 /* Two zero blocks at end of file, write out full buffer */
408 (void) dozerobuf(f
, TBLOCK
);
409 (void) dozerobuf(f
, TBLOCK
);
411 if (sys_fstat(f
, &stbuf
, false) == -1) {
412 DEBUG(0, ("Couldn't stat file handle\n"));
416 /* Could be a pipe, in which case S_ISREG should fail,
417 * and we should write out at full size */
419 size_t towrite
= S_ISREG(stbuf
.st_ex_mode
) ? tp
: tbufsiz
;
420 if (sys_write(f
, tarbuf
, towrite
) != towrite
) {
421 DEBUG(0,("dotareof: sys_write fail\n"));
426 /****************************************************************************
427 (Un)mangle DOS pathname, make nonabsolute
428 ****************************************************************************/
430 static void fixtarname(char *tptr
, const char *fp
, size_t l
)
432 /* add a '.' to start of file name, convert from ugly dos \'s in path
433 * to lovely unix /'s :-} */
437 StrnCpy(tptr
, fp
, l
-1);
438 string_replace(tptr
, '\\', '/');
441 /****************************************************************************
442 Convert from decimal to octal string
443 ****************************************************************************/
445 static void oct_it (uint64_t value
, int ndgs
, char *p
)
447 /* Converts long to octal string, pads with leading zeros */
449 /* skip final null, but do final space */
453 /* Loop does at least one digit */
455 p
[--ndgs
] = '0' + (char) (value
& 7);
457 } while (ndgs
> 0 && value
!= 0);
459 /* Do leading zeros */
464 /****************************************************************************
465 Convert from octal string to long
466 ***************************************************************************/
468 static long unoct(char *p
, int ndgs
)
471 /* Converts octal string to long, ignoring any non-digit */
474 if (isdigit((int)*p
))
475 value
= (value
<< 3) | (long) (*p
- '0');
483 /****************************************************************************
484 Compare two strings in a slash insensitive way, allowing s1 to match s2
485 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
486 a file in any subdirectory of s1, declare a match.
487 ***************************************************************************/
489 static int strslashcmp(char *s1
, char *s2
)
493 while(*s1
&& *s2
&& (*s1
== *s2
|| tolower_ascii(*s1
) == tolower_ascii(*s2
) ||
494 (*s1
== '\\' && *s2
=='/') || (*s1
== '/' && *s2
=='\\'))) {
498 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
501 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\'))
504 /* ignore trailing slash on s1 */
505 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1))
508 /* check for s1 is an "initial" string of s2 */
509 if ((*s2
== '/' || *s2
== '\\') && !*s1
)
515 /****************************************************************************
516 Ensure a remote path exists (make if necessary)
517 ***************************************************************************/
519 static bool ensurepath(const char *fname
)
521 /* *must* be called with buffer ready malloc'ed */
522 /* ensures path exists */
524 char *partpath
, *ffname
;
529 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
531 partpath
= string_create_s(strlen(fname
));
532 ffname
= string_create_s(strlen(fname
));
534 if ((partpath
== NULL
) || (ffname
== NULL
)){
535 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
543 /* fname copied to ffname so can strtok_r */
545 safe_strcpy(ffname
, fname
, strlen(fname
));
547 /* do a `basename' on ffname, so don't try and make file name directory */
548 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
) {
556 p
=strtok_r(ffname
, "\\", &saveptr
);
559 safe_strcat(partpath
, p
, strlen(fname
) + 1);
561 if (!NT_STATUS_IS_OK(cli_chkpath(cli
, partpath
))) {
562 if (!NT_STATUS_IS_OK(cli_mkdir(cli
, partpath
))) {
565 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli
)));
568 DEBUG(3, ("mkdirhiering %s\n", partpath
));
572 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
573 p
= strtok_r(NULL
, "/\\", &saveptr
);
581 static int padit(char *buf
, uint64_t bufsize
, uint64_t padsize
)
586 DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize
));
587 memset(buf
, 0, (size_t)bufsize
);
588 while( !berr
&& padsize
> 0 ) {
589 bytestowrite
= (int)MIN(bufsize
, padsize
);
590 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
591 padsize
-= bytestowrite
;
597 static void do_setrattr(char *name
, uint16 attr
, int set
)
601 if (!NT_STATUS_IS_OK(cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
))) {
605 if (set
== ATTRSET
) {
608 attr
= oldattr
& ~attr
;
611 if (!NT_STATUS_IS_OK(cli_setatr(cli
, name
, attr
, 0))) {
612 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
616 /****************************************************************************
617 append one remote file to the tar file
618 ***************************************************************************/
620 static NTSTATUS
do_atar(const char *rname_in
, char *lname
,
621 struct file_info
*finfo1
)
623 uint16_t fnum
= (uint16_t)-1;
627 bool shallitime
=True
;
629 int read_size
= 65520;
632 TALLOC_CTX
*ctx
= talloc_stackframe();
633 NTSTATUS status
= NT_STATUS_OK
;
634 struct timespec tp_start
;
636 clock_gettime_mono(&tp_start
);
638 data
= SMB_MALLOC_ARRAY(char, read_size
);
640 DEBUG(0,("do_atar: out of memory.\n"));
641 status
= NT_STATUS_NO_MEMORY
;
645 ftype
= '0'; /* An ordinary file ... */
649 finfo
.size
= finfo1
-> size
;
650 finfo
.mode
= finfo1
-> mode
;
651 finfo
.uid
= finfo1
-> uid
;
652 finfo
.gid
= finfo1
-> gid
;
653 finfo
.mtime_ts
= finfo1
-> mtime_ts
;
654 finfo
.atime_ts
= finfo1
-> atime_ts
;
655 finfo
.ctime_ts
= finfo1
-> ctime_ts
;
658 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1
->name
,
659 (double)finfo
.size
));
661 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
666 rname
= clean_name(ctx
, rname_in
);
668 status
= NT_STATUS_NO_MEMORY
;
672 status
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
, &fnum
);
673 if (!NT_STATUS_IS_OK(status
)) {
674 DEBUG(0,("%s opening remote file %s (%s)\n",
675 cli_errstr(cli
),rname
, client_get_cur_dir()));
679 finfo
.name
= string_create_s(strlen(rname
));
680 if (finfo
.name
== NULL
) {
681 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
682 status
= NT_STATUS_NO_MEMORY
;
686 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
688 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
690 if (tar_inc
&& !(finfo
.mode
& FILE_ATTRIBUTE_ARCHIVE
)) {
691 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
693 } else if (!tar_system
&& (finfo
.mode
& FILE_ATTRIBUTE_SYSTEM
)) {
694 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
696 } else if (!tar_hidden
&& (finfo
.mode
& FILE_ATTRIBUTE_HIDDEN
)) {
697 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
700 bool wrote_tar_header
= False
;
702 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
703 finfo
.name
, (double)finfo
.size
, lname
));
707 DEBUG(3,("nread=%.0f\n",(double)nread
));
709 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
712 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
713 status
= cli_nt_error(cli
);
719 /* Only if the first read succeeds, write out the tar header. */
720 if (!wrote_tar_header
) {
721 /* write a tar header, don't bother with mode - just set to 100644 */
722 writetarheader(tarhandle
, rname
, finfo
.size
,
723 finfo
.mtime_ts
.tv_sec
, "100644 \0", ftype
);
724 wrote_tar_header
= True
;
727 /* if file size has increased since we made file size query, truncate
728 read so tar header for this file will be correct.
731 if (nread
> finfo
.size
) {
732 datalen
-= nread
- finfo
.size
;
733 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
734 finfo
.name
, (double)finfo
.size
));
737 /* add received bits of file to buffer - dotarbuf will
738 * write out in 512 byte intervals */
740 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
741 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
742 status
= map_nt_error_from_unix(errno
);
746 if ( (datalen
== 0) && (finfo
.size
!= 0) ) {
747 status
= NT_STATUS_UNSUCCESSFUL
;
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 status
= map_nt_error_from_unix(errno
);
762 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
766 /* round tar file to nearest block */
767 if (finfo
.size
% TBLOCK
)
768 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
770 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
773 DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo
.name
));
775 status
= NT_STATUS_UNSUCCESSFUL
;
779 cli_close(cli
, fnum
);
783 struct timespec tp_end
;
786 /* if shallitime is true then we didn't skip */
787 if (tar_reset
&& !dry_run
)
788 (void) do_setrattr(finfo
.name
, FILE_ATTRIBUTE_ARCHIVE
, ATTRRESET
);
790 clock_gettime_mono(&tp_end
);
791 this_time
= (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 + (tp_end
.tv_nsec
- tp_start
.tv_nsec
)/1000000;
792 get_total_time_ms
+= this_time
;
793 get_total_size
+= finfo
.size
;
796 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
797 (double)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
801 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
802 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
803 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
804 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
809 if (fnum
!= (uint16_t)-1) {
810 cli_close(cli
, fnum
);
818 /****************************************************************************
819 Append single file to tar file (or not)
820 ***************************************************************************/
822 static NTSTATUS
do_tar(struct cli_state
*cli_state
, struct file_info
*finfo
,
825 TALLOC_CTX
*ctx
= talloc_stackframe();
826 NTSTATUS status
= NT_STATUS_OK
;
828 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
831 /* Is it on the exclude list ? */
832 if (!tar_excl
&& clipn
) {
835 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir())));
837 exclaim
= talloc_asprintf(ctx
,
839 client_get_cur_dir(),
842 return NT_STATUS_NO_MEMORY
;
845 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
847 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
848 (tar_re_search
&& mask_match_list(exclaim
, cliplist
, clipn
, True
))) {
849 DEBUG(3,("Skipping file %s\n", exclaim
));
850 TALLOC_FREE(exclaim
);
853 TALLOC_FREE(exclaim
);
856 if (finfo
->mode
& FILE_ATTRIBUTE_DIRECTORY
) {
857 char *saved_curdir
= NULL
;
859 char *mtar_mask
= NULL
;
861 saved_curdir
= talloc_strdup(ctx
, client_get_cur_dir());
863 return NT_STATUS_NO_MEMORY
;
866 DEBUG(5, ("strlen(cur_dir)=%d, \
867 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
868 (int)strlen(saved_curdir
),
869 (int)strlen(finfo
->name
), finfo
->name
, saved_curdir
));
871 new_cd
= talloc_asprintf(ctx
,
873 client_get_cur_dir(),
876 return NT_STATUS_NO_MEMORY
;
878 client_set_cur_dir(new_cd
);
880 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir()));
882 /* write a tar directory, don't bother with mode - just
884 writetarheader(tarhandle
, client_get_cur_dir(), 0,
885 finfo
->mtime_ts
.tv_sec
, "040755 \0", '5');
887 DEBUG(0,(" directory %s\n",
888 client_get_cur_dir()));
890 ntarf
++; /* Make sure we have a file on there */
891 mtar_mask
= talloc_asprintf(ctx
,
893 client_get_cur_dir());
895 return NT_STATUS_NO_MEMORY
;
897 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
898 status
= do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
899 client_set_cur_dir(saved_curdir
);
900 TALLOC_FREE(saved_curdir
);
902 TALLOC_FREE(mtar_mask
);
904 char *rname
= talloc_asprintf(ctx
,
906 client_get_cur_dir(),
909 return NT_STATUS_NO_MEMORY
;
911 status
= do_atar(rname
,finfo
->name
,finfo
);
917 /****************************************************************************
918 Convert from UNIX to DOS file names
919 ***************************************************************************/
921 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
)
923 /* remove '.' from start of file name, convert from unix /'s to
924 * dos \'s in path. Kill any absolute path names. But only if first!
927 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
934 if (*fp
== '\\' || *fp
== '/') {
940 safe_strcpy(tptr
, fp
, l
);
941 string_replace(tptr
, '/', '\\');
944 /****************************************************************************
945 Move to the next block in the buffer, which may mean read in another set of
946 blocks. FIXME, we should allow more than one block to be skipped.
947 ****************************************************************************/
949 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
951 int bufread
, total
= 0;
953 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
957 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
959 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
962 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
963 * Fixes bug where read can return short if coming from
967 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
970 while (total
< bufsiz
) {
971 if (bufread
< 0) { /* An error, return false */
972 return (total
> 0 ? -2 : bufread
);
980 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
984 DEBUG(5, ("Total bytes read ... %i\n", total
));
992 /* Skip a file, even if it includes a long file name? */
993 static int skip_file(int skipsize
)
995 int dsize
= skipsize
;
997 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
999 /* FIXME, we should skip more than one block at a time */
1002 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1003 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1012 /*************************************************************
1013 Get a file from the tar file and store it.
1014 When this is called, tarbuf already contains the first
1015 file block. This is a bit broken & needs fixing.
1016 **************************************************************/
1018 static int get_file(file_info2 finfo
)
1020 uint16_t fnum
= (uint16_t) -1;
1021 int pos
= 0, dsize
= 0, bpos
= 0;
1025 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo
.name
, (double)finfo
.size
));
1027 if (!ensurepath(finfo
.name
)) {
1028 DEBUG(0, ("abandoning restore\n"));
1032 status
= cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
, &fnum
);
1033 if (!NT_STATUS_IS_OK(status
)) {
1034 DEBUG(0, ("abandoning restore\n"));
1038 /* read the blocks from the tar file and write to the remote file */
1040 rsize
= finfo
.size
; /* This is how much to write */
1044 /* We can only write up to the end of the buffer */
1045 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
1046 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
1047 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
1049 status
= cli_writeall(cli
, fnum
, 0,
1050 (uint8_t *)(buffer_p
+ bpos
), pos
,
1052 if (!NT_STATUS_IS_OK(status
)) {
1053 DEBUG(0, ("Error writing remote file: %s\n",
1054 nt_errstr(status
)));
1061 /* Now figure out how much to move in the buffer */
1063 /* FIXME, we should skip more than one block at a time */
1065 /* First, skip any initial part of the part written that is left over */
1066 /* from the end of the first TBLOCK */
1068 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1069 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1072 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1073 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1079 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1080 * If the file being extracted is an exact multiple of
1081 * TBLOCK bytes then we don't want to extract the next
1082 * block from the tarfile here, as it will be done in
1083 * the caller of get_file().
1086 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1087 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1089 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1090 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1099 /* Now close the file ... */
1101 if (!NT_STATUS_IS_OK(cli_close(cli
, fnum
))) {
1102 DEBUG(0, ("Error %s closing remote file\n",
1107 /* Now we update the creation date ... */
1108 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1110 if (!NT_STATUS_IS_OK(cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime_ts
.tv_sec
))) {
1111 if (tar_real_noisy
) {
1112 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1113 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1118 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo
.name
, (double)finfo
.size
));
1122 /* Create a directory. We just ensure that the path exists and return as there
1123 is no file associated with a directory
1125 static int get_dir(file_info2 finfo
)
1127 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1129 if (!ensurepath(finfo
.name
)) {
1130 DEBUG(0, ("Problems creating directory\n"));
1137 /* Get a file with a long file name ... first file has file name, next file
1138 has the data. We only want the long file name, as the loop in do_tarput
1139 will deal with the rest.
1141 static char *get_longfilename(file_info2 finfo
)
1143 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1145 int namesize
= finfo
.size
+ strlen(client_get_cur_dir()) + 2;
1146 char *longname
= (char *)SMB_MALLOC(namesize
);
1147 int offset
= 0, left
= finfo
.size
;
1150 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1151 DEBUG(5, ("Len = %.0f\n", (double)finfo
.size
));
1153 if (longname
== NULL
) {
1154 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize
));
1158 /* First, add cur_dir to the long file name */
1160 if (strlen(client_get_cur_dir()) > 0) {
1161 strncpy(longname
, client_get_cur_dir(), namesize
);
1162 offset
= strlen(client_get_cur_dir());
1165 /* Loop through the blocks picking up the name */
1168 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1169 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1170 SAFE_FREE(longname
);
1174 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1175 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1184 static void do_tarput(void)
1187 struct timespec tp_start
;
1188 char *longfilename
= NULL
, linkflag
;
1193 clock_gettime_mono(&tp_start
);
1194 DEBUG(5, ("RJS do_tarput called ...\n"));
1196 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1198 /* Now read through those files ... */
1200 /* Get us to the next block, or the first block first time around */
1201 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1202 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1203 SAFE_FREE(longfilename
);
1207 DEBUG(5, ("Reading the next header ...\n"));
1209 switch (readtarheader((union hblock
*) buffer_p
,
1210 &finfo
, client_get_cur_dir())) {
1211 case -2: /* Hmm, not good, but not fatal */
1212 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1213 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) && !skip_file(finfo
.size
)) {
1214 DEBUG(0, ("Short file, bailing out...\n"));
1215 SAFE_FREE(longfilename
);
1221 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1222 SAFE_FREE(longfilename
);
1225 case 0: /* chksum is zero - looks like an EOF */
1226 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1227 SAFE_FREE(longfilename
);
1228 return; /* Hmmm, bad here ... */
1235 /* Now, do we have a long file name? */
1236 if (longfilename
!= NULL
) {
1237 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1238 finfo
.name
= longfilename
;
1239 longfilename
= NULL
;
1242 /* Well, now we have a header, process the file ... */
1243 /* Should we skip the file? We have the long name as well here */
1244 skip
= clipn
&& ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
) ||
1245 (tar_re_search
&& mask_match_list(finfo
.name
, cliplist
, clipn
, True
)));
1247 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1249 skip_file(finfo
.size
);
1253 /* We only get this far if we should process the file */
1254 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1256 case '0': /* Should use symbolic names--FIXME */
1258 * Skip to the next block first, so we can get the file, FIXME, should
1259 * be in get_file ...
1260 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1261 * Fixes bug where file size in tarfile is zero.
1263 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1264 DEBUG(0, ("Short file, bailing out...\n"));
1267 if (!get_file(finfo
)) {
1268 DEBUG(0, ("Abandoning restore\n"));
1273 if (!get_dir(finfo
)) {
1274 DEBUG(0, ("Abandoning restore \n"));
1279 SAFE_FREE(longfilename
);
1280 longfilename
= get_longfilename(finfo
);
1281 if (!longfilename
) {
1282 DEBUG(0, ("abandoning restore\n"));
1285 DEBUG(5, ("Long file name: %s\n", longfilename
));
1289 skip_file(finfo
.size
); /* Don't handle these yet */
1296 * samba interactive commands
1299 /****************************************************************************
1301 ***************************************************************************/
1305 TALLOC_CTX
*ctx
= talloc_tos();
1309 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1310 DEBUG(0, ("blocksize <n>\n"));
1315 if (block
< 0 || block
> 65535) {
1316 DEBUG(0, ("blocksize out of range"));
1321 DEBUG(2,("blocksize is now %d\n", blocksize
));
1325 /****************************************************************************
1326 command to set incremental / reset mode
1327 ***************************************************************************/
1329 int cmd_tarmode(void)
1331 TALLOC_CTX
*ctx
= talloc_tos();
1334 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1335 if (strequal(buf
, "full"))
1337 else if (strequal(buf
, "inc"))
1339 else if (strequal(buf
, "reset"))
1341 else if (strequal(buf
, "noreset"))
1343 else if (strequal(buf
, "system"))
1345 else if (strequal(buf
, "nosystem"))
1347 else if (strequal(buf
, "hidden"))
1349 else if (strequal(buf
, "nohidden"))
1351 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1353 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1356 DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1360 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1361 tar_inc
? "incremental" : "full",
1362 tar_system
? "system" : "nosystem",
1363 tar_hidden
? "hidden" : "nohidden",
1364 tar_reset
? "reset" : "noreset",
1365 tar_noisy
? "verbose" : "quiet"));
1369 /****************************************************************************
1370 Feeble attrib command
1371 ***************************************************************************/
1373 int cmd_setmode(void)
1375 TALLOC_CTX
*ctx
= talloc_tos();
1382 attra
[0] = attra
[1] = 0;
1384 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1385 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1389 fname
= talloc_asprintf(ctx
,
1391 client_get_cur_dir(),
1397 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1409 attra
[direct
]|=FILE_ATTRIBUTE_READONLY
;
1412 attra
[direct
]|=FILE_ATTRIBUTE_HIDDEN
;
1415 attra
[direct
]|=FILE_ATTRIBUTE_SYSTEM
;
1418 attra
[direct
]|=FILE_ATTRIBUTE_ARCHIVE
;
1421 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1427 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0) {
1428 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1432 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1433 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1434 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1439 Convert list of tokens to array; dependent on above routine.
1440 Uses the global cmd_ptr from above - bit of a hack.
1443 static char **toktocliplist(int *ctok
, const char *sep
)
1445 char *s
=(char *)cmd_ptr
;
1452 while(*s
&& strchr_m(sep
,*s
))
1461 while(*s
&& (!strchr_m(sep
,*s
)))
1463 while(*s
&& strchr_m(sep
,*s
))
1470 if (!(ret
=iret
=SMB_MALLOC_ARRAY(char *,ictok
+1)))
1487 /****************************************************************************
1488 Principal command for creating / extracting
1489 ***************************************************************************/
1493 TALLOC_CTX
*ctx
= talloc_tos();
1499 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1500 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1504 argl
=toktocliplist(&argcl
, NULL
);
1505 if (!tar_parseargs(argcl
, argl
, buf
, 0)) {
1510 ret
= process_tar();
1515 /****************************************************************************
1516 Command line (option) version
1517 ***************************************************************************/
1519 int process_tar(void)
1521 TALLOC_CTX
*ctx
= talloc_tos();
1537 if (clipn
&& tar_excl
) {
1539 char *tarmac
= NULL
;
1541 for (i
=0; i
<clipn
; i
++) {
1542 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1544 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1545 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1548 if (strrchr_m(cliplist
[i
], '\\')) {
1551 char *saved_dir
= talloc_strdup(ctx
,
1552 client_get_cur_dir());
1557 if (*cliplist
[i
]=='\\') {
1558 tarmac
= talloc_strdup(ctx
,
1561 tarmac
= talloc_asprintf(ctx
,
1563 client_get_cur_dir(),
1570 * Strip off the last \\xxx
1571 * xxx element of tarmac to set
1572 * it as current directory.
1574 p
= strrchr_m(tarmac
, '\\');
1581 client_set_cur_dir(tarmac
);
1584 * Restore the character we
1591 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1592 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1594 client_set_cur_dir(saved_dir
);
1596 TALLOC_FREE(saved_dir
);
1597 TALLOC_FREE(tarmac
);
1599 tarmac
= talloc_asprintf(ctx
,
1601 client_get_cur_dir(),
1606 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1607 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1608 TALLOC_FREE(tarmac
);
1612 char *mask
= talloc_asprintf(ctx
,
1614 client_get_cur_dir());
1618 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1619 do_list(mask
,attribute
,do_tar
,False
, True
);
1624 dotareof(tarhandle
);
1629 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1630 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1634 if (must_free_cliplist
) {
1636 for (i
= 0; i
< clipn
; ++i
) {
1637 SAFE_FREE(cliplist
[i
]);
1639 SAFE_FREE(cliplist
);
1642 must_free_cliplist
= False
;
1647 /****************************************************************************
1648 Find a token (filename) in a clip list
1649 ***************************************************************************/
1651 static int clipfind(char **aret
, int ret
, char *tok
)
1656 /* ignore leading slashes or dots in token */
1657 while(strchr_m("/\\.", *tok
))
1663 /* ignore leading slashes or dots in list */
1664 while(strchr_m("/\\.", *pkey
))
1667 if (!strslashcmp(pkey
, tok
))
1673 /****************************************************************************
1674 Read list of files to include from the file and initialize cliplist
1676 ***************************************************************************/
1678 static int read_inclusion_file(char *filename
)
1680 XFILE
*inclusion
= NULL
;
1681 char buf
[PATH_MAX
+ 1];
1682 char *inclusion_buffer
= NULL
;
1683 int inclusion_buffer_size
= 0;
1684 int inclusion_buffer_sofar
= 0;
1691 buf
[PATH_MAX
] = '\0'; /* guarantee null-termination */
1692 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1693 /* XXX It would be better to include a reason for failure, but without
1694 * autoconf, it's hard to use strerror, sys_errlist, etc.
1696 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1700 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1701 if (inclusion_buffer
== NULL
) {
1702 inclusion_buffer_size
= 1024;
1703 if ((inclusion_buffer
= (char *)SMB_MALLOC(inclusion_buffer_size
)) == NULL
) {
1704 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1710 if (buf
[strlen(buf
)-1] == '\n') {
1711 buf
[strlen(buf
)-1] = '\0';
1714 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1715 inclusion_buffer_size
*= 2;
1716 inclusion_buffer
= (char *)SMB_REALLOC(inclusion_buffer
,inclusion_buffer_size
);
1717 if (!inclusion_buffer
) {
1718 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1719 inclusion_buffer_size
));
1725 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1726 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1729 x_fclose(inclusion
);
1732 /* Allocate an array of clipn + 1 char*'s for cliplist */
1733 cliplist
= SMB_MALLOC_ARRAY(char *, clipn
+ 1);
1734 if (cliplist
== NULL
) {
1735 DEBUG(0,("failure allocating memory for cliplist\n"));
1738 cliplist
[clipn
] = NULL
;
1739 p
= inclusion_buffer
;
1740 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1741 /* set current item to NULL so array will be null-terminated even if
1742 * malloc fails below. */
1744 if ((tmpstr
= (char *)SMB_MALLOC(strlen(p
)+1)) == NULL
) {
1745 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1748 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1749 cliplist
[i
] = tmpstr
;
1750 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1751 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1757 must_free_cliplist
= True
;
1761 SAFE_FREE(inclusion_buffer
);
1765 /* We know cliplist is always null-terminated */
1766 for (pp
= cliplist
; *pp
; ++pp
) {
1769 SAFE_FREE(cliplist
);
1771 must_free_cliplist
= False
;
1776 /* cliplist and its elements are freed at the end of process_tar. */
1780 /****************************************************************************
1781 Parse tar arguments. Sets tar_type, tar_excl, etc.
1782 ***************************************************************************/
1784 int tar_parseargs(int argc
, char *argv
[], const char *Optarg
, int Optind
)
1786 int newOptind
= Optind
;
1787 char tar_clipfl
='\0';
1789 /* Reset back to defaults - could be from interactive version
1790 * reset mode and archive mode left as they are though
1802 if (tar_type
=='c') {
1803 printf("Tar must be followed by only one of c or x.\n");
1809 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1810 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1822 DEBUG(0,("Option N must be followed by valid file name\n"));
1825 SMB_STRUCT_STAT stbuf
;
1827 if (sys_stat(argv
[Optind
], &stbuf
,
1829 newer_than
= convert_timespec_to_time_t(
1831 DEBUG(1,("Getting files newer than %s",
1832 time_to_asc(newer_than
)));
1836 DEBUG(0,("Error setting newer-than time\n"));
1849 DEBUG(0,("Only one of I,X,F must be specified\n"));
1856 DEBUG(0,("Only one of I,X,F must be specified\n"));
1863 DEBUG(0,("Only one of I,X,F must be specified\n"));
1869 DEBUG(0, ("tar_re_search set\n"));
1870 tar_re_search
= True
;
1873 if (tar_type
== 'c') {
1874 DEBUG(0, ("dry_run set\n"));
1877 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1882 DEBUG(0,("Unknown tar option\n"));
1888 printf("Option T must be followed by one of c or x.\n");
1892 /* tar_excl is true if cliplist lists files to be included.
1893 * Both 'I' and 'F' mean include. */
1894 tar_excl
=tar_clipfl
!='X';
1896 if (tar_clipfl
=='F') {
1897 if (argc
-Optind
-1 != 1) {
1898 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1902 /* Optind points at the tar output file, Optind+1 at the inclusion file. */
1903 if (! read_inclusion_file(argv
[Optind
+1])) {
1906 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1911 cliplist
=argv
+Optind
+1;
1912 clipn
=argc
-Optind
-1;
1915 if ((tmplist
=SMB_MALLOC_ARRAY(char *,clipn
)) == NULL
) {
1916 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn
));
1920 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1922 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1924 if ((tmpstr
= (char *)SMB_MALLOC(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1925 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount
));
1930 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1931 tmplist
[clipcount
] = tmpstr
;
1932 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1934 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1938 must_free_cliplist
= True
;
1943 if (Optind
+1<argc
&& tar_re_search
&& tar_clipfl
!= 'F') {
1944 /* Doing regular expression seaches not from an inclusion file. */
1945 clipn
=argc
-Optind
-1;
1946 cliplist
=argv
+Optind
+1;
1950 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1951 /* Sets tar handle to either 0 or 1, as appropriate */
1952 tarhandle
=(tar_type
=='c');
1954 * Make sure that dbf points to stderr if we are using stdout for
1957 if (tarhandle
== 1) {
1958 setup_logging("smbclient", DEBUG_STDERR
);
1960 if (!argv
[Optind
]) {
1961 DEBUG(0,("Must specify tar filename\n"));
1964 if (!strcmp(argv
[Optind
], "-")) {
1969 if (tar_type
=='c' && dry_run
) {
1971 } else if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1972 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0)) {
1973 DEBUG(0,("Error opening local file %s - %s\n", argv
[Optind
], strerror(errno
)));