Changes to client.c support the need for directories to be processed by whatever
authorRichard Sharpe <sharpe@samba.org>
Sat, 11 Apr 1998 07:52:13 +0000 (07:52 +0000)
committerRichard Sharpe <sharpe@samba.org>
Sat, 11 Apr 1998 07:52:13 +0000 (07:52 +0000)
action is passed to do_dir.

Changes to clitar.c as requested by Canon Information Systems Research Australia:

1. Support restoring long file names
2. Write directory entries to TAR files as first part of setting directory create
   times
3. Ensure zero length files get correct mtime
4. Allow DOS and UNIX pathnames in command line parameters.
(This used to be commit 0c228f0b33950c8d38de0529e88a38848742a50d)

source3/client/client.c
source3/client/clitar.c

index ef942c98672af1156cd389adcab37366d9a5834c..d58644e09b8e871d8bfb5afe8331f7ea30dc5b42 100644 (file)
@@ -80,7 +80,7 @@ extern BOOL have_ip;
 extern int max_xmit;
 
 static int interpret_long_filename(int level,char *p,file_info *finfo);
-static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
+static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir, BOOL dirstoo);
 static int interpret_short_filename(char *p,file_info *finfo);
 static BOOL do_this_one(file_info *finfo);
 
@@ -478,7 +478,7 @@ static void display_finfo(file_info *finfo)
   do a directory listing, calling fn on each file found. Use the TRANSACT2
   call for long filenames
   ****************************************************************************/
-static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
+static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir, BOOL dirstoo)
 {
   int max_matches = 512;
   int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
@@ -638,7 +638,7 @@ static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*
   for (p=dirlist,i=0;i<total_received;i++)
     {
       p += interpret_long_filename(info_level,p,&finfo);
-      dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
+      dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True, dirstoo);
     }
 
   /* free up the dirlist buffer */
@@ -650,7 +650,7 @@ static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*
 /****************************************************************************
   do a directory listing, calling fn on each file found
   ****************************************************************************/
-static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
+static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir, BOOL dirstoo)
 {
   char *p;
   int received = 0;
@@ -777,7 +777,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (
   for (p=dirlist,i=0;i<num_received;i++)
     {
       p += interpret_short_filename(p,&finfo);
-      dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
+      dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False,dirstoo);
     }
 
   if (dirlist) free(dirlist);
@@ -789,17 +789,17 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (
 /****************************************************************************
   do a directory listing, calling fn on each file found
   ****************************************************************************/
-void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
+void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir, BOOL dirstoo)
 {
   DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir)));
   if (Protocol >= PROTOCOL_LANMAN2)
     {
-      if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
+      if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo) > 0)
        return;
     }
 
   expand_mask(Mask,False);
-  do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
+  do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir,dirstoo);
   return;
 }
 
@@ -973,8 +973,11 @@ static int interpret_long_filename(int level,char *p,file_info *finfo)
 
 /****************************************************************************
   act on the files in a dir listing
+
+  RJS, 4-Apr-1998, dirstoo added to allow caller to indicate that directories
+                   should be processed as well.
   ****************************************************************************/
-static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
+static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir, BOOL dirstoo)
 {
 
   if (!((finfo->mode & aDIR) == 0 && *fileselection && 
@@ -986,6 +989,11 @@ static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,B
        {
          pstring mask2;
          pstring sav_dir;
+
+          if (fn && dirstoo && do_this_one(finfo)) { /* Do dirs, RJS */
+           fn(finfo);
+         }
+
          strcpy(sav_dir,cur_dir);
          strcat(cur_dir,finfo->name);
          strcat(cur_dir,"\\");
@@ -997,9 +1005,9 @@ static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,B
          strcat(mask2,"*");
 
          if (longdir)
-           do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);      
+           do_long_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);      
          else
-           do_dir(inbuf,outbuf,mask2,attribute,fn,True);
+           do_dir(inbuf,outbuf,mask2,attribute,fn,True, dirstoo);
 
          strcpy(cur_dir,sav_dir);
        }
@@ -1038,7 +1046,7 @@ static void cmd_dir(char *inbuf,char *outbuf)
     strcat(mask,"*");
   }
 
-  do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
+  do_dir(inbuf,outbuf,mask,attribute,NULL,recurse,False);
 
   do_dskattr();
 
@@ -1541,7 +1549,7 @@ static void do_mget(file_info *finfo)
       strcat(mget_mask,"*");
       
       do_dir((char *)inbuf,(char *)outbuf,
-            mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
+            mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False, False);
       chdir("..");
       strcpy(cur_dir,saved_curdir);
       free(inbuf);free(outbuf);
