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=True;
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()
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 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
1727 /*return(False); */ /* Ignore, as Win95 does not allow changes */
1733 DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo.name, finfo.size));
1739 /* Create a directory. We just ensure that the path exists and return as there
1740 is no file associated with a directory
1742 static int get_dir(file_info2 finfo, char * inbuf, char * outbuf)
1745 DEBUG(5, ("Creating directory: %s\n", finfo.name));
1747 if (!ensurepath(finfo.name, inbuf, outbuf)) {
1749 DEBUG(0, ("Problems creating directory\n"));
1756 /* Get a file with a long file name ... first file has file name, next file
1757 has the data. We only want the long file name, as the loop in do_tarput
1758 will deal with the rest.
1760 static char * get_longfilename(file_info2 finfo)
1762 int namesize = finfo.size + strlen(cur_dir) + 2;
1763 char *longname = malloc(namesize);
1764 int offset = 0, left = finfo.size;
1767 DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
1768 DEBUG(5, ("Len = %i\n", finfo.size));
1770 if (longname == NULL) {
1772 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
1773 finfo.size + strlen(cur_dir) + 2));
1777 /* First, add cur_dir to the long file name */
1779 if (strlen(cur_dir) > 0) {
1780 strncpy(longname, cur_dir, namesize);
1781 offset = strlen(cur_dir);
1784 /* Loop through the blocks picking up the name */
1788 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1790 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1795 unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
1796 DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
1807 static void do_tarput(void)
1810 struct timeval tp_start;
1811 char *inbuf, *outbuf, *longfilename = NULL, linkflag;
1814 GetTimeOfDay(&tp_start);
1816 DEBUG(5, ("RJS do_tarput called ...\n"));
1818 buffer_p = tarbuf + tbufsiz; /* init this to force first read */
1820 #if 0 /* Fix later ... */
1821 if (push_dir(&dir_stack, &finfo)) {
1824 finfo2 = pop_dir(&dir_stack);
1825 inbuf = top_dir_name(&dir_stack); /* FIXME */
1826 if (sub_dir(inbuf, finfo2 -> name)){
1834 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1835 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1837 if (!inbuf || !outbuf) {
1839 DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
1844 /* Now read through those files ... */
1848 /* Get us to the next block, or the first block first time around */
1850 if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
1852 DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
1858 DEBUG(5, ("Reading the next header ...\n"));
1860 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir)) {
1862 case -2: /* Hmm, not good, but not fatal */
1863 DEBUG(0, ("Skipping %s...\n", finfo.name));
1864 if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) &&
1865 !skip_file(finfo.size)) {
1867 DEBUG(0, ("Short file, bailing out...\n"));
1868 free(inbuf); free(outbuf);
1876 DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
1877 free(inbuf); free(outbuf);
1880 case 0: /* chksum is zero - looks like an EOF */
1881 DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
1882 free(inbuf); free(outbuf);
1883 return; /* Hmmm, bad here ... */
1892 /* Now, do we have a long file name? */
1894 if (longfilename != NULL) {
1896 free(finfo.name); /* Free the space already allocated */
1897 finfo.name = longfilename;
1898 longfilename = NULL;
1902 /* Well, now we have a header, process the file ... */
1904 /* Should we skip the file? We have the long name as well here */
1907 ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
1909 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
1911 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
1914 DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
1918 skip_file(finfo.size);
1923 /* We only get this far if we should process the file */
1924 linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag;
1928 case '0': /* Should use symbolic names--FIXME */
1930 /* Skip to the next block first, so we can get the file, FIXME, should
1931 be in get_file ... */
1933 if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
1934 DEBUG(0, ("Short file, bailing out...\n"));
1935 free(inbuf); free(outbuf);
1938 if (!get_file(finfo, inbuf, outbuf)) {
1940 free(inbuf); free(outbuf);
1941 DEBUG(0, ("Abandoning restore\n"));
1948 if (!get_dir(finfo, inbuf, outbuf)) {
1949 free(inbuf); free(outbuf);
1950 DEBUG(0, ("Abandoning restore \n"));
1956 longfilename = get_longfilename(finfo);
1957 if (!longfilename) {
1958 free(inbuf); free(outbuf);
1959 DEBUG(0, ("abandoning restore\n"));
1963 DEBUG(5, ("Long file name: %s\n", longfilename));
1967 skip_file(finfo.size); /* Don't handle these yet */
1979 static void do_tarput()
1982 int nread=0, bufread;
1983 char *inbuf,*outbuf, *longname = NULL;
1986 struct timeval tp_start;
1987 BOOL tskip=False; /* We'll take each file as it comes */
1989 finfo.name = NULL; /* No name in here ... */
1991 GetTimeOfDay(&tp_start);
1993 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1994 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1996 if (!inbuf || !outbuf)
1998 DEBUG(0,("out of memory\n"));
2003 * Must read in tbufsiz dollops
2006 /* These should be the only reads in clitar.c */
2007 while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
2011 /* Code to handle a short read.
2012 * We always need a TBLOCK full of stuff
2014 if (bufread % TBLOCK) {
2015 int lchunk=TBLOCK-(bufread % TBLOCK);
2018 /* It's a shorty - a short read that is */
2019 DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
2021 while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
2023 if (!(lchunk-=lread)) break;
2026 /* If we've reached EOF then that must be a short file */
2027 if (lread<=0) break;
2031 endofbuffer=tarbuf+bufread;
2034 if (fsize<bufread) {
2039 if (fsize==bufread) tskip=False;
2048 int next_header = 1; /* Want at least one header */
2051 if (buffer_p >= endofbuffer) {
2053 bufread = read(tarhandle, tarbuf, tbufsiz);
2057 next_header = 0; /* Don't want the next one ... */
2059 if (finfo.name != NULL) { /* Free the space */
2065 DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n",
2066 (int)tarbuf, (int)buffer_p, (int)endofbuffer));
2067 switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
2069 case -2: /* something dodgy but not fatal about this */
2070 DEBUG(0, ("skipping %s...\n", finfo.name));
2071 buffer_p+=TBLOCK; /* header - like a link */
2074 DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
2075 free(inbuf); free(outbuf);
2077 case 0: /* chksum is zero - we assume that one all zero
2078 *header block will do for eof */
2080 ("total of %d tar files restored to share\n", ntarf));
2081 free(inbuf); free(outbuf);
2087 /* If we have a longname left from the last time through,
2088 copy it into finfo.name and free it.
2090 The size of a pstring is the limiting factor on filenames
2091 and directory names now. The total pathname length must be
2092 less than sizeof(pstring) - 1, which is currently 1023. */
2094 if (longname != NULL) {
2096 free(finfo.name); /* Free the name in the finfo */
2097 finfo.name = string_create_s(strlen(longname) + 2);
2098 strncpy(finfo.name, longname, strlen(longname) + 1);
2099 DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
2105 /* Check if a long-link. We do this before the clip checking
2106 because clip-checking should clip on real name - RJS */
2108 if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
2109 int file_len, first = 0; char *cp;
2111 /* Skip this header, but pick up length, get the name and
2112 fix the name and skip the name. Hmmm, what about end of
2115 longname = malloc(finfo.size + strlen(cur_dir) + 1);
2116 if (longname == NULL) {
2118 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
2119 finfo.size + strlen(cur_dir) + 1)
2121 free(inbuf); free(outbuf);
2126 bzero(longname, finfo.size + strlen(cur_dir) +1);
2128 buffer_p += TBLOCK; /* Skip that longlink header */
2130 /* This needs restructuring ... */
2132 safe_strcpy(longname, cur_dir, strlen(cur_dir) + 1);
2133 cp = longname + strlen(cur_dir);
2134 file_len = finfo.size;
2136 DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n",
2137 (int)longname, (int)cp, file_len));
2139 while (file_len > 0) {
2141 if (buffer_p >= endofbuffer) {
2143 bufread = read(tarhandle, tarbuf, tbufsiz);
2149 unfixtarname(cp, buffer_p, file_len >= TBLOCK?TBLOCK:file_len, first == 0);
2151 first++; /* Not the first anymore */
2152 cp = cp + strlen(cp); /* Move to end of string */
2155 DEBUG(5, ("cp=%0X, file_len=%i\n", (int)cp, file_len));
2156 next_header = 1; /* Force read of next header */
2162 && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
2164 || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
2166 || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
2170 if (finfo.mode & aDIR)
2172 else if ((fsize=finfo.size) % TBLOCK) {
2173 fsize+=TBLOCK-(fsize%TBLOCK);
2175 if (fsize<endofbuffer-buffer_p) {
2180 fsize-=endofbuffer-buffer_p;
2185 DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
2187 if (finfo.mode & aDIR)
2190 DEBUG(5, ("Creating directory: %s\n", finfo.name));
2191 DEBUG(0, ("restore tar dir %s of size %d bytes\n",
2192 finfo.name, finfo.size));
2194 if (!ensurepath(finfo.name, inbuf, outbuf))
2196 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
2197 free(inbuf); free(outbuf);
2202 /* Now we update the creation date ... */
2204 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
2206 if (!do_setrtime(finfo.name, finfo.mtime, True)) {
2208 if (tar_real_noisy) {
2209 DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
2211 /*return; - Win 95 does not like setting time on dirs */
2223 if (ensurepath(finfo.name, inbuf, outbuf)
2224 && !smbcreat(finfo, &fnum, inbuf, outbuf))
2226 DEBUG(0, ("abandoning restore\n"));
2227 free(inbuf);free(outbuf);
2231 DEBUG(0 ,("restore tar file %s of size %d bytes\n",
2232 finfo.name, finfo.size));
2234 /* if (!finfo.size) {
2235 if (!smbshut(finfo, fnum, inbuf, outbuf)){
2236 DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
2237 free(inbuf);free(outbuf);
2243 if ((buffer_p+=TBLOCK) >= endofbuffer) break;
2246 /* write out the file in chunk sized chunks - don't
2247 * go past end of buffer though */
2248 chunk=(fsize-nread < endofbuffer - buffer_p)
2249 ? fsize - nread : endofbuffer - buffer_p;
2252 int minichunk=MIN(chunk, max_xmit-200);
2254 if (!smbwrite(fnum, /* file descriptor */
2256 nread, /* offset low */
2257 0, /* offset high - not implemented */
2258 fsize-nread, /* left - only hint to server */
2263 DEBUG(0, ("Error writing remote file\n"));
2264 free(inbuf); free(outbuf);
2267 DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
2269 buffer_p+=minichunk; nread+=minichunk;
2275 if (!smbshut(finfo, fnum, inbuf, outbuf))
2277 DEBUG(0, ("Error closing remote file\n"));
2278 free(inbuf);free(outbuf);
2281 if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
2282 DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
2283 (int) buffer_p, (int)(buffer_p - tarbuf)));
2288 } while (buffer_p < endofbuffer);
2291 DEBUG(0, ("premature eof on tar file ?\n"));
2292 DEBUG(0,("total of %d tar files restored to share\n", ntarf));
2294 free(inbuf); free(outbuf);
2299 * samba interactive commands
2302 /****************************************************************************
2304 ***************************************************************************/
2305 void cmd_block(char *dum_in, char *dum_out)
2310 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2312 DEBUG(0, ("blocksize <n>\n"));
2317 if (block < 0 || block > 65535)
2319 DEBUG(0, ("blocksize out of range"));
2324 DEBUG(2,("blocksize is now %d\n", blocksize));
2327 /****************************************************************************
2328 command to set incremental / reset mode
2329 ***************************************************************************/
2330 void cmd_tarmode(char *dum_in, char *dum_out)
2334 while (next_token(NULL,buf,NULL,sizeof(buf))) {
2335 if (strequal(buf, "full"))
2337 else if (strequal(buf, "inc"))
2339 else if (strequal(buf, "reset"))
2341 else if (strequal(buf, "noreset"))
2343 else if (strequal(buf, "system"))
2345 else if (strequal(buf, "nosystem"))
2347 else if (strequal(buf, "hidden"))
2349 else if (strequal(buf, "nohidden"))
2351 else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
2353 else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
2355 else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
2358 DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
2359 tar_inc ? "incremental" : "full",
2360 tar_system ? "system" : "nosystem",
2361 tar_hidden ? "hidden" : "nohidden",
2362 tar_reset ? "reset" : "noreset",
2363 tar_noisy ? "verbose" : "quiet"));
2367 /****************************************************************************
2368 Feeble attrib command
2369 ***************************************************************************/
2370 void cmd_setmode(char *dum_in, char *dum_out)
2378 attra[0] = attra[1] = 0;
2380 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2382 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2386 safe_strcpy(fname, cur_dir, sizeof(pstring));
2387 safe_strcat(fname, buf, sizeof(pstring));
2389 while (next_token(NULL,buf,NULL,sizeof(buf))) {
2398 case 'r': attra[direct]|=aRONLY;
2400 case 'h': attra[direct]|=aHIDDEN;
2402 case 's': attra[direct]|=aSYSTEM;
2404 case 'a': attra[direct]|=aARCH;
2406 default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2411 if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
2413 DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
2417 DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
2418 (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
2419 (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
2422 /****************************************************************************
2423 Principal command for creating / extracting
2424 ***************************************************************************/
2425 void cmd_tar(char *inbuf, char *outbuf)
2431 if (!next_token(NULL,buf,NULL,sizeof(buf)))
2433 DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
2437 argl=toktocliplist(&argcl, NULL);
2438 if (!tar_parseargs(argcl, argl, buf, 0))
2441 process_tar(inbuf, outbuf);
2446 /****************************************************************************
2447 Command line (option) version
2448 ***************************************************************************/
2449 int process_tar(char *inbuf, char *outbuf)
2465 if (clipn && tar_excl) {
2469 for (i=0; i<clipn; i++) {
2470 DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
2472 if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
2473 *(cliplist[i]+strlen(cliplist[i])-1)='\0';
2476 if (strrchr(cliplist[i], '\\')) {
2479 safe_strcpy(saved_dir, cur_dir, sizeof(pstring));
2481 if (*cliplist[i]=='\\') {
2482 safe_strcpy(tarmac, cliplist[i], sizeof(pstring));
2484 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2485 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2487 safe_strcpy(cur_dir, tarmac, sizeof(pstring));
2488 *(strrchr(cur_dir, '\\')+1)='\0';
2490 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2491 safe_strcpy(cur_dir,saved_dir, sizeof(pstring));
2493 safe_strcpy(tarmac, cur_dir, sizeof(pstring));
2494 safe_strcat(tarmac, cliplist[i], sizeof(pstring));
2495 do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
2500 safe_strcpy(mask,cur_dir, sizeof(pstring));
2501 safe_strcat(mask,"\\*", sizeof(pstring));
2502 do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
2505 if (ntarf) dotareof(tarhandle);
2509 DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
2510 DEBUG(0, ("Total bytes written: %d\n", ttarf));
2514 if (must_free_cliplist) {
2516 for (i = 0; i < clipn; ++i) {
2522 must_free_cliplist = False;
2528 /****************************************************************************
2529 Find a token (filename) in a clip list
2530 ***************************************************************************/
2531 static int clipfind(char **aret, int ret, char *tok)
2533 if (aret==NULL) return 0;
2535 /* ignore leading slashes or dots in token */
2536 while(strchr("/\\.", *tok)) tok++;
2541 /* ignore leading slashes or dots in list */
2542 while(strchr("/\\.", *pkey)) pkey++;
2544 if (!strslashcmp(pkey, tok)) return 1;
2550 /****************************************************************************
2551 Read list of files to include from the file and initialize cliplist
2553 ***************************************************************************/
2554 static int read_inclusion_file(char *filename)
2556 FILE *inclusion = NULL;
2557 char buf[MAXPATHLEN + 1];
2558 char *inclusion_buffer = NULL;
2559 int inclusion_buffer_size = 0;
2560 int inclusion_buffer_sofar = 0;
2567 buf[MAXPATHLEN] = '\0'; /* guarantee null-termination */
2568 if ((inclusion = fopen(filename, "r")) == NULL) {
2569 /* XXX It would be better to include a reason for failure, but without
2570 * autoconf, it's hard to use strerror, sys_errlist, etc.
2572 DEBUG(0,("Unable to open inclusion file %s\n", filename));
2576 while ((! error) && (fgets(buf, sizeof(buf)-1, inclusion))) {
2577 if (inclusion_buffer == NULL) {
2578 inclusion_buffer_size = 1024;
2579 if ((inclusion_buffer = malloc(inclusion_buffer_size)) == NULL) {
2580 DEBUG(0,("failure allocating buffer to read inclusion file\n"));
2586 if (buf[strlen(buf)-1] == '\n') {
2587 buf[strlen(buf)-1] = '\0';
2590 if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
2591 inclusion_buffer_size *= 2;
2592 inclusion_buffer = Realloc(inclusion_buffer,inclusion_buffer_size);
2593 if (! inclusion_buffer) {
2594 DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
2595 inclusion_buffer_size));
2601 safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
2602 inclusion_buffer_sofar += strlen(buf) + 1;
2608 /* Allocate an array of clipn + 1 char*'s for cliplist */
2609 cliplist = malloc((clipn + 1) * sizeof(char *));
2610 if (cliplist == NULL) {
2611 DEBUG(0,("failure allocating memory for cliplist\n"));
2614 cliplist[clipn] = NULL;
2615 p = inclusion_buffer;
2616 for (i = 0; (! error) && (i < clipn); i++) {
2617 /* set current item to NULL so array will be null-terminated even if
2618 * malloc fails below. */
2620 if ((tmpstr = (char *)malloc(strlen(p)+1)) == NULL) {
2621 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i));
2624 unfixtarname(tmpstr, p, strlen(p) + 1, True);
2625 cliplist[i] = tmpstr;
2626 if ((p = strchr(p, '\000')) == NULL) {
2627 DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
2633 must_free_cliplist = True;
2637 if (inclusion_buffer) {
2638 free(inclusion_buffer);
2643 /* We know cliplist is always null-terminated */
2644 for (pp = cliplist; *pp; ++pp) {
2649 must_free_cliplist = False;
2654 /* cliplist and its elements are freed at the end of process_tar. */
2658 /****************************************************************************
2659 Parse tar arguments. Sets tar_type, tar_excl, etc.
2660 ***************************************************************************/
2661 int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
2663 char tar_clipfl='\0';
2665 /* Reset back to defaults - could be from interactive version
2666 * reset mode and archive mode left as they are though
2678 if (tar_type=='c') {
2679 printf("Tar must be followed by only one of c or x.\n");
2685 if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
2686 DEBUG(0,("Option b must be followed by valid blocksize\n"));
2697 DEBUG(0,("Option N must be followed by valid file name\n"));
2700 SMB_STRUCT_STAT stbuf;
2701 extern time_t newer_than;
2703 if (dos_stat(argv[Optind], &stbuf) == 0) {
2704 newer_than = stbuf.st_mtime;
2705 DEBUG(1,("Getting files newer than %s",
2706 asctime(LocalTime(&newer_than))));
2709 DEBUG(0,("Error setting newer-than time\n"));
2719 DEBUG(0,("Only one of I,X,F must be specified\n"));
2726 DEBUG(0,("Only one of I,X,F must be specified\n"));
2733 DEBUG(0,("Only one of I,X,F must be specified\n"));
2739 DEBUG(0, ("tar_re_search set\n"));
2740 tar_re_search = True;
2743 if (tar_type == 'c') {
2744 DEBUG(0, ("dry_run set\n"));
2747 DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
2752 DEBUG(0,("Unknown tar option\n"));
2757 printf("Option T must be followed by one of c or x.\n");
2761 /* tar_excl is true if cliplist lists files to be included.
2762 * Both 'I' and 'F' mean include. */
2763 tar_excl=tar_clipfl!='X';
2765 if (tar_clipfl=='F') {
2766 if (argc-Optind-1 != 1) {
2767 DEBUG(0,("Option F must be followed by exactly one filename.\n"));
2770 if (! read_inclusion_file(argv[Optind+1])) {
2773 } else if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
2778 cliplist=argv+Optind+1;
2779 clipn=argc-Optind-1;
2782 if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
2783 DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n",
2789 for (clipcount = 0; clipcount < clipn; clipcount++) {
2791 DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
2793 if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
2794 DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
2799 unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1, True);
2800 tmplist[clipcount] = tmpstr;
2801 DEBUG(5, ("Processed an item, %s\n", tmpstr));
2803 DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
2806 must_free_cliplist = True;
2809 if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
2813 if ((preg = (regex_t *)malloc(65536)) == NULL) {
2815 DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
2820 if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
2824 errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
2826 DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
2832 clipn=argc-Optind-1;
2833 cliplist=argv+Optind+1;
2837 if (Optind>=argc || !strcmp(argv[Optind], "-")) {
2838 /* Sets tar handle to either 0 or 1, as appropriate */
2839 tarhandle=(tar_type=='c');
2841 if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0))
2844 DEBUG(0,("Output is /dev/null, assuming dry_run"));
2849 if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
2850 || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
2852 DEBUG(0,("Error opening local file %s - %s\n",
2853 argv[Optind], strerror(errno)));