2 Unix SMB/Netbios implementation.
5 Copyright (C) Ricky Poulten 1995-1998
6 Copyright (C) Richard Sharpe 1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* The following changes developed by Richard Sharpe for Canon Information
23 Systems Research Australia (CISRA)
25 1. Restore can now restore files with long file names
26 2. Save now saves directory information so that we can restore
27 directory creation times
28 3. tar now accepts both UNIX path names and DOS path names. I prefer
29 those lovely /'s to those UGLY \'s :-)
30 4. the files to exclude can be specified as a regular expression by adding
31 an r flag to the other tar flags. Eg:
33 -TcrX file.tar "*.(obj|exe)"
35 will skip all .obj and .exe files
42 static int clipfind(char **aret
, int ret
, char *tok
);
44 typedef struct file_info_struct file_info2
;
46 struct file_info_struct
52 /* These times are normally kept in GMT */
56 char *name
; /* This is dynamically allocate */
58 file_info2
*next
, *prev
; /* Used in the stack ... */
69 stack dir_stack
= {NULL
, 0}; /* Want an empty stack */
73 #define SEPARATORS " \t\n\r"
74 extern int DEBUGLEVEL
;
77 /* These defines are for the do_setrattr routine, to indicate
78 * setting and reseting of file attributes in the function call */
82 static int attribute
= aDIR
| aSYSTEM
| aHIDDEN
;
84 #ifndef CLIENT_TIMEOUT
85 #define CLIENT_TIMEOUT (30*1000)
88 static char *tarbuf
, *buffer_p
;
89 static int tp
, ntarf
, tbufsiz
, ttarf
;
90 /* Incremental mode */
92 /* Reset archive bit */
94 /* Include / exclude mode (true=include, false=exclude) */
96 /* use regular expressions for search on file names */
97 BOOL tar_re_search
=False
;
101 /* Do not dump anything, just calculate sizes */
103 /* Dump files with System attribute */
104 BOOL tar_system
=True
;
105 /* Dump files with Hidden attribute */
106 BOOL tar_hidden
=True
;
107 /* Be noisy - make a catalogue */
109 BOOL tar_real_noisy
=False
; /* Don't want to be really noisy by default */
112 static char **cliplist
=NULL
;
114 static BOOL must_free_cliplist
= False
;
116 extern file_info def_finfo
;
117 extern BOOL lowercase
;
119 extern BOOL readbraw_supported
;
121 extern pstring cur_dir
;
122 extern int get_total_time_ms
;
123 extern int get_total_size
;
129 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
130 char *amode
, unsigned char ftype
);
131 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
);
132 static void do_tar(file_info
*finfo
);
133 static void oct_it(long value
, int ndgs
, char *p
);
134 static void fixtarname(char *tptr
, char *fp
, int l
);
135 static int dotarbuf(int f
, char *b
, int n
);
136 static void dozerobuf(int f
, int n
);
137 static void dotareof(int f
);
138 static void initarbuf(void);
139 static int do_setrattr(char *fname
, int attr
, int setit
);
141 /* restore functions */
142 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
);
143 static long unoct(char *p
, int ndgs
);
144 static void do_tarput(void);
145 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
);
148 * tar specific utitlities
151 #if 0 /* Removed to get around gcc 'defined but not used' error. */
154 * Stack routines, push_dir, pop_dir, top_dir_name
157 static BOOL
push_dir(stack
*tar_dir_stack
, file_info2
*dir
)
159 dir
-> next
= tar_dir_stack
-> top
;
161 tar_dir_stack
-> items
++;
162 tar_dir_stack
-> top
= dir
;
167 static file_info2
*pop_dir(stack
*tar_dir_stack
)
171 ptr
= tar_dir_stack
-> top
;
172 if (tar_dir_stack
-> top
!= NULL
) {
174 tar_dir_stack
-> top
= tar_dir_stack
-> top
-> next
;
175 tar_dir_stack
-> items
--;
183 static char *top_dir_name(stack
*tar_dir_stack
)
186 return(tar_dir_stack
-> top
!= NULL
?tar_dir_stack
-> top
-> name
:NULL
);
190 static BOOL
sub_dir(char *dir1
, char *dir2
)
197 #endif /* Removed to get around gcc 'defined but not used' error. */
199 /*******************************************************************
200 Create a string of size size+1 (for the null)
201 *******************************************************************/
202 static char *string_create_s(int size
)
206 tmp
= (char *)malloc(size
+1);
210 DEBUG(0, ("Out of memory in string_create_s\n"));
218 /****************************************************************************
219 Write a tar header to buffer
220 ****************************************************************************/
221 static void writetarheader(int f
, char *aname
, int size
, time_t mtime
,
222 char *amode
, unsigned char ftype
)
228 DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype
, size
, aname
));
230 memset(hb
.dummy
, 0, sizeof(hb
.dummy
));
234 /* write a GNU tar style long header */
236 b
= (char *)malloc(l
+TBLOCK
+100);
238 DEBUG(0,("out of memory\n"));
241 writetarheader(f
, "/./@LongLink", l
+1, 0, " 0 \0", 'L');
242 memset(b
, 0, l
+TBLOCK
+100);
243 fixtarname(b
, aname
, l
);
245 DEBUG(5, ("File name in tar file: %s, size=%i, \n", b
, strlen(b
)));
246 dotarbuf(f
, b
, TBLOCK
*(((i
-1)/TBLOCK
)+1));
250 /* use l + 1 to do the null too */
251 fixtarname(hb
.dbuf
.name
, aname
, (l
>= NAMSIZ
) ? NAMSIZ
: l
+ 1);
254 strlower(hb
.dbuf
.name
);
256 /* write out a "standard" tar format header */
258 hb
.dbuf
.name
[NAMSIZ
-1]='\0';
259 safe_strcpy(hb
.dbuf
.mode
, amode
, strlen(amode
));
260 oct_it(0L, 8, hb
.dbuf
.uid
);
261 oct_it(0L, 8, hb
.dbuf
.gid
);
262 oct_it((long) size
, 13, hb
.dbuf
.size
);
263 oct_it((long) mtime
, 13, hb
.dbuf
.mtime
);
264 memcpy(hb
.dbuf
.chksum
, " ", sizeof(hb
.dbuf
.chksum
));
265 memset(hb
.dbuf
.linkname
, 0, NAMSIZ
);
266 hb
.dbuf
.linkflag
=ftype
;
268 for (chk
=0, i
=sizeof(hb
.dummy
), jp
=hb
.dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
270 oct_it((long) chk
, 8, hb
.dbuf
.chksum
);
271 hb
.dbuf
.chksum
[6] = '\0';
273 (void) dotarbuf(f
, hb
.dummy
, sizeof(hb
.dummy
));
276 /****************************************************************************
277 Read a tar header into a hblock structure, and validate
278 ***************************************************************************/
279 static long readtarheader(union hblock
*hb
, file_info2
*finfo
, char *prefix
)
286 * read in a "standard" tar format header - we're not that interested
287 * in that many fields, though
290 /* check the checksum */
291 for (chk
=0, i
=sizeof(hb
->dummy
), jp
=hb
->dummy
; --i
>=0;) chk
+=(0xFF & *jp
++);
296 /* compensate for blanks in chksum header */
297 for (i
=sizeof(hb
->dbuf
.chksum
), jp
=hb
->dbuf
.chksum
; --i
>=0;)
300 chk
+= ' ' * sizeof(hb
->dbuf
.chksum
);
302 fchk
=unoct(hb
->dbuf
.chksum
, sizeof(hb
->dbuf
.chksum
));
304 DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
305 chk
, fchk
, hb
->dbuf
.chksum
));
309 DEBUG(0, ("checksums don't match %ld %ld\n", fchk
, chk
));
310 dump_data(5, (char *)hb
- TBLOCK
, TBLOCK
*3);
314 if ((finfo
->name
= string_create_s(strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3)) == NULL
) {
316 DEBUG(0, ("Out of space creating file_info2 for %s\n", hb
-> dbuf
.name
));
321 safe_strcpy(finfo
->name
, prefix
, strlen(prefix
) + strlen(hb
-> dbuf
.name
) + 3);
323 /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
324 unfixtarname(finfo
->name
+ strlen(prefix
), hb
->dbuf
.name
,
325 strlen(hb
->dbuf
.name
) + 1, True
);
327 /* can't handle some links at present */
328 if ((hb
->dbuf
.linkflag
!= '0') && (hb
-> dbuf
.linkflag
!= '5')) {
329 if (hb
->dbuf
.linkflag
== 0) {
330 DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
333 if (hb
-> dbuf
.linkflag
== 'L') { /* We have a longlink */
334 /* Do nothing here at the moment. do_tarput will handle this
335 as long as the longlink gets back to it, as it has to advance
336 the buffer pointer, etc */
339 DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
345 if ((unoct(hb
->dbuf
.mode
, sizeof(hb
->dbuf
.mode
)) & S_IFDIR
)
346 || (*(finfo
->name
+strlen(finfo
->name
)-1) == '\\'))
351 finfo
->mode
=0; /* we don't care about mode at the moment, we'll
352 * just make it a regular file */
354 * Bug fix by richard@sj.co.uk
356 * REC: restore times correctly (as does tar)
357 * We only get the modification time of the file; set the creation time
358 * from the mod. time, and the access time to current time
360 finfo
->mtime
= finfo
->ctime
= strtol(hb
->dbuf
.mtime
, NULL
, 8);
361 finfo
->atime
= time(NULL
);
362 finfo
->size
= unoct(hb
->dbuf
.size
, sizeof(hb
->dbuf
.size
));
367 /****************************************************************************
368 Write out the tar buffer to tape or wherever
369 ****************************************************************************/
370 static int dotarbuf(int f
, char *b
, int n
)
377 /* This routine and the next one should be the only ones that do write()s */
378 if (tp
+ n
>= tbufsiz
)
383 memcpy(tarbuf
+ tp
, b
, diff
);
384 fail
=fail
&& (1+write(f
, tarbuf
, tbufsiz
));
391 fail
=fail
&& (1 + write(f
, b
, tbufsiz
));
397 memcpy(tarbuf
+tp
, b
, n
);
401 return(fail
? writ
: 0);
404 /****************************************************************************
405 Write zeros to buffer / tape
406 ****************************************************************************/
407 static void dozerobuf(int f
, int n
)
409 /* short routine just to write out n zeros to buffer -
410 * used to round files to nearest block
411 * and to do tar EOFs */
418 memset(tarbuf
+tp
, 0, tbufsiz
-tp
);
420 write(f
, tarbuf
, tbufsiz
);
421 memset(tarbuf
, 0, (tp
+=n
-tbufsiz
));
425 memset(tarbuf
+tp
, 0, n
);
430 /****************************************************************************
432 ****************************************************************************/
433 static void initarbuf(void)
435 /* initialize tar buffer */
436 tbufsiz
=blocksize
*TBLOCK
;
437 tarbuf
=malloc(tbufsiz
); /* FIXME: We might not get the buffer */
439 /* reset tar buffer pointer and tar file counter and total dumped */
440 tp
=0; ntarf
=0; ttarf
=0;
443 /****************************************************************************
444 Write two zero blocks at end of file
445 ****************************************************************************/
446 static void dotareof(int f
)
448 SMB_STRUCT_STAT stbuf
;
449 /* Two zero blocks at end of file, write out full buffer */
454 (void) dozerobuf(f
, TBLOCK
);
455 (void) dozerobuf(f
, TBLOCK
);
457 if (sys_fstat(f
, &stbuf
) == -1)
459 DEBUG(0, ("Couldn't stat file handle\n"));
463 /* Could be a pipe, in which case S_ISREG should fail,
464 * and we should write out at full size */
465 if (tp
> 0) write(f
, tarbuf
, S_ISREG(stbuf
.st_mode
) ? tp
: tbufsiz
);
468 /****************************************************************************
469 (Un)mangle DOS pathname, make nonabsolute
470 ****************************************************************************/
471 static void fixtarname(char *tptr
, char *fp
, int l
)
473 /* add a '.' to start of file name, convert from ugly dos \'s in path
474 * to lovely unix /'s :-} */
480 if((skip
= skip_multibyte_char( *fp
)) != 0) {
485 } else if (skip
== 1) {
489 } else if (*fp
== '\\') {
500 /****************************************************************************
501 Convert from decimal to octal string
502 ****************************************************************************/
503 static void oct_it (long value
, int ndgs
, char *p
)
505 /* Converts long to octal string, pads with leading zeros */
507 /* skip final null, but do final space */
511 /* Loop does at least one digit */
513 p
[--ndgs
] = '0' + (char) (value
& 7);
516 while (ndgs
> 0 && value
!= 0);
518 /* Do leading zeros */
523 /****************************************************************************
524 Convert from octal string to long
525 ***************************************************************************/
526 static long unoct(char *p
, int ndgs
)
529 /* Converts octal string to long, ignoring any non-digit */
533 if (isdigit((int)*p
))
534 value
= (value
<< 3) | (long) (*p
- '0');
542 /****************************************************************************
543 Compare two strings in a slash insensitive way, allowing s1 to match s2
544 if s1 is an "initial" string (up to directory marker). Thus, if s2 is
545 a file in any subdirectory of s1, declare a match.
546 ***************************************************************************/
547 static int strslashcmp(char *s1
, char *s2
)
553 || tolower(*s1
) == tolower(*s2
)
554 || (*s1
== '\\' && *s2
=='/')
555 || (*s1
== '/' && *s2
=='\\'))) {
559 /* if s1 has a trailing slash, it compared equal, so s1 is an "initial"
562 if (!*s1
&& s1
!= s1_0
&& (*(s1
-1) == '/' || *(s1
-1) == '\\')) return 0;
564 /* ignore trailing slash on s1 */
565 if (!*s2
&& (*s1
== '/' || *s1
== '\\') && !*(s1
+1)) return 0;
567 /* check for s1 is an "initial" string of s2 */
568 if (*s2
== '/' || *s2
== '\\') return 0;
574 * general smb utility functions
576 /**********************************************************************
577 do_setrtime, set time on a file or dir ...
578 **********************************************************************/
580 static int do_setrtime(char *fname
, int mtime
, BOOL err_silent
)
582 char *inbuf
, *outbuf
, *p
;
585 DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname
, strlen(fname
)));
587 name
= (char *)malloc(strlen(fname
) + 1 + 1);
590 DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname
));
596 safe_strcpy(name
, "\\", strlen(fname
) + 1);
598 safe_strcpy(name
, "", strlen(fname
) + 1);
599 safe_strcat(name
, fname
, strlen(fname
) + 1);
601 if (fname
[strlen(name
) - 1] == '\\')
602 name
[strlen(name
) - 1] = '\0';
604 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
605 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
607 if (!inbuf
|| !outbuf
) {
609 DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname
));
615 memset(outbuf
, 0, smb_size
);
616 set_message(outbuf
, 8, 4 + strlen(name
), True
);
617 CVAL(outbuf
, smb_com
) = SMBsetatr
;
618 SSVAL(outbuf
, smb_tid
, cnum
);
619 cli_setup_pkt(outbuf
);
621 SSVAL(outbuf
, smb_vwv0
, 0);
622 put_dos_date3(outbuf
, smb_vwv1
, mtime
);
626 safe_strcpy(p
, name
, strlen(name
));
627 p
+= (strlen(fname
)+1);
632 send_smb(Client
, outbuf
);
633 client_receive_smb(Client
, inbuf
, CLIENT_TIMEOUT
);
635 if (CVAL(inbuf
,smb_rcls
) != 0)
638 DEBUG(0,("%s setting attributes on file %s\n",
639 smb_errstr(inbuf
), fname
));
641 free(name
);free(inbuf
);free(outbuf
);
646 free(inbuf
);free(outbuf
);
651 /****************************************************************************
652 Set DOS file attributes
653 ***************************************************************************/
654 static int do_setrattr(char *fname
, int attr
, int setit
)
657 * First get the existing attribs from existing file
664 name
= (char *)malloc(strlen(fname
) + 1 + 1);
667 DEBUG(0, ("Failed to allocate space in do_setrattr while setting time on file: %s", fname
));
672 safe_strcpy(name
, "\\", strlen(fname
) + 1);
673 safe_strcat(name
, fname
, strlen(fname
) + 1);
675 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
676 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
678 if (!inbuf
|| !outbuf
)
680 DEBUG(0,("out of memory\n"));
685 /* send an smb getatr message */
687 memset(outbuf
,0,smb_size
);
688 set_message(outbuf
,0,2 + strlen(fname
),True
);
689 CVAL(outbuf
,smb_com
) = SMBgetatr
;
690 SSVAL(outbuf
,smb_tid
,cnum
);
691 cli_setup_pkt(outbuf
);
695 safe_strcpy(p
,name
, strlen(name
));
696 p
+= (strlen(name
)+1);
701 send_smb(Client
,outbuf
);
702 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
704 if (CVAL(inbuf
,smb_rcls
) != 0)
705 DEBUG(5,("getatr: %s\n",smb_errstr(inbuf
)));
708 DEBUG(5,("\nattr 0x%X time %d size %d\n",
709 (int)CVAL(inbuf
,smb_vwv0
),
710 SVAL(inbuf
,smb_vwv1
),
711 SVAL(inbuf
,smb_vwv3
)));
714 fattr
=CVAL(inbuf
,smb_vwv0
);
716 /* combine found attributes with bits to be set or reset */
718 attr
=setit
? (fattr
| attr
) : (fattr
& ~attr
);
720 /* now try and set attributes by sending smb reset message */
722 /* clear out buffer and start again */
723 memset(outbuf
,0,smb_size
);
724 set_message(outbuf
,8,4 + strlen(name
),True
);
725 CVAL(outbuf
,smb_com
) = SMBsetatr
;
726 SSVAL(outbuf
,smb_tid
,cnum
);
727 cli_setup_pkt(outbuf
);
729 SSVAL(outbuf
,smb_vwv0
,attr
);
733 safe_strcpy(p
,name
, strlen(name
));
734 p
+= (strlen(name
)+1);
739 send_smb(Client
,outbuf
);
740 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
742 if (CVAL(inbuf
,smb_rcls
) != 0)
744 DEBUG(0,("%s setting attributes on file %s\n",
745 smb_errstr(inbuf
), name
));
746 free(name
);free(inbuf
);free(outbuf
);
751 free(inbuf
);free(outbuf
);
755 /****************************************************************************
756 Create a file on a share
757 ***************************************************************************/
758 static BOOL
smbcreat(file_info2 finfo
, int *fnum
, char *inbuf
, char *outbuf
)
761 /* *must* be called with buffer ready malloc'ed */
762 /* open remote file */
764 memset(outbuf
,0,smb_size
);
765 set_message(outbuf
,3,2 + strlen(finfo
.name
),True
);
766 CVAL(outbuf
,smb_com
) = SMBcreate
;
767 SSVAL(outbuf
,smb_tid
,cnum
);
768 cli_setup_pkt(outbuf
);
770 SSVAL(outbuf
,smb_vwv0
,finfo
.mode
);
771 put_dos_date3(outbuf
,smb_vwv1
,finfo
.mtime
);
775 safe_strcpy(p
,finfo
.name
, strlen(finfo
.name
));
777 send_smb(Client
,outbuf
);
778 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
780 if (CVAL(inbuf
,smb_rcls
) != 0)
782 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),
787 *fnum
= SVAL(inbuf
,smb_vwv0
);
791 /****************************************************************************
792 Write a file to a share
793 ***************************************************************************/
794 static BOOL
smbwrite(int fnum
, int n
, int low
, int high
, int left
,
795 char *bufferp
, char *inbuf
, char *outbuf
)
797 /* *must* be called with buffer ready malloc'ed */
799 memset(outbuf
,0,smb_size
);
800 set_message(outbuf
,5,n
+ 3,True
);
802 memcpy(smb_buf(outbuf
)+3, bufferp
, n
);
804 set_message(outbuf
,5,n
+ 3, False
);
805 CVAL(outbuf
,smb_com
) = SMBwrite
;
806 SSVAL(outbuf
,smb_tid
,cnum
);
807 cli_setup_pkt(outbuf
);
809 SSVAL(outbuf
,smb_vwv0
,fnum
);
810 SSVAL(outbuf
,smb_vwv1
,n
);
811 SIVAL(outbuf
,smb_vwv2
,low
);
812 SSVAL(outbuf
,smb_vwv4
,left
);
813 CVAL(smb_buf(outbuf
),0) = 1;
814 SSVAL(smb_buf(outbuf
),1,n
);
816 send_smb(Client
,outbuf
);
817 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
819 if (CVAL(inbuf
,smb_rcls
) != 0)
821 DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf
)));
825 if (n
!= SVAL(inbuf
,smb_vwv0
))
827 DEBUG(0,("Error: only wrote %d bytes out of %d\n",
828 SVAL(inbuf
,smb_vwv0
), n
));
835 /****************************************************************************
836 Close a file on a share
837 ***************************************************************************/
838 static BOOL
smbshut(file_info2 finfo
, int fnum
, char *inbuf
, char *outbuf
)
840 /* *must* be called with buffer ready malloc'ed */
842 memset(outbuf
,0,smb_size
);
843 set_message(outbuf
,3,0,True
);
844 CVAL(outbuf
,smb_com
) = SMBclose
;
845 SSVAL(outbuf
,smb_tid
,cnum
);
846 cli_setup_pkt(outbuf
);
848 SSVAL(outbuf
,smb_vwv0
,fnum
);
849 put_dos_date3(outbuf
,smb_vwv1
,finfo
.mtime
);
851 DEBUG(3,("Setting date to %s (0x%lX)",
852 asctime(LocalTime(&finfo
.mtime
)),
855 send_smb(Client
,outbuf
);
856 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
858 if (CVAL(inbuf
,smb_rcls
) != 0)
860 DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf
),
868 /****************************************************************************
869 Verify existence of path on share
870 ***************************************************************************/
871 static BOOL
smbchkpath(char *fname
, char *inbuf
, char *outbuf
)
875 memset(outbuf
,0,smb_size
);
876 set_message(outbuf
,0,4 + strlen(fname
),True
);
877 CVAL(outbuf
,smb_com
) = SMBchkpth
;
878 SSVAL(outbuf
,smb_tid
,cnum
);
879 cli_setup_pkt(outbuf
);
883 safe_strcpy(p
,fname
, strlen(fname
));
885 send_smb(Client
,outbuf
);
886 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
888 DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf
)));
890 return(CVAL(inbuf
,smb_rcls
) == 0);
893 /****************************************************************************
894 Make a directory on share
895 ***************************************************************************/
896 static BOOL
smbmkdir(char *fname
, char *inbuf
, char *outbuf
)
898 /* *must* be called with buffer ready malloc'ed */
901 memset(outbuf
,0,smb_size
);
902 set_message(outbuf
,0,2 + strlen(fname
),True
);
904 CVAL(outbuf
,smb_com
) = SMBmkdir
;
905 SSVAL(outbuf
,smb_tid
,cnum
);
906 cli_setup_pkt(outbuf
);
910 safe_strcpy(p
,fname
, strlen(fname
));
912 send_smb(Client
,outbuf
);
913 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
915 if (CVAL(inbuf
,smb_rcls
) != 0)
917 DEBUG(0,("%s making remote directory %s\n",
918 smb_errstr(inbuf
),fname
));
925 /****************************************************************************
926 Ensure a remote path exists (make if necessary)
927 ***************************************************************************/
928 static BOOL
ensurepath(char *fname
, char *inbuf
, char *outbuf
)
930 /* *must* be called with buffer ready malloc'ed */
931 /* ensures path exists */
933 char *partpath
, *ffname
;
934 char *p
=fname
, *basehack
;
936 DEBUG(5, ( "Ensurepath called with: %s\n", fname
));
938 partpath
= string_create_s(strlen(fname
));
939 ffname
= string_create_s(strlen(fname
));
941 if ((partpath
== NULL
) || (ffname
== NULL
)){
943 DEBUG(0, ("Out of memory in ensurepath: %s\n", fname
));
950 /* fname copied to ffname so can strtok */
952 safe_strcpy(ffname
, fname
, strlen(fname
));
954 /* do a `basename' on ffname, so don't try and make file name directory */
955 if ((basehack
=strrchr(ffname
, '\\')) == NULL
)
960 p
=strtok(ffname
, "\\");
964 safe_strcat(partpath
, p
, strlen(fname
) + 1);
966 if (!smbchkpath(partpath
, inbuf
, outbuf
)) {
967 if (!smbmkdir(partpath
, inbuf
, outbuf
))
969 DEBUG(0, ("Error mkdirhiering\n"));
973 DEBUG(3, ("mkdirhiering %s\n", partpath
));
977 safe_strcat(partpath
, "\\", strlen(fname
) + 1);
978 p
= strtok(NULL
,"/\\");
984 static int padit(char *buf
, int bufsize
, int padsize
)
989 DEBUG(5, ("Padding with %d zeros\n", padsize
));
990 memset(buf
, 0, bufsize
);
991 while( !berr
&& padsize
> 0 ) {
992 bytestowrite
= MIN(bufsize
, padsize
);
993 berr
= dotarbuf(tarhandle
, buf
, bytestowrite
) != bytestowrite
;
994 padsize
-= bytestowrite
;
1001 * smbclient functions
1003 /****************************************************************************
1004 append one remote file to the tar file
1005 ***************************************************************************/
1006 static void do_atar(char *rname
,char *lname
,file_info
*finfo1
)
1011 char *inbuf
,*outbuf
;
1013 BOOL close_done
= False
;
1014 BOOL shallitime
=True
;
1015 BOOL ignore_close_error
= False
;
1019 struct timeval tp_start
;
1020 GetTimeOfDay(&tp_start
);
1022 ftype
= '0'; /* An ordinary file ... */
1025 finfo
.size
= finfo1
-> size
;
1026 finfo
.mode
= finfo1
-> mode
;
1027 finfo
.uid
= finfo1
-> uid
;
1028 finfo
.gid
= finfo1
-> gid
;
1029 finfo
.mtime
= finfo1
-> mtime
;
1030 finfo
.atime
= finfo1
-> atime
;
1031 finfo
.ctime
= finfo1
-> ctime
;
1034 finfo
.size
= def_finfo
.size
;
1035 finfo
.mode
= def_finfo
.mode
;
1036 finfo
.uid
= def_finfo
.uid
;
1037 finfo
.gid
= def_finfo
.gid
;
1038 finfo
.mtime
= def_finfo
.mtime
;
1039 finfo
.atime
= def_finfo
.atime
;
1040 finfo
.ctime
= def_finfo
.ctime
;
1045 DEBUG(3,("skipping file %s of size %d bytes\n",
1049 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
1054 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1055 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1057 if (!inbuf
|| !outbuf
)
1059 DEBUG(0,("out of memory\n"));
1063 memset(outbuf
,0,smb_size
);
1064 set_message(outbuf
,15,1 + strlen(rname
),True
);
1066 CVAL(outbuf
,smb_com
) = SMBopenX
;
1067 SSVAL(outbuf
,smb_tid
,cnum
);
1068 cli_setup_pkt(outbuf
);
1070 SSVAL(outbuf
,smb_vwv0
,0xFF);
1071 SSVAL(outbuf
,smb_vwv2
,1);
1072 SSVAL(outbuf
,smb_vwv3
,(DENY_NONE
<<4));
1073 SSVAL(outbuf
,smb_vwv4
,aSYSTEM
| aHIDDEN
);
1074 SSVAL(outbuf
,smb_vwv5
,aSYSTEM
| aHIDDEN
);
1075 SSVAL(outbuf
,smb_vwv8
,1);
1077 p
= smb_buf(outbuf
);
1078 safe_strcpy(p
, rname
, strlen(rname
));
1079 p
= skip_string(p
,1);
1081 dos_clean_name(rname
);
1083 /* do a chained openX with a readX? */
1086 SSVAL(outbuf
,smb_vwv0
,SMBreadX
);
1087 SSVAL(outbuf
,smb_vwv1
,PTR_DIFF(p
,outbuf
) - 4);
1090 SCVAL(p
,smb_wct
,10);
1091 SSVAL(p
,smb_vwv0
,0xFF);
1092 SSVAL(p
,smb_vwv5
,MIN(max_xmit
-500,finfo
.size
));
1093 SSVAL(p
,smb_vwv9
,MIN(0xFFFF,finfo
.size
));
1094 smb_setlen(outbuf
,smb_len(outbuf
)+11*2+1);
1097 send_smb(Client
,outbuf
);
1098 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1100 if (CVAL(inbuf
,smb_rcls
) != 0)
1102 if (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
1103 SVAL(inbuf
,smb_err
) == ERRnoresource
&&
1104 cli_reopen_connection(inbuf
,outbuf
))
1106 do_atar(rname
,lname
,finfo1
);
1107 free(inbuf
);free(outbuf
);
1111 DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf
),rname
));
1112 free(inbuf
);free(outbuf
);
1116 finfo
.name
= string_create_s(strlen(rname
));
1117 if (finfo
.name
== NULL
) {
1119 DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
1120 free(inbuf
); free(outbuf
);
1125 safe_strcpy(finfo
.name
,rname
, strlen(rname
));
1128 finfo
.mode
= SVAL(inbuf
,smb_vwv3
);
1129 finfo
.size
= IVAL(inbuf
,smb_vwv4
);
1130 finfo
.mtime
= make_unix_date3(inbuf
+smb_vwv6
);
1131 finfo
.atime
= finfo
.ctime
= finfo
.mtime
;
1134 DEBUG(3,("file %s attrib 0x%X\n",finfo
.name
,finfo
.mode
));
1136 fnum
= SVAL(inbuf
,smb_vwv2
);
1138 if (tar_inc
&& !(finfo
.mode
& aARCH
))
1140 DEBUG(4, ("skipping %s - archive bit not set\n", finfo
.name
));
1143 else if (!tar_system
&& (finfo
.mode
& aSYSTEM
))
1145 DEBUG(4, ("skipping %s - system bit is set\n", finfo
.name
));
1148 else if (!tar_hidden
&& (finfo
.mode
& aHIDDEN
))
1150 DEBUG(4, ("skipping %s - hidden bit is set\n", finfo
.name
));
1155 if (SVAL(inbuf
,smb_vwv0
) == SMBreadX
)
1157 p
= (inbuf
+4+SVAL(inbuf
,smb_vwv1
)) - smb_wct
;
1158 datalen
= SVAL(p
,smb_vwv5
);
1159 dataptr
= inbuf
+ 4 + SVAL(p
,smb_vwv6
);
1167 DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
1172 /* write a tar header, don't bother with mode - just set to 100644 */
1173 writetarheader(tarhandle
, rname
, finfo
.size
, finfo
.mtime
, "100644 \0", ftype
);
1175 while (nread
< finfo
.size
&& !close_done
)
1178 static BOOL can_chain_close
=True
;
1182 DEBUG(3,("nread=%d\n",nread
));
1184 /* 3 possible read types. readbraw if a large block is required.
1185 readX + close if not much left and read if neither is supported */
1187 /* we might have already read some data from a chained readX */
1188 if (dataptr
&& datalen
>0)
1191 /* if we can finish now then readX+close */
1192 if (method
<0 && can_chain_close
&& (Protocol
>= PROTOCOL_LANMAN1
) &&
1193 ((finfo
.size
- nread
) <
1194 (max_xmit
- (2*smb_size
+ 13*SIZEOFWORD
+ 300))))
1197 /* if we support readraw then use that */
1198 if (method
<0 && readbraw_supported
)
1201 /* if we can then use readX */
1202 if (method
<0 && (Protocol
>= PROTOCOL_LANMAN1
))
1214 /* use readX + close */
1215 memset(outbuf
,0,smb_size
);
1216 set_message(outbuf
,10,0,True
);
1217 CVAL(outbuf
,smb_com
) = SMBreadX
;
1218 SSVAL(outbuf
,smb_tid
,cnum
);
1219 cli_setup_pkt(outbuf
);
1223 CVAL(outbuf
,smb_vwv0
) = SMBclose
;
1224 SSVAL(outbuf
,smb_vwv1
,PTR_DIFF(smb_buf(outbuf
),outbuf
) - 4);
1227 CVAL(outbuf
,smb_vwv0
) = 0xFF;
1230 SSVAL(outbuf
,smb_vwv2
,fnum
);
1231 SIVAL(outbuf
,smb_vwv3
,nread
);
1232 SSVAL(outbuf
,smb_vwv5
,MIN(max_xmit
-200,finfo
.size
- nread
));
1233 SSVAL(outbuf
,smb_vwv6
,0);
1234 SIVAL(outbuf
,smb_vwv7
,0);
1235 SSVAL(outbuf
,smb_vwv9
,MIN(0xFFFF,finfo
.size
-nread
));
1239 p
= smb_buf(outbuf
);
1246 /* now set the total packet length */
1247 smb_setlen(outbuf
,smb_len(outbuf
)+9);
1250 send_smb(Client
,outbuf
);
1251 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1253 if (CVAL(inbuf
,smb_rcls
) != 0)
1255 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1260 SVAL(inbuf
,smb_vwv0
) != SMBclose
)
1262 /* NOTE: WfWg sometimes just ignores the chained
1263 command! This seems to break the spec? */
1264 DEBUG(3,("Rejected chained close?\n"));
1266 can_chain_close
= False
;
1267 ignore_close_error
= True
;
1270 datalen
= SVAL(inbuf
,smb_vwv5
);
1271 dataptr
= inbuf
+ 4 + SVAL(inbuf
,smb_vwv6
);
1278 static int readbraw_size
= 0xFFFF;
1281 memset(outbuf
,0,smb_size
);
1282 set_message(outbuf
,8,0,True
);
1283 CVAL(outbuf
,smb_com
) = SMBreadbraw
;
1284 SSVAL(outbuf
,smb_tid
,cnum
);
1285 cli_setup_pkt(outbuf
);
1286 SSVAL(outbuf
,smb_vwv0
,fnum
);
1287 SIVAL(outbuf
,smb_vwv1
,nread
);
1288 SSVAL(outbuf
,smb_vwv3
,MIN(finfo
.size
-nread
,readbraw_size
));
1289 SSVAL(outbuf
,smb_vwv4
,0);
1290 SIVALS(outbuf
,smb_vwv5
,-1);
1291 send_smb(Client
,outbuf
);
1293 /* Now read the raw data into the buffer and write it */
1294 if(read_smb_length(Client
,inbuf
,0) == -1) {
1295 DEBUG(0,("Failed to read length in readbraw\n"));
1299 /* Even though this is not an smb message, smb_len
1300 returns the generic length of an smb message */
1301 datalen
= smb_len(inbuf
);
1305 /* we got a readbraw error */
1306 DEBUG(4,("readbraw error - reducing size\n"));
1307 readbraw_size
= (readbraw_size
* 9) / 10;
1309 if (readbraw_size
< max_xmit
)
1311 DEBUG(0,("disabling readbraw\n"));
1312 readbraw_supported
= False
;
1319 if(read_data(Client
,inbuf
,datalen
) != datalen
) {
1320 DEBUG(0,("Failed to read data in readbraw\n"));
1328 /* we've already read some data with a chained readX */
1332 /* use plain read */
1333 memset(outbuf
,0,smb_size
);
1334 set_message(outbuf
,5,0,True
);
1335 CVAL(outbuf
,smb_com
) = SMBread
;
1336 SSVAL(outbuf
,smb_tid
,cnum
);
1337 cli_setup_pkt(outbuf
);
1339 SSVAL(outbuf
,smb_vwv0
,fnum
);
1340 SSVAL(outbuf
,smb_vwv1
,MIN(max_xmit
-200,finfo
.size
- nread
));
1341 SIVAL(outbuf
,smb_vwv2
,nread
);
1342 SSVAL(outbuf
,smb_vwv4
,finfo
.size
- nread
);
1344 send_smb(Client
,outbuf
);
1345 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1347 if (CVAL(inbuf
,smb_rcls
) != 0)
1349 DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf
)));
1353 datalen
= SVAL(inbuf
,smb_vwv0
);
1354 dataptr
= smb_buf(inbuf
) + 3;
1359 /* add received bits of file to buffer - dotarbuf will
1360 * write out in 512 byte intervals */
1361 if (dotarbuf(tarhandle
,dataptr
,datalen
) != datalen
)
1363 DEBUG(0,("Error writing to tar file - %s\n", strerror(errno
)));
1370 DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname
));
1378 /* pad tar file with zero's if we couldn't get entire file */
1379 if (nread
< finfo
.size
)
1381 DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo
.size
, nread
));
1382 if (padit(inbuf
, BUFFER_SIZE
, finfo
.size
- nread
))
1383 DEBUG(0,("Error writing tar file - %s\n", strerror(errno
)));
1386 /* round tar file to nearest block */
1387 if (finfo
.size
% TBLOCK
)
1388 dozerobuf(tarhandle
, TBLOCK
- (finfo
.size
% TBLOCK
));
1390 ttarf
+=finfo
.size
+ TBLOCK
- (finfo
.size
% TBLOCK
);
1396 memset(outbuf
,0,smb_size
);
1397 set_message(outbuf
,3,0,True
);
1398 CVAL(outbuf
,smb_com
) = SMBclose
;
1399 SSVAL(outbuf
,smb_tid
,cnum
);
1400 cli_setup_pkt(outbuf
);
1402 SSVAL(outbuf
,smb_vwv0
,fnum
);
1403 SIVALS(outbuf
,smb_vwv1
,-1);
1405 send_smb(Client
,outbuf
);
1406 client_receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
1408 if (!ignore_close_error
&& CVAL(inbuf
,smb_rcls
) != 0)
1410 DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf
)));
1411 free(inbuf
);free(outbuf
);
1418 struct timeval tp_end
;
1421 /* if shallitime is true then we didn't skip */
1422 if (tar_reset
&& !dry_run
)
1423 (void) do_setrattr(finfo
.name
, aARCH
, ATTRRESET
);
1425 GetTimeOfDay(&tp_end
);
1427 (tp_end
.tv_sec
- tp_start
.tv_sec
)*1000 +
1428 (tp_end
.tv_usec
- tp_start
.tv_usec
)/1000;
1429 get_total_time_ms
+= this_time
;
1430 get_total_size
+= finfo
.size
;
1434 DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
1435 finfo
.size
, finfo
.size
/ MAX(0.001, (1.024*this_time
)),
1439 /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
1440 DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
1441 finfo
.size
/ MAX(0.001, (1.024*this_time
)),
1442 get_total_size
/ MAX(0.001, (1.024*get_total_time_ms
))));
1445 free(inbuf
);free(outbuf
);
1448 /****************************************************************************
1449 Append single file to tar file (or not)
1450 ***************************************************************************/
1451 static void do_tar(file_info
*finfo
)
1455 if (strequal(finfo
->name
,".."))
1458 /* Is it on the exclude list ? */
1459 if (!tar_excl
&& clipn
) {
1462 DEBUG(5, ("Excl: strlen(cur_dir) = %i\n", strlen(cur_dir
)));
1464 safe_strcpy(exclaim
, cur_dir
, sizeof(pstring
));
1465 *(exclaim
+strlen(exclaim
)-1)='\0';
1467 safe_strcat(exclaim
, "\\", sizeof(pstring
));
1468 safe_strcat(exclaim
, finfo
->name
, sizeof(exclaim
));
1470 DEBUG(5, ("...tar_re_search: %d\n", tar_re_search
));
1472 if ((!tar_re_search
&& clipfind(cliplist
, clipn
, exclaim
)) ||
1474 (tar_re_search
&& !regexec(preg
, exclaim
, 0, NULL
, 0))) {
1476 (tar_re_search
&& mask_match(exclaim
, cliplist
[0], True
, False
))) {
1478 DEBUG(3,("Skipping file %s\n", exclaim
));
1483 if (finfo
->mode
& aDIR
)
1485 pstring saved_curdir
;
1487 char *inbuf
,*outbuf
;
1489 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1490 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1492 if (!inbuf
|| !outbuf
)
1494 DEBUG(0,("out of memory\n"));
1498 safe_strcpy(saved_curdir
, cur_dir
, sizeof(saved_curdir
));
1500 DEBUG(5, ("Sizeof(cur_dir)=%i, strlen(cur_dir)=%i, strlen(finfo->name)=%i\nname=%s,cur_dir=%s\n", sizeof(cur_dir
), strlen(cur_dir
), strlen(finfo
->name
), finfo
->name
, cur_dir
));
1502 safe_strcat(cur_dir
,finfo
->name
, sizeof(cur_dir
));
1503 safe_strcat(cur_dir
,"\\", sizeof(cur_dir
));
1505 DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir
));
1507 /* write a tar directory, don't bother with mode - just set it to
1509 writetarheader(tarhandle
, cur_dir
, 0, finfo
->mtime
, "040755 \0", '5');
1512 DEBUG(0, (" directory %s\n", cur_dir
));
1515 ntarf
++; /* Make sure we have a file on there */
1516 safe_strcpy(mtar_mask
,cur_dir
, sizeof(pstring
));
1517 safe_strcat(mtar_mask
,"*", sizeof(pstring
));
1518 /* do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
1519 safe_strcpy(cur_dir
,saved_curdir
, sizeof(pstring
));
1520 free(inbuf
);free(outbuf
);
1524 safe_strcpy(rname
,cur_dir
, sizeof(pstring
));
1525 safe_strcat(rname
,finfo
->name
, sizeof(pstring
));
1526 do_atar(rname
,finfo
->name
,finfo
);
1530 /****************************************************************************
1531 Convert from UNIX to DOS file names
1532 ***************************************************************************/
1533 static void unfixtarname(char *tptr
, char *fp
, int l
, BOOL first
)
1535 /* remove '.' from start of file name, convert from unix /'s to
1536 * dos \'s in path. Kill any absolute path names. But only if first!
1539 DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr
, (long)fp
, l
));
1546 if (*fp
== '\\' || *fp
== '/') {
1554 if(( skip
= skip_multibyte_char( *fp
)) != 0) {
1559 } else if (skip
== 1) {
1563 } else if (*fp
== '/') {
1574 #ifndef OLD_DOTARPUT
1576 /****************************************************************************
1577 Move to the next block in the buffer, which may mean read in another set of
1578 blocks. FIXME, we should allow more than one block to be skipped.
1579 ****************************************************************************/
1580 static int next_block(char *ltarbuf
, char **bufferp
, int bufsiz
)
1582 int bufread
, total
= 0;
1584 DEBUG(5, ("Advancing to next block: %0x\n", (unsigned int)*bufferp
));
1588 if (*bufferp
>= (ltarbuf
+ bufsiz
)) {
1590 DEBUG(5, ("Reading more data into ltarbuf ...\n"));
1594 for (bufread
= read(tarhandle
, ltarbuf
, bufsiz
); total
< bufsiz
; total
+= bufread
) {
1596 if (bufread
<= 0) { /* An error, return false */
1597 return (total
> 0 ? -2 : bufread
);
1602 DEBUG(5, ("Total bytes read ... %i\n", total
));
1612 /* Skip a file, even if it includes a long file name? */
1613 static int skip_file(int skipsize
)
1615 int dsize
= skipsize
;
1617 DEBUG(5, ("Skiping file. Size = %i\n", skipsize
));
1619 /* FIXME, we should skip more than one block at a time */
1623 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1625 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1637 /* We get a file from the tar file and store it */
1638 static int get_file(file_info2 finfo
, char * inbuf
, char * outbuf
)
1640 int fsize
= finfo
.size
;
1641 int fnum
, pos
= 0, dsize
= 0, rsize
= 0, bpos
= 0;
1643 DEBUG(5, ("get_file: file: %s, size %i\n", finfo
.name
, fsize
));
1645 if (ensurepath(finfo
.name
, inbuf
, outbuf
) &&
1646 !smbcreat(finfo
, &fnum
, inbuf
, outbuf
))
1648 DEBUG(0, ("abandoning restore\n"));
1652 /* read the blocks from the tar file and write to the remote file */
1654 rsize
= fsize
; /* This is how much to write */
1658 /* We can only write up to the end of the buffer */
1660 dsize
= MIN(tbufsiz
- (buffer_p
- tarbuf
) - bpos
, max_xmit
- 50); /* Calculate the size to write */
1661 dsize
= MIN(dsize
, rsize
); /* Should be only what is left */
1662 DEBUG(5, ("writing %i bytes, max_xmit = %i, bpos = %i ...\n", dsize
, max_xmit
, bpos
));
1664 if (!smbwrite(fnum
, dsize
, pos
, 0, fsize
- pos
, buffer_p
+ bpos
, inbuf
, outbuf
)) {
1666 DEBUG(0, ("Error writing remote file\n"));
1674 /* Now figure out how much to move in the buffer */
1676 /* FIXME, we should skip more than one block at a time */
1678 /* First, skip any initial part of the part written that is left over */
1679 /* from the end of the first TBLOCK */
1681 if ((bpos
) && ((bpos
+ dsize
) >= TBLOCK
)) {
1683 dsize
-= (TBLOCK
- bpos
); /* Get rid of the end of the first block */
1686 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) { /* and skip the block */
1687 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1694 while (dsize
>= TBLOCK
) {
1696 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1698 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1711 /* Now close the file ... */
1713 if (!smbshut(finfo
, fnum
, inbuf
, outbuf
)) {
1715 DEBUG(0, ("Error closing remote file\n"));
1720 /* Now we update the creation date ... */
1722 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
1724 if (!do_setrtime(finfo
.name
, finfo
.mtime
, True
)) {
1726 if (tar_real_noisy
) {
1727 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
1728 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1734 DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo
.name
, finfo
.size
));
1740 /* Create a directory. We just ensure that the path exists and return as there
1741 is no file associated with a directory
1743 static int get_dir(file_info2 finfo
, char * inbuf
, char * outbuf
)
1746 DEBUG(5, ("Creating directory: %s\n", finfo
.name
));
1748 if (!ensurepath(finfo
.name
, inbuf
, outbuf
)) {
1750 DEBUG(0, ("Problems creating directory\n"));
1757 /* Get a file with a long file name ... first file has file name, next file
1758 has the data. We only want the long file name, as the loop in do_tarput
1759 will deal with the rest.
1761 static char * get_longfilename(file_info2 finfo
)
1763 int namesize
= finfo
.size
+ strlen(cur_dir
) + 2;
1764 char *longname
= malloc(namesize
);
1765 int offset
= 0, left
= finfo
.size
;
1768 DEBUG(5, ("Restoring a long file name: %s\n", finfo
.name
));
1769 DEBUG(5, ("Len = %i\n", finfo
.size
));
1771 if (longname
== NULL
) {
1773 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1774 finfo
.size
+ strlen(cur_dir
) + 2));
1778 /* First, add cur_dir to the long file name */
1780 if (strlen(cur_dir
) > 0) {
1781 strncpy(longname
, cur_dir
, namesize
);
1782 offset
= strlen(cur_dir
);
1785 /* Loop through the blocks picking up the name */
1789 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1791 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1796 unfixtarname(longname
+ offset
, buffer_p
, MIN(TBLOCK
, finfo
.size
), first
--);
1797 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname
, buffer_p
));
1808 static void do_tarput(void)
1811 struct timeval tp_start
;
1812 char *inbuf
, *outbuf
, *longfilename
= NULL
, linkflag
;
1815 GetTimeOfDay(&tp_start
);
1817 DEBUG(5, ("RJS do_tarput called ...\n"));
1819 buffer_p
= tarbuf
+ tbufsiz
; /* init this to force first read */
1821 #if 0 /* Fix later ... */
1822 if (push_dir(&dir_stack
, &finfo
)) {
1825 finfo2
= pop_dir(&dir_stack
);
1826 inbuf
= top_dir_name(&dir_stack
); /* FIXME */
1827 if (sub_dir(inbuf
, finfo2
-> name
)){
1835 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1836 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1838 if (!inbuf
|| !outbuf
) {
1840 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1845 /* Now read through those files ... */
1849 /* Get us to the next block, or the first block first time around */
1851 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) {
1853 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno
)));
1859 DEBUG(5, ("Reading the next header ...\n"));
1861 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
)) {
1863 case -2: /* Hmm, not good, but not fatal */
1864 DEBUG(0, ("Skipping %s...\n", finfo
.name
));
1865 if ((next_block(tarbuf
, &buffer_p
, tbufsiz
) <= 0) &&
1866 !skip_file(finfo
.size
)) {
1868 DEBUG(0, ("Short file, bailing out...\n"));
1869 free(inbuf
); free(outbuf
);
1877 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1878 free(inbuf
); free(outbuf
);
1881 case 0: /* chksum is zero - looks like an EOF */
1882 DEBUG(0, ("total of %d tar files restored to share\n", ntarf
));
1883 free(inbuf
); free(outbuf
);
1884 return; /* Hmmm, bad here ... */
1893 /* Now, do we have a long file name? */
1895 if (longfilename
!= NULL
) {
1897 free(finfo
.name
); /* Free the space already allocated */
1898 finfo
.name
= longfilename
;
1899 longfilename
= NULL
;
1903 /* Well, now we have a header, process the file ... */
1905 /* Should we skip the file? We have the long name as well here */
1908 ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
)
1910 || (tar_re_search
&& !regexec(preg
, finfo
.name
, 0, NULL
, 0)));
1912 || (tar_re_search
&& mask_match(finfo
.name
, cliplist
[0], True
, False
)));
1915 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip
, (cliplist
?cliplist
[0]:NULL
), finfo
.name
));
1919 skip_file(finfo
.size
);
1924 /* We only get this far if we should process the file */
1925 linkflag
= ((union hblock
*)buffer_p
) -> dbuf
.linkflag
;
1929 case '0': /* Should use symbolic names--FIXME */
1931 /* Skip to the next block first, so we can get the file, FIXME, should
1932 be in get_file ... */
1934 if (next_block(tarbuf
, &buffer_p
, tbufsiz
) <=0) {
1935 DEBUG(0, ("Short file, bailing out...\n"));
1936 free(inbuf
); free(outbuf
);
1939 if (!get_file(finfo
, inbuf
, outbuf
)) {
1941 free(inbuf
); free(outbuf
);
1942 DEBUG(0, ("Abandoning restore\n"));
1949 if (!get_dir(finfo
, inbuf
, outbuf
)) {
1950 free(inbuf
); free(outbuf
);
1951 DEBUG(0, ("Abandoning restore \n"));
1957 longfilename
= get_longfilename(finfo
);
1958 if (!longfilename
) {
1959 free(inbuf
); free(outbuf
);
1960 DEBUG(0, ("abandoning restore\n"));
1964 DEBUG(5, ("Long file name: %s\n", longfilename
));
1968 skip_file(finfo
.size
); /* Don't handle these yet */
1980 static void do_tarput()
1983 int nread
=0, bufread
;
1984 char *inbuf
,*outbuf
, *longname
= NULL
;
1987 struct timeval tp_start
;
1988 BOOL tskip
=False
; /* We'll take each file as it comes */
1990 finfo
.name
= NULL
; /* No name in here ... */
1992 GetTimeOfDay(&tp_start
);
1994 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1995 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
1997 if (!inbuf
|| !outbuf
)
1999 DEBUG(0,("out of memory\n"));
2004 * Must read in tbufsiz dollops
2007 /* These should be the only reads in clitar.c */
2008 while ((bufread
=read(tarhandle
, tarbuf
, tbufsiz
))>0) {
2012 /* Code to handle a short read.
2013 * We always need a TBLOCK full of stuff
2015 if (bufread
% TBLOCK
) {
2016 int lchunk
=TBLOCK
-(bufread
% TBLOCK
);
2019 /* It's a shorty - a short read that is */
2020 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread
, lchunk
));
2022 while ((lread
=read(tarhandle
, tarbuf
+bufread
, lchunk
))>0) {
2024 if (!(lchunk
-=lread
)) break;
2027 /* If we've reached EOF then that must be a short file */
2028 if (lread
<=0) break;
2032 endofbuffer
=tarbuf
+bufread
;
2035 if (fsize
<bufread
) {
2040 if (fsize
==bufread
) tskip
=False
;
2049 int next_header
= 1; /* Want at least one header */
2052 if (buffer_p
>= endofbuffer
) {
2054 bufread
= read(tarhandle
, tarbuf
, tbufsiz
);
2058 next_header
= 0; /* Don't want the next one ... */
2060 if (finfo
.name
!= NULL
) { /* Free the space */
2066 DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n",
2067 (int)tarbuf
, (int)buffer_p
, (int)endofbuffer
));
2068 switch (readtarheader((union hblock
*) buffer_p
, &finfo
, cur_dir
))
2070 case -2: /* something dodgy but not fatal about this */
2071 DEBUG(0, ("skipping %s...\n", finfo
.name
));
2072 buffer_p
+=TBLOCK
; /* header - like a link */
2075 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
2076 free(inbuf
); free(outbuf
);
2078 case 0: /* chksum is zero - we assume that one all zero
2079 *header block will do for eof */
2081 ("total of %d tar files restored to share\n", ntarf
));
2082 free(inbuf
); free(outbuf
);
2088 /* If we have a longname left from the last time through,
2089 copy it into finfo.name and free it.
2091 The size of a pstring is the limiting factor on filenames
2092 and directory names now. The total pathname length must be
2093 less than sizeof(pstring) - 1, which is currently 1023. */
2095 if (longname
!= NULL
) {
2097 free(finfo
.name
); /* Free the name in the finfo */
2098 finfo
.name
= string_create_s(strlen(longname
) + 2);
2099 strncpy(finfo
.name
, longname
, strlen(longname
) + 1);
2100 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname
, finfo
.name
));
2106 /* Check if a long-link. We do this before the clip checking
2107 because clip-checking should clip on real name - RJS */
2109 if (((union hblock
*)buffer_p
) -> dbuf
.linkflag
== 'L') {
2110 int file_len
, first
= 0; char *cp
;
2112 /* Skip this header, but pick up length, get the name and
2113 fix the name and skip the name. Hmmm, what about end of
2116 longname
= malloc(finfo
.size
+ strlen(cur_dir
) + 1);
2117 if (longname
== NULL
) {
2119 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
2120 finfo
.size
+ strlen(cur_dir
) + 1)
2122 free(inbuf
); free(outbuf
);
2127 bzero(longname
, finfo
.size
+ strlen(cur_dir
) +1);
2129 buffer_p
+= TBLOCK
; /* Skip that longlink header */
2131 /* This needs restructuring ... */
2133 safe_strcpy(longname
, cur_dir
, strlen(cur_dir
) + 1);
2134 cp
= longname
+ strlen(cur_dir
);
2135 file_len
= finfo
.size
;
2137 DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n",
2138 (int)longname
, (int)cp
, file_len
));
2140 while (file_len
> 0) {
2142 if (buffer_p
>= endofbuffer
) {
2144 bufread
= read(tarhandle
, tarbuf
, tbufsiz
);
2150 unfixtarname(cp
, buffer_p
, file_len
>= TBLOCK
?TBLOCK
:file_len
, first
== 0);
2152 first
++; /* Not the first anymore */
2153 cp
= cp
+ strlen(cp
); /* Move to end of string */
2156 DEBUG(5, ("cp=%0X, file_len=%i\n", (int)cp
, file_len
));
2157 next_header
= 1; /* Force read of next header */
2163 && ((!tar_re_search
&& clipfind(cliplist
, clipn
, finfo
.name
) ^ tar_excl
)
2165 || (tar_re_search
&& !regexec(preg
, finfo
.name
, 0, NULL
, 0)));
2167 || (tar_re_search
&& mask_match(finfo
.name
, cliplist
[0], True
, False
)));
2171 if (finfo
.mode
& aDIR
)
2173 else if ((fsize
=finfo
.size
) % TBLOCK
) {
2174 fsize
+=TBLOCK
-(fsize
%TBLOCK
);
2176 if (fsize
<endofbuffer
-buffer_p
) {
2181 fsize
-=endofbuffer
-buffer_p
;
2186 DEBUG(5, ("do_tarput: File is: %s\n", finfo
.name
));
2188 if (finfo
.mode
& aDIR
)
2191 DEBUG(5, ("Creating directory: %s\n", finfo
.name
));
2192 DEBUG(0, ("restore tar dir %s of size %d bytes\n",
2193 finfo
.name
, finfo
.size
));
2195 if (!ensurepath(finfo
.name
, inbuf
, outbuf
))
2197 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
2198 free(inbuf
); free(outbuf
);
2203 /* Now we update the creation date ... */
2205 DEBUG(5, ("Updating creation date on %s\n", finfo
.name
));
2207 if (!do_setrtime(finfo
.name
, finfo
.mtime
, True
)) {
2209 if (tar_real_noisy
) {
2210 DEBUG(0, ("Could not set time on file: %s\n", finfo
.name
));
2212 /*return; - Win 95 does not like setting time on dirs */
2224 if (ensurepath(finfo
.name
, inbuf
, outbuf
)
2225 && !smbcreat(finfo
, &fnum
, inbuf
, outbuf
))
2227 DEBUG(0, ("abandoning restore\n"));
2228 free(inbuf
);free(outbuf
);
2232 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
2233 finfo
.name
, finfo
.size
));
2235 /* if (!finfo.size) {
2236 if (!smbshut(finfo, fnum, inbuf, outbuf)){
2237 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
2238 free(inbuf);free(outbuf);
2244 if ((buffer_p
+=TBLOCK
) >= endofbuffer
) break;
2247 /* write out the file in chunk sized chunks - don't
2248 * go past end of buffer though */
2249 chunk
=(fsize
-nread
< endofbuffer
- buffer_p
)
2250 ? fsize
- nread
: endofbuffer
- buffer_p
;
2253 int minichunk
=MIN(chunk
, max_xmit
-200);
2255 if (!smbwrite(fnum
, /* file descriptor */
2257 nread
, /* offset low */
2258 0, /* offset high - not implemented */
2259 fsize
-nread
, /* left - only hint to server */
2264 DEBUG(0, ("Error writing remote file\n"));
2265 free(inbuf
); free(outbuf
);
2268 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo
.name
, fnum
, nread
, minichunk
, chunk
, fsize
));
2270 buffer_p
+=minichunk
; nread
+=minichunk
;
2276 if (!smbshut(finfo
, fnum
, inbuf
, outbuf
))
2278 DEBUG(0, ("Error closing remote file\n"));
2279 free(inbuf
);free(outbuf
);
2282 if (fsize
% TBLOCK
) buffer_p
+=TBLOCK
- (fsize
% TBLOCK
);
2283 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
2284 (int) buffer_p
, (int)(buffer_p
- tarbuf
)));
2289 } while (buffer_p
< endofbuffer
);
2292 DEBUG(0, ("premature eof on tar file ?\n"));
2293 DEBUG(0,("total of %d tar files restored to share\n", ntarf
));
2295 free(inbuf
); free(outbuf
);
2300 * samba interactive commands
2303 /****************************************************************************
2305 ***************************************************************************/
2306 void cmd_block(char *dum_in
, char *dum_out
)
2311 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2313 DEBUG(0, ("blocksize <n>\n"));
2318 if (block
< 0 || block
> 65535)
2320 DEBUG(0, ("blocksize out of range"));
2325 DEBUG(2,("blocksize is now %d\n", blocksize
));
2328 /****************************************************************************
2329 command to set incremental / reset mode
2330 ***************************************************************************/
2331 void cmd_tarmode(char *dum_in
, char *dum_out
)
2335 while (next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
2336 if (strequal(buf
, "full"))
2338 else if (strequal(buf
, "inc"))
2340 else if (strequal(buf
, "reset"))
2342 else if (strequal(buf
, "noreset"))
2344 else if (strequal(buf
, "system"))
2346 else if (strequal(buf
, "nosystem"))
2348 else if (strequal(buf
, "hidden"))
2350 else if (strequal(buf
, "nohidden"))
2352 else if (strequal(buf
, "verbose") || strequal(buf
, "noquiet"))
2354 else if (strequal(buf
, "quiet") || strequal(buf
, "noverbose"))
2356 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf
));
2359 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2360 tar_inc
? "incremental" : "full",
2361 tar_system
? "system" : "nosystem",
2362 tar_hidden
? "hidden" : "nohidden",
2363 tar_reset
? "reset" : "noreset",
2364 tar_noisy
? "verbose" : "quiet"));
2368 /****************************************************************************
2369 Feeble attrib command
2370 ***************************************************************************/
2371 void cmd_setmode(char *dum_in
, char *dum_out
)
2379 attra
[0] = attra
[1] = 0;
2381 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2383 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2387 safe_strcpy(fname
, cur_dir
, sizeof(pstring
));
2388 safe_strcat(fname
, buf
, sizeof(pstring
));
2390 while (next_token(NULL
,buf
,NULL
,sizeof(buf
))) {
2399 case 'r': attra
[direct
]|=aRONLY
;
2401 case 'h': attra
[direct
]|=aHIDDEN
;
2403 case 's': attra
[direct
]|=aSYSTEM
;
2405 case 'a': attra
[direct
]|=aARCH
;
2407 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2412 if (attra
[ATTRSET
]==0 && attra
[ATTRRESET
]==0)
2414 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2418 DEBUG(2, ("\nperm set %d %d\n", attra
[ATTRSET
], attra
[ATTRRESET
]));
2419 (void) do_setrattr(fname
, attra
[ATTRSET
], ATTRSET
);
2420 (void) do_setrattr(fname
, attra
[ATTRRESET
], ATTRRESET
);
2423 /****************************************************************************
2424 Principal command for creating / extracting
2425 ***************************************************************************/
2426 void cmd_tar(char *inbuf
, char *outbuf
)
2432 if (!next_token(NULL
,buf
,NULL
,sizeof(buf
)))
2434 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
2438 argl
=toktocliplist(&argcl
, NULL
);
2439 if (!tar_parseargs(argcl
, argl
, buf
, 0))
2442 process_tar(inbuf
, outbuf
);
2447 /****************************************************************************
2448 Command line (option) version
2449 ***************************************************************************/
2450 int process_tar(char *inbuf
, char *outbuf
)
2466 if (clipn
&& tar_excl
) {
2470 for (i
=0; i
<clipn
; i
++) {
2471 DEBUG(5,("arg %d = %s\n", i
, cliplist
[i
]));
2473 if (*(cliplist
[i
]+strlen(cliplist
[i
])-1)=='\\') {
2474 *(cliplist
[i
]+strlen(cliplist
[i
])-1)='\0';
2477 if (strrchr(cliplist
[i
], '\\')) {
2480 safe_strcpy(saved_dir
, cur_dir
, sizeof(pstring
));
2482 if (*cliplist
[i
]=='\\') {
2483 safe_strcpy(tarmac
, cliplist
[i
], sizeof(pstring
));
2485 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
2486 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
2488 safe_strcpy(cur_dir
, tarmac
, sizeof(pstring
));
2489 *(strrchr(cur_dir
, '\\')+1)='\0';
2491 do_dir((char *)inbuf
,(char *)outbuf
,tarmac
,attribute
,do_tar
,recurse
, True
);
2492 safe_strcpy(cur_dir
,saved_dir
, sizeof(pstring
));
2494 safe_strcpy(tarmac
, cur_dir
, sizeof(pstring
));
2495 safe_strcat(tarmac
, cliplist
[i
], sizeof(pstring
));
2496 do_dir((char *)inbuf
,(char *)outbuf
,tarmac
,attribute
,do_tar
,recurse
, True
);
2501 safe_strcpy(mask
,cur_dir
, sizeof(pstring
));
2502 safe_strcat(mask
,"\\*", sizeof(pstring
));
2503 do_dir((char *)inbuf
,(char *)outbuf
,mask
,attribute
,do_tar
,recurse
, True
);
2506 if (ntarf
) dotareof(tarhandle
);
2510 DEBUG(0, ("tar: dumped %d tar files\n", ntarf
));
2511 DEBUG(0, ("Total bytes written: %d\n", ttarf
));
2515 if (must_free_cliplist
) {
2517 for (i
= 0; i
< clipn
; ++i
) {
2523 must_free_cliplist
= False
;
2529 /****************************************************************************
2530 Find a token (filename) in a clip list
2531 ***************************************************************************/
2532 static int clipfind(char **aret
, int ret
, char *tok
)
2534 if (aret
==NULL
) return 0;
2536 /* ignore leading slashes or dots in token */
2537 while(strchr("/\\.", *tok
)) tok
++;
2542 /* ignore leading slashes or dots in list */
2543 while(strchr("/\\.", *pkey
)) pkey
++;
2545 if (!strslashcmp(pkey
, tok
)) return 1;
2551 /****************************************************************************
2552 Read list of files to include from the file and initialize cliplist
2554 ***************************************************************************/
2555 static int read_inclusion_file(char *filename
)
2557 FILE *inclusion
= NULL
;
2558 char buf
[MAXPATHLEN
+ 1];
2559 char *inclusion_buffer
= NULL
;
2560 int inclusion_buffer_size
= 0;
2561 int inclusion_buffer_sofar
= 0;
2568 buf
[MAXPATHLEN
] = '\0'; /* guarantee null-termination */
2569 if ((inclusion
= fopen(filename
, "r")) == NULL
) {
2570 /* XXX It would be better to include a reason for failure, but without
2571 * autoconf, it's hard to use strerror, sys_errlist, etc.
2573 DEBUG(0,("Unable to open inclusion file %s\n", filename
));
2577 while ((! error
) && (fgets(buf
, sizeof(buf
)-1, inclusion
))) {
2578 if (inclusion_buffer
== NULL
) {
2579 inclusion_buffer_size
= 1024;
2580 if ((inclusion_buffer
= malloc(inclusion_buffer_size
)) == NULL
) {
2581 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
2587 if (buf
[strlen(buf
)-1] == '\n') {
2588 buf
[strlen(buf
)-1] = '\0';
2591 if ((strlen(buf
) + 1 + inclusion_buffer_sofar
) >= inclusion_buffer_size
) {
2592 inclusion_buffer_size
*= 2;
2593 inclusion_buffer
= Realloc(inclusion_buffer
,inclusion_buffer_size
);
2594 if (! inclusion_buffer
) {
2595 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
2596 inclusion_buffer_size
));
2602 safe_strcpy(inclusion_buffer
+ inclusion_buffer_sofar
, buf
, inclusion_buffer_size
- inclusion_buffer_sofar
);
2603 inclusion_buffer_sofar
+= strlen(buf
) + 1;
2609 /* Allocate an array of clipn + 1 char*'s for cliplist */
2610 cliplist
= malloc((clipn
+ 1) * sizeof(char *));
2611 if (cliplist
== NULL
) {
2612 DEBUG(0,("failure allocating memory for cliplist\n"));
2615 cliplist
[clipn
] = NULL
;
2616 p
= inclusion_buffer
;
2617 for (i
= 0; (! error
) && (i
< clipn
); i
++) {
2618 /* set current item to NULL so array will be null-terminated even if
2619 * malloc fails below. */
2621 if ((tmpstr
= (char *)malloc(strlen(p
)+1)) == NULL
) {
2622 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i
));
2625 unfixtarname(tmpstr
, p
, strlen(p
) + 1, True
);
2626 cliplist
[i
] = tmpstr
;
2627 if ((p
= strchr(p
, '\000')) == NULL
) {
2628 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
2634 must_free_cliplist
= True
;
2638 if (inclusion_buffer
) {
2639 free(inclusion_buffer
);
2644 /* We know cliplist is always null-terminated */
2645 for (pp
= cliplist
; *pp
; ++pp
) {
2650 must_free_cliplist
= False
;
2655 /* cliplist and its elements are freed at the end of process_tar. */
2659 /****************************************************************************
2660 Parse tar arguments. Sets tar_type, tar_excl, etc.
2661 ***************************************************************************/
2662 int tar_parseargs(int argc
, char *argv
[], char *Optarg
, int Optind
)
2664 char tar_clipfl
='\0';
2666 /* Reset back to defaults - could be from interactive version
2667 * reset mode and archive mode left as they are though
2679 if (tar_type
=='c') {
2680 printf("Tar must be followed by only one of c or x.\n");
2686 if (Optind
>=argc
|| !(blocksize
=atoi(argv
[Optind
]))) {
2687 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2698 DEBUG(0,("Option N must be followed by valid file name\n"));
2701 SMB_STRUCT_STAT stbuf
;
2702 extern time_t newer_than
;
2704 if (dos_stat(argv
[Optind
], &stbuf
) == 0) {
2705 newer_than
= stbuf
.st_mtime
;
2706 DEBUG(1,("Getting files newer than %s",
2707 asctime(LocalTime(&newer_than
))));
2710 DEBUG(0,("Error setting newer-than time\n"));
2723 DEBUG(0,("Only one of I,X,F must be specified\n"));
2730 DEBUG(0,("Only one of I,X,F must be specified\n"));
2737 DEBUG(0,("Only one of I,X,F must be specified\n"));
2743 DEBUG(0, ("tar_re_search set\n"));
2744 tar_re_search
= True
;
2747 if (tar_type
== 'c') {
2748 DEBUG(0, ("dry_run set\n"));
2751 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
2756 DEBUG(0,("Unknown tar option\n"));
2761 printf("Option T must be followed by one of c or x.\n");
2765 /* tar_excl is true if cliplist lists files to be included.
2766 * Both 'I' and 'F' mean include. */
2767 tar_excl
=tar_clipfl
!='X';
2769 if (tar_clipfl
=='F') {
2770 if (argc
-Optind
-1 != 1) {
2771 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
2774 if (! read_inclusion_file(argv
[Optind
+1])) {
2777 } else if (Optind
+1<argc
&& !tar_re_search
) { /* For backwards compatibility */
2782 cliplist
=argv
+Optind
+1;
2783 clipn
=argc
-Optind
-1;
2786 if ((tmplist
=malloc(clipn
*sizeof(char *))) == NULL
) {
2787 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2793 for (clipcount
= 0; clipcount
< clipn
; clipcount
++) {
2795 DEBUG(5, ("Processing an item, %s\n", cliplist
[clipcount
]));
2797 if ((tmpstr
= (char *)malloc(strlen(cliplist
[clipcount
])+1)) == NULL
) {
2798 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2803 unfixtarname(tmpstr
, cliplist
[clipcount
], strlen(cliplist
[clipcount
]) + 1, True
);
2804 tmplist
[clipcount
] = tmpstr
;
2805 DEBUG(5, ("Processed an item, %s\n", tmpstr
));
2807 DEBUG(5, ("Cliplist is: %s\n", cliplist
[0]));
2810 must_free_cliplist
= True
;
2813 if (Optind
+1<argc
&& tar_re_search
) { /* Doing regular expression seaches */
2817 if ((preg
= (regex_t
*)malloc(65536)) == NULL
) {
2819 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2824 if (errcode
= regcomp(preg
, argv
[Optind
+ 1], REG_EXTENDED
)) {
2828 errlen
= regerror(errcode
, preg
, errstr
, sizeof(errstr
) - 1);
2830 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv
[Optind
+ 1], errstr
));
2836 clipn
=argc
-Optind
-1;
2837 cliplist
=argv
+Optind
+1;
2841 if (Optind
>=argc
|| !strcmp(argv
[Optind
], "-")) {
2842 /* Sets tar handle to either 0 or 1, as appropriate */
2843 tarhandle
=(tar_type
=='c');
2845 if (tar_type
=='c' && (dry_run
|| strcmp(argv
[Optind
], "/dev/null")==0))
2848 DEBUG(0,("Output is /dev/null, assuming dry_run"));
2853 if ((tar_type
=='x' && (tarhandle
= open(argv
[Optind
], O_RDONLY
)) == -1)
2854 || (tar_type
=='c' && (tarhandle
=creat(argv
[Optind
], 0644)) < 0))
2856 DEBUG(0,("Error opening local file %s - %s\n",
2857 argv
[Optind
], strerror(errno
)));