@@ -1610,7 +1618,7 @@ static void cmd_mget(char *inbuf,char *outbuf)
        strcpy(mget_mask,p);
       else
        strcat(mget_mask,p);
-      do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
+      do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
     }
 
   if (! *mget_mask)
@@ -1619,7 +1627,7 @@ static void cmd_mget(char *inbuf,char *outbuf)
       if(mget_mask[strlen(mget_mask)-1]!='\\')
        strcat(mget_mask,"\\");
       strcat(mget_mask,"*");
-      do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
+      do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False,False);
     }
 }
 
@@ -2674,7 +2682,7 @@ static void cmd_del(char *inbuf,char *outbuf )
     }
   strcat(mask,buf);
 
-  do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
+  do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False,False);
 }
 
 
index 36cefeec557b1bf77fc70b8944b0d539ea1e1936..130c5e7a276533440a633c2604b13f3674510927 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
+/* The following changes developed by Richard Sharpe for Canon Information
+   Systems Research Australia (CISRA) are Copyright (C) 1998 by CISRA and are 
+   made available under the terms of the GPL as listed above:
+
+   1. Restore can now restore files with long file names
+   2. Save now saves directory information so that we can restore 
+      directory creation times
+   3. tar now accepts both UNIX path names and DOS path names. I prefer
+      those lovely /'s to those UGLY \'s :-)
+
+*/
 
 
 #include "includes.h"
 #include "clitar.h"
+#include <regex.h>
 
 extern BOOL recurse;
 
@@ -72,7 +84,8 @@ extern int Protocol;
 int blocksize=20;
 int tarhandle;
 
-static void writetarheader();
+static void writetarheader(int f,  char *aname, int size, time_t mtime,
+                          char *amode, unsigned char ftype);
 static void do_atar();
 static void do_tar();
 static void oct_it();
@@ -97,12 +110,14 @@ static void unfixtarname();
 Write a tar header to buffer
 ****************************************************************************/
 static void writetarheader(int f,  char *aname, int size, time_t mtime,
-                          char *amode)
+                          char *amode, unsigned char ftype)
 {
   union hblock hb;
   int i, chk, l;
   char *jp;
 
+  DEBUG(5, ("WriteTarHdr, Type = %c, Name = %s\n", ftype, aname));
+
   memset(hb.dummy, 0, sizeof(hb.dummy));
   
   l=strlen(aname);
@@ -114,7 +129,7 @@ static void writetarheader(int f,  char *aname, int size, time_t mtime,
                  DEBUG(0,("out of memory\n"));
                  exit(1);
          }
-         writetarheader(f, "/./@LongLink", l+1, 0, "     0 \0");
+         writetarheader(f, "/./@LongLink", l+1, 0, "     0 \0", 'L');
          memset(b, 0, l+TBLOCK+100);
          fixtarname(b, aname, l+1);
          i = strlen(b)+1;
@@ -138,12 +153,7 @@ static void writetarheader(int f,  char *aname, int size, time_t mtime,
   oct_it((long) mtime, 13, hb.dbuf.mtime);
   memcpy(hb.dbuf.chksum, "        ", sizeof(hb.dbuf.chksum));
   memset(hb.dbuf.linkname, 0, NAMSIZ);
-  if (strcmp("/./@LongLink", aname) == 0) {
-         /* we're doing a GNU tar long filename */
-         hb.dbuf.linkflag='L';
-  } else {
-         hb.dbuf.linkflag='0';
-  }
+  hb.dbuf.linkflag=ftype;
   
   for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
 
@@ -196,14 +206,21 @@ static long readtarheader(union hblock *hb, file_info *finfo, char *prefix)
   unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
               strlen(hb->dbuf.name) + 1);
 
-/* can't handle links at present */
-  if (hb->dbuf.linkflag != '0') {
+/* can't handle some links at present */
+  if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
     if (hb->dbuf.linkflag == 0) {
       DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
                finfo->name));
     } else { 
-      DEBUG(0, ("this tar file appears to contain some kind of link - ignoring\n"));
-      return -2;
+      if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
+         /* Do nothing here at the moment. do_tarput will handle this
+            as long as the longlink gets back to it, as it has to advance 
+            the buffer pointer, etc */
+
+      } else {
+        DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
+        return -2;
+      }
     }
   }
     
