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 NTSTATUS
do_atar(const char *rname_in
, char *lname
,
118 struct file_info
*finfo1
);
119 static NTSTATUS
do_tar(struct cli_state
*cli_state
, struct file_info
*finfo
,
121 static void oct_it(uint64_t value
, int ndgs
, char *p
);
122 static void fixtarname(char *tptr
, const char *fp
, size_t l
);
123 static int dotarbuf(int f
, char *b
, int n
);
124 static void dozerobuf(int f
, int n
);
125 static void dotareof(int f
);
126 static void initarbuf(void);
128 /* restore functions */
129 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, const char *prefix
);
130 static long unoct(char *p
, int ndgs
);
131 static void do_tarput(void);
132 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
);
135 * tar specific utitlities
138 /*******************************************************************
139 Create a string of size size+1 (for the null)
140 *******************************************************************/
142 static char *string_create_s(int size
)
146 tmp
= (char *)SMB_MALLOC(size
+1);
149 DEBUG(0, ("Out of memory in string_create_s\n"));
155 /****************************************************************************
156 Write a tar header to buffer
157 ****************************************************************************/
159 static void writetarheader(int f
, const char *aname
, uint64_t size
, time_t mtime
,
160 const char *amode
, unsigned char ftype
)
166 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype
, (double)size
, aname
));
168 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
171 /* We will be prepending a '.' in fixtarheader so use +2 to
172 * take care of the . and terminating zero. JRA.
175 /* write a GNU tar style long header */
177 b
= (char *)SMB_MALLOC(l
+TBLOCK
+100);
179 DEBUG(0,("out of memory\n"));
182 writetarheader(f
, "/./@LongLink", l
+2, 0, " 0 \0", 'L');
183 memset(b
, 0, l
+TBLOCK
+100);
184 fixtarname(b
, aname
, l
+2);
186 DEBUG(5, ("File name in tar file: %s, size=%d, \n", b
, (int)strlen(b
)));
187 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
191 fixtarname(hb
.dbuf
.name
, aname
, (l
+2 >= NAMSIZ
) ? NAMSIZ
: l
+ 2);
194 strlower_m(hb
.dbuf
.name
);
196 /* write out a "standard" tar format header */
198 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
199 safe_strcpy(hb
.dbuf
.mode
, amode
, sizeof(hb
.dbuf
.mode
)-1);
200 oct_it((uint64_t)0, 8, hb
.dbuf
.uid
);
201 oct_it((uint64_t)0, 8, hb
.dbuf
.gid
);
202 oct_it((uint64_t) size
, 13, hb
.dbuf
.size
);
203 if (size
> (uint64_t)077777777777LL) {
204 /* This is a non-POSIX compatible extention to store files
207 memset(hb
.dbuf
.size
, 0, 4);
209 for (i
= 8, jp
=(char*)&size
; i
; i
--)
210 hb
.dbuf
.size
[i
+3] = *(jp
++);
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 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
317 /****************************************************************************
318 Write out the tar buffer to tape or wherever
319 ****************************************************************************/
321 static int dotarbuf(int f
, char *b
, int n
)
328 /* This routine and the next one should be the only ones that do write()s */
329 if (tp
+ n
>= tbufsiz
) {
333 memcpy(tarbuf
+ tp
, b
, diff
);
334 fail
=fail
&& (1+sys_write(f
, tarbuf
, tbufsiz
));
339 while (n
>= tbufsiz
) {
340 fail
=fail
&& (1 + sys_write(f
, b
, tbufsiz
));
347 memcpy(tarbuf
+tp
, b
, n
);
351 return(fail
? writ
: 0);
354 /****************************************************************************
355 Write zeros to buffer / tape
356 ****************************************************************************/
358 static void dozerobuf(int f
, int n
)
360 /* short routine just to write out n zeros to buffer -
361 * used to round files to nearest block
362 * and to do tar EOFs */
367 if (n
+tp
>= tbufsiz
) {
368 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
369 if (sys_write(f
, tarbuf
, tbufsiz
) != tbufsiz
) {
370 DEBUG(0, ("dozerobuf: sys_write fail\n"));
373 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
375 memset(tarbuf
+tp
, 0, n
);
380 /****************************************************************************
382 ****************************************************************************/
384 static void initarbuf(void)
386 /* initialize tar buffer */
387 tbufsiz
=blocksize
*TBLOCK
;
388 tarbuf
=(char *)SMB_MALLOC(tbufsiz
); /* FIXME: We might not get the buffer */
390 /* reset tar buffer pointer and tar file counter and total dumped */
391 tp
=0; ntarf
=0; ttarf
=0;
394 /****************************************************************************
395 Write two zero blocks at end of file
396 ****************************************************************************/
398 static void dotareof(int f
)
400 SMB_STRUCT_STAT stbuf
;
401 /* Two zero blocks at end of file, write out full buffer */
406 (void) dozerobuf(f
, TBLOCK
);
407 (void) dozerobuf(f
, TBLOCK
);
409 if (sys_fstat(f
, &stbuf
, false) == -1) {
410 DEBUG(0, ("Couldn't stat file handle\n"));
414 /* Could be a pipe, in which case S_ISREG should fail,
415 * and we should write out at full size */
417 size_t towrite
= S_ISREG(stbuf
.st_ex_mode
) ? tp
: tbufsiz
;
418 if (sys_write(f
, tarbuf
, towrite
) != towrite
) {
419 DEBUG(0,("dotareof: sys_write fail\n"));
424 /****************************************************************************
425 (Un)mangle DOS pathname, make nonabsolute
426 ****************************************************************************/
428 static void fixtarname(char *tptr
, const char *fp
, size_t l
)
430 /* add a '.' to start of file name, convert from ugly dos \'s in path
431 * to lovely unix /'s :-} */
435 StrnCpy(tptr
, fp
, l
-1);
436 string_replace(tptr
, '\\', '/');
439 /****************************************************************************
440 Convert from decimal to octal string
441 ****************************************************************************/
443 static void oct_it (uint64_t value
, int ndgs
, char *p
)
445 /* Converts long to octal string, pads with leading zeros */
447 /* skip final null, but do final space */
451 /* Loop does at least one digit */
453 p
[--ndgs
] = '0' + (char) (value
& 7);
455 } while (ndgs
> 0 && value
!= 0);
457 /* Do leading zeros */
462 /****************************************************************************
463 Convert from octal string to long
464 ***************************************************************************/
466 static long unoct(char *p
, int ndgs
)
469 /* Converts octal string to long, ignoring any non-digit */
472 if (isdigit((int)*p
))
473 value
= (value
<< 3) | (long) (*p
- '0');
481 /****************************************************************************
482 Compare two strings in a slash insensitive way, allowing s1 to match s2
483 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
484 a file in any subdirectory of s1, declare a match.
485 ***************************************************************************/
487 static int strslashcmp(char *s1
, char *s2
)
491 while(*s1
&& *s2
&& (*s1
== *s2
|| tolower_ascii(*s1
) == tolower_ascii(*s2
) ||
492 (*s1
== '\\' && *s2
=='/') || (*s1
== '/' && *s2
=='\\'))) {
496 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
499 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\'))
502 /* ignore trailing slash on s1 */
503 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1))
506 /* check for s1 is an "initial" string of s2 */
507 if ((*s2
== '/' || *s2
== '\\') && !*s1
)
513 /****************************************************************************
514 Ensure a remote path exists (make if necessary)
515 ***************************************************************************/
517 static bool ensurepath(const char *fname
)
519 /* *must* be called with buffer ready malloc'ed */
520 /* ensures path exists */
522 char *partpath
, *ffname
;
527 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
529 partpath
= string_create_s(strlen(fname
));
530 ffname
= string_create_s(strlen(fname
));
532 if ((partpath
== NULL
) || (ffname
== NULL
)){
533 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
541 /* fname copied to ffname so can strtok_r */
543 safe_strcpy(ffname
, fname
, strlen(fname
));
545 /* do a `basename' on ffname, so don't try and make file name directory */
546 if ((basehack
=strrchr_m(ffname
, '\\')) == NULL
) {
554 p
=strtok_r(ffname
, "\\", &saveptr
);
557 safe_strcat(partpath
, p
, strlen(fname
) + 1);
559 if (!NT_STATUS_IS_OK(cli_chkpath(cli
, partpath
))) {
560 if (!NT_STATUS_IS_OK(cli_mkdir(cli
, partpath
))) {
563 DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli
)));
566 DEBUG(3, ("mkdirhiering %s\n", partpath
));
570 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
571 p
= strtok_r(NULL
, "/\\", &saveptr
);
579 static int padit(char *buf
, uint64_t bufsize
, uint64_t padsize
)
584 DEBUG(5, ("Padding with %0.f zeros\n", (double)padsize
));
585 memset(buf
, 0, (size_t)bufsize
);
586 while( !berr
&& padsize
> 0 ) {
587 bytestowrite
= (int)MIN(bufsize
, padsize
);
588 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
589 padsize
-= bytestowrite
;
595 static void do_setrattr(char *name
, uint16 attr
, int set
)
599 if (!NT_STATUS_IS_OK(cli_getatr(cli
, name
, &oldattr
, NULL
, NULL
))) {
603 if (set
== ATTRSET
) {
606 attr
= oldattr
& ~attr
;
609 if (!NT_STATUS_IS_OK(cli_setatr(cli
, name
, attr
, 0))) {
610 DEBUG(1,("setatr failed: %s\n", cli_errstr(cli
)));
614 /****************************************************************************
615 append one remote file to the tar file
616 ***************************************************************************/
618 static NTSTATUS
do_atar(const char *rname_in
, char *lname
,
619 struct file_info
*finfo1
)
621 uint16_t fnum
= (uint16_t)-1;
625 bool shallitime
=True
;
627 int read_size
= 65520;
630 TALLOC_CTX
*ctx
= talloc_stackframe();
631 NTSTATUS status
= NT_STATUS_OK
;
632 struct timespec tp_start
;
634 clock_gettime_mono(&tp_start
);
636 data
= SMB_MALLOC_ARRAY(char, read_size
);
638 DEBUG(0,("do_atar: out of memory.\n"));
639 status
= NT_STATUS_NO_MEMORY
;
643 ftype
= '0'; /* An ordinary file ... */
647 finfo
.size
= finfo1
-> size
;
648 finfo
.mode
= finfo1
-> mode
;
649 finfo
.uid
= finfo1
-> uid
;
650 finfo
.gid
= finfo1
-> gid
;
651 finfo
.mtime_ts
= finfo1
-> mtime_ts
;
652 finfo
.atime_ts
= finfo1
-> atime_ts
;
653 finfo
.ctime_ts
= finfo1
-> ctime_ts
;
656 DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo1
->name
,
657 (double)finfo
.size
));
659 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
664 rname
= clean_name(ctx
, rname_in
);
666 status
= NT_STATUS_NO_MEMORY
;
670 status
= cli_open(cli
, rname
, O_RDONLY
, DENY_NONE
, &fnum
);
671 if (!NT_STATUS_IS_OK(status
)) {
672 DEBUG(0,("%s opening remote file %s (%s)\n",
673 cli_errstr(cli
),rname
, client_get_cur_dir()));
677 finfo
.name
= string_create_s(strlen(rname
));
678 if (finfo
.name
== NULL
) {
679 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
680 status
= NT_STATUS_NO_MEMORY
;
684 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
686 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
688 if (tar_inc
&& !(finfo
.mode
& aARCH
)) {
689 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
691 } else if (!tar_system
&& (finfo
.mode
& aSYSTEM
)) {
692 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
694 } else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
)) {
695 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
698 bool wrote_tar_header
= False
;
700 DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s",
701 finfo
.name
, (double)finfo
.size
, lname
));
705 DEBUG(3,("nread=%.0f\n",(double)nread
));
707 datalen
= cli_read(cli
, fnum
, data
, nread
, read_size
);
710 DEBUG(0,("Error reading file %s : %s\n", rname
, cli_errstr(cli
)));
711 status
= cli_nt_error(cli
);
717 /* Only if the first read succeeds, write out the tar header. */
718 if (!wrote_tar_header
) {
719 /* write a tar header, don't bother with mode - just set to 100644 */
720 writetarheader(tarhandle
, rname
, finfo
.size
,
721 finfo
.mtime_ts
.tv_sec
, "100644 \0", ftype
);
722 wrote_tar_header
= True
;
725 /* if file size has increased since we made file size query, truncate
726 read so tar header for this file will be correct.
729 if (nread
> finfo
.size
) {
730 datalen
-= nread
- finfo
.size
;
731 DEBUG(0,("File size change - truncating %s to %.0f bytes\n",
732 finfo
.name
, (double)finfo
.size
));
735 /* add received bits of file to buffer - dotarbuf will
736 * write out in 512 byte intervals */
738 if (dotarbuf(tarhandle
,data
,datalen
) != datalen
) {
739 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
740 status
= map_nt_error_from_unix(errno
);
744 if ( (datalen
== 0) && (finfo
.size
!= 0) ) {
745 status
= NT_STATUS_UNSUCCESSFUL
;
746 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
751 } while ( nread
< finfo
.size
);
753 if (wrote_tar_header
) {
754 /* pad tar file with zero's if we couldn't get entire file */
755 if (nread
< finfo
.size
) {
756 DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
757 (double)finfo
.size
, (int)nread
));
758 if (padit(data
, (uint64_t)sizeof(data
), finfo
.size
- nread
)) {
759 status
= map_nt_error_from_unix(errno
);
760 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
));
773 status
= NT_STATUS_UNSUCCESSFUL
;
777 cli_close(cli
, fnum
);
781 struct timespec tp_end
;
784 /* if shallitime is true then we didn't skip */
785 if (tar_reset
&& !dry_run
)
786 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
788 clock_gettime_mono(&tp_end
);
789 this_time
= (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 + (tp_end
.tv_nsec
- tp_start
.tv_nsec
)/1000000;
790 get_total_time_ms
+= this_time
;
791 get_total_size
+= finfo
.size
;
794 DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n",
795 (double)finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
799 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
800 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
801 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
802 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
807 if (fnum
!= (uint16_t)-1) {
808 cli_close(cli
, fnum
);
816 /****************************************************************************
817 Append single file to tar file (or not)
818 ***************************************************************************/
820 static NTSTATUS
do_tar(struct cli_state
*cli_state
, struct file_info
*finfo
,
823 TALLOC_CTX
*ctx
= talloc_stackframe();
824 NTSTATUS status
= NT_STATUS_OK
;
826 if (strequal(finfo
->name
,"..") || strequal(finfo
->name
,"."))
829 /* Is it on the exclude list ? */
830 if (!tar_excl
&& clipn
) {
833 DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(client_get_cur_dir())));
835 exclaim
= talloc_asprintf(ctx
,
837 client_get_cur_dir(),
840 return NT_STATUS_NO_MEMORY
;
843 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
845 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
846 (tar_re_search
&& mask_match_list(exclaim
, cliplist
, clipn
, True
))) {
847 DEBUG(3,("Skipping file %s\n", exclaim
));
848 TALLOC_FREE(exclaim
);
851 TALLOC_FREE(exclaim
);
854 if (finfo
->mode
& aDIR
) {
855 char *saved_curdir
= NULL
;
857 char *mtar_mask
= NULL
;
859 saved_curdir
= talloc_strdup(ctx
, client_get_cur_dir());
861 return NT_STATUS_NO_MEMORY
;
864 DEBUG(5, ("strlen(cur_dir)=%d, \
865 strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
866 (int)strlen(saved_curdir
),
867 (int)strlen(finfo
->name
), finfo
->name
, saved_curdir
));
869 new_cd
= talloc_asprintf(ctx
,
871 client_get_cur_dir(),
874 return NT_STATUS_NO_MEMORY
;
876 client_set_cur_dir(new_cd
);
878 DEBUG(5, ("Writing a dir, Name = %s\n", client_get_cur_dir()));
880 /* write a tar directory, don't bother with mode - just
882 writetarheader(tarhandle
, client_get_cur_dir(), 0,
883 finfo
->mtime_ts
.tv_sec
, "040755 \0", '5');
885 DEBUG(0,(" directory %s\n",
886 client_get_cur_dir()));
888 ntarf
++; /* Make sure we have a file on there */
889 mtar_mask
= talloc_asprintf(ctx
,
891 client_get_cur_dir());
893 return NT_STATUS_NO_MEMORY
;
895 DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask
));
896 status
= do_list(mtar_mask
, attribute
, do_tar
, False
, True
);
897 client_set_cur_dir(saved_curdir
);
898 TALLOC_FREE(saved_curdir
);
900 TALLOC_FREE(mtar_mask
);
902 char *rname
= talloc_asprintf(ctx
,
904 client_get_cur_dir(),
907 return NT_STATUS_NO_MEMORY
;
909 status
= do_atar(rname
,finfo
->name
,finfo
);
915 /****************************************************************************
916 Convert from UNIX to DOS file names
917 ***************************************************************************/
919 static void unfixtarname(char *tptr
, char *fp
, int l
, bool first
)
921 /* remove '.' from start of file name, convert from unix /'s to
922 * dos \'s in path. Kill any absolute path names. But only if first!
925 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
932 if (*fp
== '\\' || *fp
== '/') {
938 safe_strcpy(tptr
, fp
, l
);
939 string_replace(tptr
, '/', '\\');
942 /****************************************************************************
943 Move to the next block in the buffer, which may mean read in another set of
944 blocks. FIXME, we should allow more than one block to be skipped.
945 ****************************************************************************/
947 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
949 int bufread
, total
= 0;
951 DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp
));
955 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
957 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
960 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
961 * Fixes bug where read can return short if coming from
965 bufread
= read(tarhandle
, ltarbuf
, bufsiz
);
968 while (total
< bufsiz
) {
969 if (bufread
< 0) { /* An error, return false */
970 return (total
> 0 ? -2 : bufread
);
978 bufread
= read(tarhandle
, <arbuf
[total
], bufsiz
- total
);
982 DEBUG(5, ("Total bytes read ... %i\n", total
));
990 /* Skip a file, even if it includes a long file name? */
991 static int skip_file(int skipsize
)
993 int dsize
= skipsize
;
995 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
997 /* FIXME, we should skip more than one block at a time */
1000 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1001 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1010 /*************************************************************
1011 Get a file from the tar file and store it.
1012 When this is called, tarbuf already contains the first
1013 file block. This is a bit broken & needs fixing.
1014 **************************************************************/
1016 static int get_file(file_info2 finfo
)
1018 uint16_t fnum
= (uint16_t) -1;
1019 int pos
= 0, dsize
= 0, bpos
= 0;
1023 DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo
.name
, (double)finfo
.size
));
1025 if (!ensurepath(finfo
.name
)) {
1026 DEBUG(0, ("abandoning restore\n"));
1030 status
= cli_open(cli
, finfo
.name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
, &fnum
);
1031 if (!NT_STATUS_IS_OK(status
)) {
1032 DEBUG(0, ("abandoning restore\n"));
1036 /* read the blocks from the tar file and write to the remote file */
1038 rsize
= finfo
.size
; /* This is how much to write */
1042 /* We can only write up to the end of the buffer */
1043 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, 65520); /* Calculate the size to write */
1044 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
1045 DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize
, bpos
));
1047 if (cli_write(cli
, fnum
, 0, buffer_p
+ bpos
, pos
, dsize
) != dsize
) {
1048 DEBUG(0, ("Error writing remote file\n"));
1055 /* Now figure out how much to move in the buffer */
1057 /* FIXME, we should skip more than one block at a time */
1059 /* First, skip any initial part of the part written that is left over */
1060 /* from the end of the first TBLOCK */
1062 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1063 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1066 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1067 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1073 * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
1074 * If the file being extracted is an exact multiple of
1075 * TBLOCK bytes then we don't want to extract the next
1076 * block from the tarfile here, as it will be done in
1077 * the caller of get_file().
1080 while (((rsize
!= 0) && (dsize
>= TBLOCK
)) ||
1081 ((rsize
== 0) && (dsize
> TBLOCK
))) {
1083 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1084 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1093 /* Now close the file ... */
1095 if (!NT_STATUS_IS_OK(cli_close(cli
, fnum
))) {
1096 DEBUG(0, ("Error %s closing remote file\n",
1101 /* Now we update the creation date ... */
1102 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1104 if (!NT_STATUS_IS_OK(cli_setatr(cli
, finfo
.name
, finfo
.mode
, finfo
.mtime_ts
.tv_sec
))) {
1105 if (tar_real_noisy
) {
1106 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1107 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1112 DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo
.name
, (double)finfo
.size
));
1116 /* Create a directory. We just ensure that the path exists and return as there
1117 is no file associated with a directory
1119 static int get_dir(file_info2 finfo
)
1121 DEBUG(0, ("restore directory %s\n", finfo
.name
));
1123 if (!ensurepath(finfo
.name
)) {
1124 DEBUG(0, ("Problems creating directory\n"));
1131 /* Get a file with a long file name ... first file has file name, next file
1132 has the data. We only want the long file name, as the loop in do_tarput
1133 will deal with the rest.
1135 static char *get_longfilename(file_info2 finfo
)
1137 /* finfo.size here is the length of the filename as written by the "/./@LongLink" name
1139 int namesize
= finfo
.size
+ strlen(client_get_cur_dir()) + 2;
1140 char *longname
= (char *)SMB_MALLOC(namesize
);
1141 int offset
= 0, left
= finfo
.size
;
1144 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1145 DEBUG(5, ("Len = %.0f\n", (double)finfo
.size
));
1147 if (longname
== NULL
) {
1148 DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize
));
1152 /* First, add cur_dir to the long file name */
1154 if (strlen(client_get_cur_dir()) > 0) {
1155 strncpy(longname
, client_get_cur_dir(), namesize
);
1156 offset
= strlen(client_get_cur_dir());
1159 /* Loop through the blocks picking up the name */
1162 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1163 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1164 SAFE_FREE(longname
);
1168 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1169 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1178 static void do_tarput(void)
1181 struct timespec tp_start
;
1182 char *longfilename
= NULL
, linkflag
;
1187 clock_gettime_mono(&tp_start
);
1188 DEBUG(5, ("RJS do_tarput called ...\n"));
1190 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1192 /* Now read through those files ... */
1194 /* Get us to the next block, or the first block first time around */
1195 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1196 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1197 SAFE_FREE(longfilename
);
1201 DEBUG(5, ("Reading the next header ...\n"));
1203 switch (readtarheader((union hblock
*) buffer_p
,
1204 &finfo
, client_get_cur_dir())) {
1205 case -2: /* Hmm, not good, but not fatal */
1206 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1207 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) && !skip_file(finfo
.size
)) {
1208 DEBUG(0, ("Short file, bailing out...\n"));
1214 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1217 case 0: /* chksum is zero - looks like an EOF */
1218 DEBUG(0, ("tar: restored %d files and directories\n", ntarf
));
1219 return; /* Hmmm, bad here ... */
1226 /* Now, do we have a long file name? */
1227 if (longfilename
!= NULL
) {
1228 SAFE_FREE(finfo
.name
); /* Free the space already allocated */
1229 finfo
.name
= longfilename
;
1230 longfilename
= NULL
;
1233 /* Well, now we have a header, process the file ... */
1234 /* Should we skip the file? We have the long name as well here */
1235 skip
= clipn
&& ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
) ||
1236 (tar_re_search
&& mask_match_list(finfo
.name
, cliplist
, clipn
, True
)));
1238 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1240 skip_file(finfo
.size
);
1244 /* We only get this far if we should process the file */
1245 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1247 case '0': /* Should use symbolic names--FIXME */
1249 * Skip to the next block first, so we can get the file, FIXME, should
1250 * be in get_file ...
1251 * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
1252 * Fixes bug where file size in tarfile is zero.
1254 if ((finfo
.size
!= 0) && next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1255 DEBUG(0, ("Short file, bailing out...\n"));
1258 if (!get_file(finfo
)) {
1259 DEBUG(0, ("Abandoning restore\n"));
1264 if (!get_dir(finfo
)) {
1265 DEBUG(0, ("Abandoning restore \n"));
1270 SAFE_FREE(longfilename
);
1271 longfilename
= get_longfilename(finfo
);
1272 if (!longfilename
) {
1273 DEBUG(0, ("abandoning restore\n"));
1276 DEBUG(5, ("Long file name: %s\n", longfilename
));
1280 skip_file(finfo
.size
); /* Don't handle these yet */
1287 * samba interactive commands
1290 /****************************************************************************
1292 ***************************************************************************/
1296 TALLOC_CTX
*ctx
= talloc_tos();
1300 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1301 DEBUG(0, ("blocksize <n>\n"));
1306 if (block
< 0 || block
> 65535) {
1307 DEBUG(0, ("blocksize out of range"));
1312 DEBUG(2,("blocksize is now %d\n", blocksize
));
1316 /****************************************************************************
1317 command to set incremental / reset mode
1318 ***************************************************************************/
1320 int cmd_tarmode(void)
1322 TALLOC_CTX
*ctx
= talloc_tos();
1325 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1326 if (strequal(buf
, "full"))
1328 else if (strequal(buf
, "inc"))
1330 else if (strequal(buf
, "reset"))
1332 else if (strequal(buf
, "noreset"))
1334 else if (strequal(buf
, "system"))
1336 else if (strequal(buf
, "nosystem"))
1338 else if (strequal(buf
, "hidden"))
1340 else if (strequal(buf
, "nohidden"))
1342 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
1344 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
1347 DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
1351 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
1352 tar_inc
? "incremental" : "full",
1353 tar_system
? "system" : "nosystem",
1354 tar_hidden
? "hidden" : "nohidden",
1355 tar_reset
? "reset" : "noreset",
1356 tar_noisy
? "verbose" : "quiet"));
1360 /****************************************************************************
1361 Feeble attrib command
1362 ***************************************************************************/
1364 int cmd_setmode(void)
1366 TALLOC_CTX
*ctx
= talloc_tos();
1373 attra
[0] = attra
[1] = 0;
1375 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1376 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1380 fname
= talloc_asprintf(ctx
,
1382 client_get_cur_dir(),
1388 while (next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1400 attra
[direct
]|=aRONLY
;
1403 attra
[direct
]|=aHIDDEN
;
1406 attra
[direct
]|=aSYSTEM
;
1409 attra
[direct
]|=aARCH
;
1412 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
1418 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0) {
1419 DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
1423 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
1424 do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
1425 do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
1430 Convert list of tokens to array; dependent on above routine.
1431 Uses the global cmd_ptr from above - bit of a hack.
1434 static char **toktocliplist(int *ctok
, const char *sep
)
1436 char *s
=(char *)cmd_ptr
;
1443 while(*s
&& strchr_m(sep
,*s
))
1452 while(*s
&& (!strchr_m(sep
,*s
)))
1454 while(*s
&& strchr_m(sep
,*s
))
1461 if (!(ret
=iret
=SMB_MALLOC_ARRAY(char *,ictok
+1)))
1478 /****************************************************************************
1479 Principal command for creating / extracting
1480 ***************************************************************************/
1484 TALLOC_CTX
*ctx
= talloc_tos();
1490 if (!next_token_talloc(ctx
, &cmd_ptr
,&buf
,NULL
)) {
1491 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
1495 argl
=toktocliplist(&argcl
, NULL
);
1496 if (!tar_parseargs(argcl
, argl
, buf
, 0)) {
1501 ret
= process_tar();
1506 /****************************************************************************
1507 Command line (option) version
1508 ***************************************************************************/
1510 int process_tar(void)
1512 TALLOC_CTX
*ctx
= talloc_tos();
1528 if (clipn
&& tar_excl
) {
1530 char *tarmac
= NULL
;
1532 for (i
=0; i
<clipn
; i
++) {
1533 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
1535 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
1536 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
1539 if (strrchr_m(cliplist
[i
], '\\')) {
1542 char *saved_dir
= talloc_strdup(ctx
,
1543 client_get_cur_dir());
1548 if (*cliplist
[i
]=='\\') {
1549 tarmac
= talloc_strdup(ctx
,
1552 tarmac
= talloc_asprintf(ctx
,
1554 client_get_cur_dir(),
1561 * Strip off the last \\xxx
1562 * xxx element of tarmac to set
1563 * it as current directory.
1565 p
= strrchr_m(tarmac
, '\\');
1572 client_set_cur_dir(tarmac
);
1575 * Restore the character we
1582 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1583 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1585 client_set_cur_dir(saved_dir
);
1587 TALLOC_FREE(saved_dir
);
1588 TALLOC_FREE(tarmac
);
1590 tarmac
= talloc_asprintf(ctx
,
1592 client_get_cur_dir(),
1597 DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac
));
1598 do_list(tarmac
,attribute
,do_tar
, False
, True
);
1599 TALLOC_FREE(tarmac
);
1603 char *mask
= talloc_asprintf(ctx
,
1605 client_get_cur_dir());
1609 DEBUG(5, ("process_tar, do_list with mask: %s\n", mask
));
1610 do_list(mask
,attribute
,do_tar
,False
, True
);
1615 dotareof(tarhandle
);
1620 DEBUG(0, ("tar: dumped %d files and directories\n", ntarf
));
1621 DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf
));
1625 if (must_free_cliplist
) {
1627 for (i
= 0; i
< clipn
; ++i
) {
1628 SAFE_FREE(cliplist
[i
]);
1630 SAFE_FREE(cliplist
);
1633 must_free_cliplist
= False
;
1638 /****************************************************************************
1639 Find a token (filename) in a clip list
1640 ***************************************************************************/
1642 static int clipfind(char **aret
, int ret
, char *tok
)
1647 /* ignore leading slashes or dots in token */
1648 while(strchr_m("/\\.", *tok
))
1654 /* ignore leading slashes or dots in list */
1655 while(strchr_m("/\\.", *pkey
))
1658 if (!strslashcmp(pkey
, tok
))
1664 /****************************************************************************
1665 Read list of files to include from the file and initialize cliplist
1667 ***************************************************************************/
1669 static int read_inclusion_file(char *filename
)
1671 XFILE
*inclusion
= NULL
;
1672 char buf
[PATH_MAX
+ 1];
1673 char *inclusion_buffer
= NULL
;
1674 int inclusion_buffer_size
= 0;
1675 int inclusion_buffer_sofar
= 0;
1682 buf
[PATH_MAX
] = '\0'; /* guarantee null-termination */
1683 if ((inclusion
= x_fopen(filename
, O_RDONLY
, 0)) == NULL
) {
1684 /* XXX It would be better to include a reason for failure, but without
1685 * autoconf, it's hard to use strerror, sys_errlist, etc.
1687 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
1691 while ((! error
) && (x_fgets(buf
, sizeof(buf
)-1, inclusion
))) {
1692 if (inclusion_buffer
== NULL
) {
1693 inclusion_buffer_size
= 1024;
1694 if ((inclusion_buffer
= (char *)SMB_MALLOC(inclusion_buffer_size
)) == NULL
) {
1695 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
1701 if (buf
[strlen(buf
)-1] == '\n') {
1702 buf
[strlen(buf
)-1] = '\0';
1705 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
1706 inclusion_buffer_size
*= 2;
1707 inclusion_buffer
= (char *)SMB_REALLOC(inclusion_buffer
,inclusion_buffer_size
);
1708 if (!inclusion_buffer
) {
1709 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
1710 inclusion_buffer_size
));
1716 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
1717 inclusion_buffer_sofar
+= strlen(buf
) + 1;
1720 x_fclose(inclusion
);
1723 /* Allocate an array of clipn + 1 char*'s for cliplist */
1724 cliplist
= SMB_MALLOC_ARRAY(char *, clipn
+ 1);
1725 if (cliplist
== NULL
) {
1726 DEBUG(0,("failure allocating memory for cliplist\n"));
1729 cliplist
[clipn
] = NULL
;
1730 p
= inclusion_buffer
;
1731 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
1732 /* set current item to NULL so array will be null-terminated even if
1733 * malloc fails below. */
1735 if ((tmpstr
= (char *)SMB_MALLOC(strlen(p
)+1)) == NULL
) {
1736 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
1739 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
1740 cliplist
[i
] = tmpstr
;
1741 if ((p
= strchr_m(p
, '\000')) == NULL
) {
1742 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
1748 must_free_cliplist
= True
;
1752 SAFE_FREE(inclusion_buffer
);
1756 /* We know cliplist is always null-terminated */
1757 for (pp
= cliplist
; *pp
; ++pp
) {
1760 SAFE_FREE(cliplist
);
1762 must_free_cliplist
= False
;
1767 /* cliplist and its elements are freed at the end of process_tar. */
1771 /****************************************************************************
1772 Parse tar arguments. Sets tar_type, tar_excl, etc.
1773 ***************************************************************************/
1775 int tar_parseargs(int argc
, char *argv
[], const char *Optarg
, int Optind
)
1777 int newOptind
= Optind
;
1778 char tar_clipfl
='\0';
1780 /* Reset back to defaults - could be from interactive version
1781 * reset mode and archive mode left as they are though
1793 if (tar_type
=='c') {
1794 printf("Tar must be followed by only one of c or x.\n");
1800 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
1801 DEBUG(0,("Option b must be followed by valid blocksize\n"));
1813 DEBUG(0,("Option N must be followed by valid file name\n"));
1816 SMB_STRUCT_STAT stbuf
;
1818 if (sys_stat(argv
[Optind
], &stbuf
,
1820 newer_than
= convert_timespec_to_time_t(
1822 DEBUG(1,("Getting files newer than %s",
1823 time_to_asc(newer_than
)));
1827 DEBUG(0,("Error setting newer-than time\n"));
1840 DEBUG(0,("Only one of I,X,F must be specified\n"));
1847 DEBUG(0,("Only one of I,X,F must be specified\n"));
1854 DEBUG(0,("Only one of I,X,F must be specified\n"));
1860 DEBUG(0, ("tar_re_search set\n"));
1861 tar_re_search
= True
;
1864 if (tar_type
== 'c') {
1865 DEBUG(0, ("dry_run set\n"));
1868 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
1873 DEBUG(0,("Unknown tar option\n"));
1879 printf("Option T must be followed by one of c or x.\n");
1883 /* tar_excl is true if cliplist lists files to be included.
1884 * Both 'I' and 'F' mean include. */
1885 tar_excl
=tar_clipfl
!='X';
1887 if (tar_clipfl
=='F') {
1888 if (argc
-Optind
-1 != 1) {
1889 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
1893 /* Optind points at the tar output file, Optind+1 at the inclusion file. */
1894 if (! read_inclusion_file(argv
[Optind
+1])) {
1897 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
1902 cliplist
=argv
+Optind
+1;
1903 clipn
=argc
-Optind
-1;
1906 if ((tmplist
=SMB_MALLOC_ARRAY(char *,clipn
)) == NULL
) {
1907 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", clipn
));
1911 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
1913 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
1915 if ((tmpstr
= (char *)SMB_MALLOC(strlen(cliplist
[clipcount
])+1)) == NULL
) {
1916 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount
));
1921 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
1922 tmplist
[clipcount
] = tmpstr
;
1923 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
1925 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
1929 must_free_cliplist
= True
;
1934 if (Optind
+1<argc
&& tar_re_search
&& tar_clipfl
!= 'F') {
1935 /* Doing regular expression seaches not from an inclusion file. */
1936 clipn
=argc
-Optind
-1;
1937 cliplist
=argv
+Optind
+1;
1941 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
1942 /* Sets tar handle to either 0 or 1, as appropriate */
1943 tarhandle
=(tar_type
=='c');
1945 * Make sure that dbf points to stderr if we are using stdout for
1948 if (tarhandle
== 1) {
1949 setup_logging("smbclient", DEBUG_STDERR
);
1951 if (!argv
[Optind
]) {
1952 DEBUG(0,("Must specify tar filename\n"));
1955 if (!strcmp(argv
[Optind
], "-")) {
1960 if (tar_type
=='c' && dry_run
) {
1962 } else if ((tar_type
=='x' && (tarhandle
= sys_open(argv
[Optind
], O_RDONLY
, 0)) == -1)
1963 || (tar_type
=='c' && (tarhandle
=sys_creat(argv
[Optind
], 0644)) < 0)) {
1964 DEBUG(0,("Error opening local file %s - %s\n", argv
[Optind
], strerror(errno
)));