@@ -264,7 +281,7 @@ static int dotarbuf(int f, char *b, int n)
 }
 
 /****************************************************************************
-Write zeros to buffer / tape
+Write zeros to buffer / tape
 ****************************************************************************/
 static void dozerobuf(int f, int n)
 {
@@ -275,6 +292,7 @@ static void dozerobuf(int f, int n)
   if (n+tp >= tbufsiz)
     {
       memset(tarbuf+tp, 0, tbufsiz-tp);
+
       write(f, tarbuf, tbufsiz);
       memset(tarbuf, 0, (tp+=n-tbufsiz));
     }
@@ -292,7 +310,7 @@ static void initarbuf()
 {
   /* initialize tar buffer */
   tbufsiz=blocksize*TBLOCK;
-  tarbuf=malloc(tbufsiz);
+  tarbuf=malloc(tbufsiz);      /* FIXME: We might not get the buffer */
 
   /* reset tar buffer pointer and tar file counter and total dumped */
   tp=0; ntarf=0; ttarf=0;
@@ -428,6 +446,70 @@ static int strslashcmp(char *s1, char *s2)
 /*
  * general smb utility functions
  */
+/**********************************************************************
+do_setrtime, set time on a file or dir ...
+**********************************************************************/
+
+static int do_setrtime(char *fname, int mtime)
+{
+  char *inbuf, *outbuf, *p;
+  char *name;
+
+  name = (char *)malloc(strlen(fname) + 1 + 1);
+  if (name == NULL) {
+
+     DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
+     return False;
+
+  }
+
+  strcpy(name, fname);
+  strcpy(fname, "\\");
+  strcat(fname, name);
+
+  inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+  outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+
+  if (!inbuf || !outbuf) {
+
+    DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
+    return False;
+
+  }
+
+  memset(outbuf, 0, smb_size);
+  set_message(outbuf, 8, 4 + strlen(fname), True);
+  CVAL(outbuf, smb_com) = SMBsetatr;
+  SSVAL(outbuf, smb_tid, cnum);
+  cli_setup_pkt(outbuf);
+
+  SSVAL(outbuf, smb_vwv0, 0);
+  put_dos_date3(outbuf, smb_vwv1, mtime);
+
+  p = smb_buf(outbuf);
+  *p++ = 4;
+  strcpy(p, fname);
+  p+= (strlen(fname)+1);
+
+  *p++ = 4;
+  *p++ = 0;
+
+  send_smb(Client, outbuf);
+  client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
+
+  if (CVAL(inbuf,smb_rcls) != 0)
+    {
+      DEBUG(0,("%s setting attributes on file %s\n",
+           smb_errstr(inbuf), fname));
+      free(inbuf);free(outbuf);
+      return(False);
+    }
+
+  free(inbuf);free(outbuf);
+  return(True);
+
+}
+
 /****************************************************************************
 Set DOS file attributes
 ***************************************************************************/
@@ -499,7 +581,7 @@ static int do_setrattr(char *fname, int attr, int setit)
   cli_setup_pkt(outbuf);
 
   SSVAL(outbuf,smb_vwv0,attr);
-
+  
   p = smb_buf(outbuf);
   *p++ = 4;      
   strcpy(p,fname);
@@ -531,7 +613,7 @@ static BOOL smbcreat(file_info finfo, int *fnum, char *inbuf, char *outbuf)
   char *p;
   /* *must* be called with buffer ready malloc'ed */
   /* open remote file */
-  
+
   memset(outbuf,0,smb_size);
   set_message(outbuf,3,2 + strlen(finfo.name),True);
   CVAL(outbuf,smb_com) = SMBcreate;
@@ -704,6 +786,8 @@ static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
   pstring partpath, ffname;
   char *p=fname, *basehack;
 
+  DEBUG(5, ( "Ensurepath called with: %s\n", fname));
+
   *partpath = 0;
 
   /* fname copied to ffname so can strtok */
@@ -766,7 +850,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
 {
   int fnum;
   uint32 nread=0;
-  char *p;
+  char *p, ftype;
   char *inbuf,*outbuf;
   file_info finfo;
   BOOL close_done = False;
@@ -778,6 +862,8 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
   struct timeval tp_start;
   GetTimeOfDay(&tp_start);
 
+  ftype = '0'; /* An ordinary file ... */
+
   if (finfo1) 
     finfo = *finfo1;
   else
@@ -893,7 +979,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
               lname));
       
       /* write a tar header, don't bother with mode - just set to 100644 */
-      writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0");
+      writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
       
       while (nread < finfo.size && !close_done)
        {
@@ -1174,7 +1260,7 @@ static void do_tar(file_info *finfo)
 {
   pstring rname;
 
-  if (strequal(finfo->name,".") || strequal(finfo->name,".."))
+  if (strequal(finfo->name,".."))
     return;
 
   /* Is it on the exclude list ? */
@@ -1213,14 +1299,16 @@ static void do_tar(file_info *finfo)
       strcat(cur_dir,finfo->name);
       strcat(cur_dir,"\\");
 
+      DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
+
       /* write a tar directory, don't bother with mode - just set it to
        * 40755 */
-      writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0");
+      writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
+      ntarf++;  /* Make sure we have a file on there */
       strcpy(mtar_mask,cur_dir);
       strcat(mtar_mask,"*");
-      
-      do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse);
-      strcpy(cur_dir,saved_curdir);
+      /*      do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
+             strcpy(cur_dir,saved_curdir);
       free(inbuf);free(outbuf);
     }
   else
@@ -1265,11 +1353,25 @@ static void unfixtarname(char *tptr, char *fp, int l)
   }
 }
 
+/****************************************************************************
+Move to the next block in the buffer, which may mean read in another set of
+blocks.
+****************************************************************************/
+int next_block(char *tarbuf, char *bufferp, int bufsiz)
+{
+  int bufread, total = 0;
+
+  for (bufread = read(tarhandle, tarbuf, bufsiz); total += bufread; total < bufsiz) {
+
+    }
+
+}
+
 static void do_tarput()
 {
   file_info finfo;
   int nread=0, bufread;
-  char *inbuf,*outbuf; 
+  char *inbuf,*outbuf, *longname = NULL
   int fsize=0;
   int fnum;
   struct timeval tp_start;
@@ -1332,26 +1434,93 @@ static void do_tarput()
     do {
       if (!fsize)
        {
-         switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir))
-           {
-           case -2:             /* something dodgy but not fatal about this */
-             DEBUG(0, ("skipping %s...\n", finfo.name));
-             bufferp+=TBLOCK;   /* header - like a link */
-             continue;
-           case -1:
-             DEBUG(0, ("abandoning restore\n"));
-             free(inbuf); free(outbuf);
-             return;
-           case 0: /* chksum is zero - we assume that one all zero
-                    *header block will do for eof */
-             DEBUG(0,
-                   ("total of %d tar files restored to share\n", ntarf));
-             free(inbuf); free(outbuf);
-             return;
-           default:
-             break;
-           }
+          int next_header = 1;  /* Want at least one header */
+          while (next_header) 
+            {  
+            if (bufferp >= endofbuffer) {
+
+              bufread = read(tarhandle, tarbuf, tbufsiz);
+              bufferp = tarbuf;
+
+            }
+            next_header = 0;    /* Don't want the next one ... */
+           switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir))
+             {
+             case -2:             /* something dodgy but not fatal about this */
+               DEBUG(0, ("skipping %s...\n", finfo.name));
+               bufferp+=TBLOCK;   /* header - like a link */
+               continue;
+             case -1:
+               DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
+               free(inbuf); free(outbuf);
+               return;
+             case 0: /* chksum is zero - we assume that one all zero
+                      *header block will do for eof */
+               DEBUG(0,
+                     ("total of %d tar files restored to share\n", ntarf));
+               free(inbuf); free(outbuf);
+               return;
+             default:
+               break;
+             }
+
+            /* If we have a longname left from the last time through, 
+               copy it into finfo.name and free it.
+
+               The size of a pstring is the limiting factor on filenames
+               and directory names now. The total pathname length must be
+               less than sizeof(pstring) - 1, which is currently 1023. */
+
+            if (longname != NULL) {
+
+              strncpy(finfo.name, longname, sizeof(pstring) - 1);
+              free(longname);
+              longname = NULL;
+
+            }
+
+            /* Check if a long-link. We do this before the clip checking
+               because clip-checking should clip on real name - RJS */
+
+            if (((union hblock *)bufferp) -> dbuf.linkflag == 'L') {
+
+              /* Skip this header, but pick up length, get the name and 
+                 fix the name and skip the name. Hmmm, what about end of
+                 buffer??? */
+
+              longname = malloc(finfo.size + strlen(cur_dir) + 1);
+              if (longname == NULL) {
+
+                 DEBUG(0, ("could not allocate buffer of size %d for longname\n",
+                          finfo.size + strlen(cur_dir) + 1)
+                      );
+                 free(inbuf); free(outbuf);
+                 return;
+              }
+
+              bufferp += TBLOCK;   /* Skip that longlink header */
 
+              /* This needs restructuring ... */
+
+             if (bufferp >= endofbuffer) {
+
+               bufread = read(tarhandle, tarbuf, tbufsiz);
+
+               bufferp = tarbuf;
+
+              }
+
+              strncpy(longname, cur_dir, strlen(cur_dir)); 
+              unfixtarname(longname+strlen(cur_dir), bufferp, finfo.size);
+
+              /* Next rounds up to next TBLOCK and takes care of us being right
+                 on a TBLOCK boundary */
+
+              bufferp += (((finfo.size - 1)/TBLOCK)+1)*TBLOCK;
+              next_header = 1;  /* Force read of next header */
+
+            }
+          }
          tskip=clipn
            && (clipfind(cliplist, clipn, finfo.name) ^ tar_excl);
          if (tskip) {
@@ -1371,17 +1540,32 @@ static void do_tarput()
            }
          }
 
+         DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
+
          if (finfo.mode & aDIR)
            {
-             if (!smbchkpath(finfo.name, inbuf, outbuf)
-                 && !smbmkdir(finfo.name, inbuf, outbuf))
+             if (!ensurepath(finfo.name, inbuf, outbuf))
+/*           if (!smbchkpath(finfo.name, inbuf, outbuf)
+                 && !smbmkdir(finfo.name, inbuf, outbuf))*/
                {
-                 DEBUG(0, ("abandoning restore\n"));
+                 DEBUG(0, ("abandoning restore, problems ensuring path\n"));
                  free(inbuf); free(outbuf);
                  return;
              }
              else
                {
+                 /* Now we update the creation date ... */
+
+                 DEBUG(5, ("Updating creation date on %s\n", finfo.name));
+
+                 if (!do_setrtime(finfo.name, finfo.mtime)) {
+
+                    DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
+                    return;
+
+                  }
+
+                 ntarf++;
                  bufferp+=TBLOCK;
                  continue;
                }
@@ -1397,9 +1581,17 @@ static void do_tarput()
              return;
            }
 
-         DEBUG(0,("restore tar file %s of size %d bytes\n",
+         DEBUG(0 ,("restore tar file %s of size %d bytes\n",
                   finfo.name,finfo.size));
 
+          if (!finfo.size) {
+           if (!smbshut(finfo, fnum, inbuf, outbuf)){
+              DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
+             free(inbuf);free(outbuf);
+              return;
+            }
+         }
+
          nread=0;
          if ((bufferp+=TBLOCK) >= endofbuffer) break;    
        } /* if (!fsize) */
@@ -1430,7 +1622,7 @@ static void do_tarput()
        bufferp+=minichunk; nread+=minichunk;
        chunk-=minichunk;
       }
-      
+
       if (nread>=fsize)
        {
          if (!smbshut(finfo, fnum, inbuf, outbuf))
@@ -1641,19 +1833,19 @@ int process_tar(char *inbuf, char *outbuf)
          strcpy(cur_dir, tarmac);
          *(strrchr(cur_dir, '\\')+1)='\0';
 
-         do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse);
+         do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
          strcpy(cur_dir,saved_dir);
        } else {
          strcpy(tarmac, cur_dir);
          strcat(tarmac, cliplist[i]);
-         do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse);
+         do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
        }
       }
     } else {
       pstring mask;
       strcpy(mask,cur_dir);
       strcat(mask,"\\*");
-      do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse);
+      do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
     }
     
     if (ntarf) dotareof(tarhandle);
@@ -1774,8 +1966,38 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
 
   tar_excl=tar_clipfl!='X';
   if (Optind+1<argc) {
+    char *tmpstr;
+    char **tmplist;
+    int clipcount;
+
     cliplist=argv+Optind+1;
     clipn=argc-Optind-1;
+    clipcount = clipn;
+
+    if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
+      DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", 
+               clipn)
+           );
+      return 0;
+    }
+
+    for (clipcount = 0; clipcount < clipn; clipcount++) {
+
+      DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
+
+      if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
+        DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
+                 clipcount)
+             );
+        return 0;
+      }
+      unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1);
+      tmplist[clipcount] = tmpstr;
+      DEBUG(5, ("Processed an item, %s\n", tmpstr));
+
+      DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
+    }
+    cliplist = tmplist;
   }
   if (Optind>=argc || !strcmp(argv[Optind], "-")) {
     /* Sets tar handle to either 0 or 1, as appropriate */