updated the 3.0 branch from the head branch - ready for alpha18
[kai/samba.git] / source3 / client / clitar.c
index dcc176b9d145da87466fb7fb6a371336fcddec4f..43b0ef44bc745aec7752eaa3aa63c8180377ed2c 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    Tar Extensions
    Copyright (C) Ricky Poulten 1995-1998
    Copyright (C) Richard Sharpe 1998
@@ -38,6 +37,7 @@
 
 #include "includes.h"
 #include "clitar.h"
+#include "../client/client_proto.h"
 
 static int clipfind(char **aret, int ret, char *tok);
 
@@ -66,12 +66,8 @@ typedef struct
 
 } stack;
 
-stack dir_stack = {NULL, 0}; /* Want an empty stack */
-
 #define SEPARATORS " \t\n\r"
-extern int DEBUGLEVEL;
 extern struct cli_state *cli;
-extern FILE *dbf;
 
 /* These defines are for the do_setrattr routine, to indicate
  * setting and reseting of file attributes in the function call */
@@ -85,27 +81,28 @@ static uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
 #endif
 
 static char *tarbuf, *buffer_p;
-static int tp, ntarf, tbufsiz, ttarf;
+static int tp, ntarf, tbufsiz;
+static double ttarf;
 /* Incremental mode */
-BOOL tar_inc=False;
+static BOOL tar_inc=False;
 /* Reset archive bit */
-BOOL tar_reset=False;
+static BOOL tar_reset=False;
 /* Include / exclude mode (true=include, false=exclude) */
-BOOL tar_excl=True;
+static BOOL tar_excl=True;
 /* use regular expressions for search on file names */
-BOOL tar_re_search=False;
+static BOOL tar_re_search=False;
 #ifdef HAVE_REGEX_H
 regex_t *preg;
 #endif
 /* Do not dump anything, just calculate sizes */
-BOOL dry_run=False;
+static BOOL dry_run=False;
 /* Dump files with System attribute */
-BOOL tar_system=True;
+static BOOL tar_system=True;
 /* Dump files with Hidden attribute */
-BOOL tar_hidden=True;
+static BOOL tar_hidden=True;
 /* Be noisy - make a catalogue */
-BOOL tar_noisy=True;
-BOOL tar_real_noisy=False;  /* Don't want to be really noisy by default */
+static BOOL tar_noisy=True;
+static BOOL tar_real_noisy=False;  /* Don't want to be really noisy by default */
 
 char tar_type='\0';
 static char **cliplist=NULL;
@@ -120,10 +117,9 @@ extern int max_xmit;
 extern pstring cur_dir;
 extern int get_total_time_ms;
 extern int get_total_size;
-extern int Protocol;
 
-int blocksize=20;
-int tarhandle;
+static int blocksize=20;
+static int tarhandle;
 
 static void writetarheader(int f,  char *aname, int size, time_t mtime,
                           char *amode, unsigned char ftype);
@@ -180,7 +176,7 @@ static void writetarheader(int f,  char *aname, int size, time_t mtime,
   memset(hb.dummy, 0, sizeof(hb.dummy));
   
   l=strlen(aname);
-  if (l >= NAMSIZ) {
+  if (l >= NAMSIZ - 1) {
          /* write a GNU tar style long header */
          char *b;
          b = (char *)malloc(l+TBLOCK+100);
@@ -188,13 +184,13 @@ 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", 'L');
+         writetarheader(f, "/./@LongLink", l+2, 0, "     0 \0", 'L');
          memset(b, 0, l+TBLOCK+100);
          fixtarname(b, aname, l);
          i = strlen(b)+1;
-         DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
+         DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b)));
          dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
-         free(b);
+         SAFE_FREE(b);
   }
 
   /* use l + 1 to do the null too */
@@ -420,31 +416,12 @@ static void dotareof(int f)
 ****************************************************************************/
 static void fixtarname(char *tptr, char *fp, int l)
 {
-  /* add a '.' to start of file name, convert from ugly dos \'s in path
-   * to lovely unix /'s :-} */
-
-  *tptr++='.';
-
-  while (l > 0) {
-    int skip;
-    if((skip = skip_multibyte_char( *fp)) != 0) {
-      if (skip == 2) {
-        *tptr++ = *fp++;
-        *tptr++ = *fp++;
-        l -= 2;
-      } else if (skip == 1) {
-        *tptr++ = *fp++;
-        l--;
-      }
-    } else if (*fp == '\\') {
-      *tptr++ = '/';
-      fp++;
-      l--;
-    } else {
-      *tptr++ = *fp++;
-      l--;
-    }
-  }
+       /* add a '.' to start of file name, convert from ugly dos \'s in path
+        * to lovely unix /'s :-} */
+       *tptr++='.';
+
+       safe_strcpy(tptr, fp, l);
+       string_replace(tptr, '\\', '/');
 }
 
 /****************************************************************************
@@ -551,7 +528,7 @@ static BOOL ensurepath(char *fname)
   safe_strcpy(ffname, fname, strlen(fname));
 
   /* do a `basename' on ffname, so don't try and make file name directory */
-  if ((basehack=strrchr(ffname, '\\')) == NULL)
+  if ((basehack=strrchr_m(ffname, '\\')) == NULL)
     return True;
   else
     *basehack='\0';
@@ -658,7 +635,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
     {
       DEBUG(3,("skipping file %s of size %d bytes\n",
               finfo.name,
-              finfo.size));
+              (int)finfo.size));
       shallitime=0;
       ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
       ntarf++;
@@ -711,7 +688,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
     {
       DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
               finfo.name,
-              finfo.size,
+              (int)finfo.size,
               lname));
       
       /* write a tar header, don't bother with mode - just set to 100644 */
@@ -728,6 +705,17 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
                      break;
              }
              
+                 nread += datalen;
+
+                 /* if file size has increased since we made file size query, truncate
+                       read so tar header for this file will be correct.
+                  */
+
+                 if (nread > finfo.size) {
+                       datalen -= nread - finfo.size;
+                       DEBUG(0,("File size change - truncating %s to %d bytes\n", finfo.name, (int)finfo.size));
+                 }
+
              /* add received bits of file to buffer - dotarbuf will
               * write out in 512 byte intervals */
              if (dotarbuf(tarhandle,data,datalen) != datalen) {
@@ -735,7 +723,6 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
                      break;
              }
              
-             nread += datalen;
              if (datalen == 0) {
                      DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
                      break;
@@ -746,7 +733,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
 
       /* pad tar file with zero's if we couldn't get entire file */
       if (nread < finfo.size) {
-             DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
+             DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", (int)finfo.size, (int)nread));
              if (padit(data, sizeof(data), finfo.size - nread))
                      DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
       }
@@ -780,7 +767,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
       if (tar_noisy)
        {
          DEBUG(0, ("%10d (%7.1f kb/s) %s\n",
-              finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
+              (int)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
                finfo.name));
        }
 
@@ -805,7 +792,7 @@ static void do_tar(file_info *finfo)
   if (!tar_excl && clipn) {
     pstring exclaim;
 
-    DEBUG(5, ("Excl: strlen(cur_dir) = %i\n", strlen(cur_dir)));
+    DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir)));
 
     safe_strcpy(exclaim, cur_dir, sizeof(pstring));
     *(exclaim+strlen(exclaim)-1)='\0';
@@ -819,7 +806,7 @@ static void do_tar(file_info *finfo)
 #ifdef HAVE_REGEX_H
        (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
 #else
-        (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
+        (tar_re_search && mask_match(exclaim, cliplist[0], True))) {
 #endif
       DEBUG(3,("Skipping file %s\n", exclaim));
       return;
@@ -833,7 +820,7 @@ static void do_tar(file_info *finfo)
 
       safe_strcpy(saved_curdir, cur_dir, sizeof(saved_curdir));
 
-      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));
+      DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n", (int)sizeof(cur_dir), (int)strlen(cur_dir), (int)strlen(finfo->name), finfo->name, cur_dir));
 
       safe_strcat(cur_dir,finfo->name, sizeof(cur_dir));
       safe_strcat(cur_dir,"\\", sizeof(cur_dir));
@@ -866,43 +853,25 @@ Convert from UNIX to DOS file names
 ***************************************************************************/
 static void unfixtarname(char *tptr, char *fp, int l, BOOL first)
 {
-  /* remove '.' from start of file name, convert from unix /'s to
-   * dos \'s in path. Kill any absolute path names. But only if first!
-   */
-
-  DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
-
-  if (first) {
-    if (*fp == '.') {
-      fp++;
-      l--;
-    }
-    if (*fp == '\\' || *fp == '/') {
-      fp++;
-      l--;
-    }
-  }
+       /* remove '.' from start of file name, convert from unix /'s to
+        * dos \'s in path. Kill any absolute path names. But only if first!
+        */
+
+       DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
+
+       if (first) {
+               if (*fp == '.') {
+                       fp++;
+                       l--;
+               }
+               if (*fp == '\\' || *fp == '/') {
+                       fp++;
+                       l--;
+               }
+       }
 
-  while (l > 0) {
-    int skip;
-    if(( skip = skip_multibyte_char( *fp )) != 0) {
-      if (skip == 2) {
-        *tptr++ = *fp++;
-        *tptr++ = *fp++;
-        l -= 2;
-      } else if (skip == 1) {
-        *tptr++ = *fp++;
-        l--;
-      }
-    } else if (*fp == '/') {
-      *tptr++ = '\\';
-      fp++;
-      l--;
-    } else {
-      *tptr++ = *fp++;
-      l--;
-    }
-  }
+       safe_strcpy(tptr, fp, l);
+       string_replace(tptr, '/', '\\');
 }
 
 
@@ -922,14 +891,27 @@ static int next_block(char *ltarbuf, char **bufferp, int bufsiz)
 
     DEBUG(5, ("Reading more data into ltarbuf ...\n"));
 
-    total = 0;
+    /*
+     * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>
+     * Fixes bug where read can return short if coming from
+     * a pipe.
+     */
 
-    for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
+    bufread = read(tarhandle, ltarbuf, bufsiz);
+    total = bufread;
 
-      if (bufread <= 0) { /* An error, return false */
-       return (total > 0 ? -2 : bufread);
+    while (total < bufsiz) {
+      if (bufread < 0) { /* An error, return false */
+        return (total > 0 ? -2 : bufread);
       }
-
+      if (bufread == 0) {
+        if (total <= 0) {
+            return -2;
+        }
+        break;
+      }
+      bufread = read(tarhandle, &ltarbuf[total], bufsiz - total);
+      total += bufread;
     }
 
     DEBUG(5, ("Total bytes read ... %i\n", total));
@@ -967,24 +949,27 @@ static int skip_file(int skipsize)
   return(True);
 }
 
-/* We get a file from the tar file and store it */
+/*************************************************************
+ Get a file from the tar file and store it.
+ When this is called, tarbuf already contains the first
+ file block. This is a bit broken & needs fixing.
+**************************************************************/
+
 static int get_file(file_info2 finfo)
 {
-  int fsize = finfo.size;
   int fnum = -1, pos = 0, dsize = 0, rsize = 0, bpos = 0;
 
-  DEBUG(5, ("get_file: file: %s, size %i\n", finfo.name, fsize));
+  DEBUG(5, ("get_file: file: %s, size %i\n", finfo.name, (int)finfo.size));
 
   if (ensurepath(finfo.name) && 
-      (fnum=cli_open(cli, finfo.name, O_WRONLY|O_CREAT|O_TRUNC, DENY_NONE)) == -1)
-    {
+      (fnum=cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) == -1) {
       DEBUG(0, ("abandoning restore\n"));
       return(False);
-    }
+  }
 
   /* read the blocks from the tar file and write to the remote file */
 
-  rsize = fsize;  /* This is how much to write */
+  rsize = finfo.size;  /* This is how much to write */
 
   while (rsize > 0) {
 
@@ -1022,17 +1007,23 @@ static int get_file(file_info2 finfo)
 
     }
 
-    while (dsize >= TBLOCK) {
+    /*
+     * Bugfix from Bob Boehmer <boehmer@worldnet.att.net>.
+     * If the file being extracted is an exact multiple of
+     * TBLOCK bytes then we don't want to extract the next
+     * block from the tarfile here, as it will be done in
+     * the caller of get_file().
+     */
 
-      if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
+    while (((rsize != 0) && (dsize >= TBLOCK)) ||
+         ((rsize == 0) && (dsize > TBLOCK))) {
 
+      if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
        DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
        return False;
-
       }
 
       dsize -= TBLOCK;
-
     }
 
     bpos = dsize;
@@ -1059,7 +1050,7 @@ static int get_file(file_info2 finfo)
 
   ntarf++;
 
-  DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo.name, finfo.size));
+  DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo.name, (int)finfo.size));
   
   return(True);
 }
@@ -1070,7 +1061,7 @@ static int get_file(file_info2 finfo)
 static int get_dir(file_info2 finfo)
 {
 
-  DEBUG(5, ("Creating directory: %s\n", finfo.name));
+  DEBUG(0, ("restore directory %s\n", finfo.name));
 
   if (!ensurepath(finfo.name)) {
 
@@ -1078,6 +1069,8 @@ static int get_dir(file_info2 finfo)
     return(False);
 
   }
+
+  ntarf++;
   return(True);
 
 }
@@ -1093,12 +1086,12 @@ static char * get_longfilename(file_info2 finfo)
   BOOL first = True;
 
   DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
-  DEBUG(5, ("Len = %i\n", finfo.size));
+  DEBUG(5, ("Len = %d\n", (int)finfo.size));
 
   if (longname == NULL) {
 
     DEBUG(0, ("could not allocate buffer of size %d for longname\n", 
-             finfo.size + strlen(cur_dir) + 2));
+             (int)(finfo.size + strlen(cur_dir) + 2)));
     return(NULL);
   }
 
@@ -1180,7 +1173,7 @@ static void do_tarput(void)
       return;
 
     case 0: /* chksum is zero - looks like an EOF */
-      DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
+      DEBUG(0, ("tar: restored %d files and directories\n", ntarf));
       return;        /* Hmmm, bad here ... */
 
     default: 
@@ -1194,7 +1187,7 @@ static void do_tarput(void)
 
     if (longfilename != NULL) {
 
-      free(finfo.name);   /* Free the space already allocated */
+      SAFE_FREE(finfo.name);   /* Free the space already allocated */
       finfo.name = longfilename;
       longfilename = NULL;
 
@@ -1209,7 +1202,7 @@ static void do_tarput(void)
 #ifdef HAVE_REGEX_H
       || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
 #else
-      || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
+      || (tar_re_search && mask_match(finfo.name, cliplist[0], True)));
 #endif
 
   DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
@@ -1228,10 +1221,14 @@ static void do_tarput(void)
 
     case '0':  /* Should use symbolic names--FIXME */
 
-      /* Skip to the next block first, so we can get the file, FIXME, should
-         be in get_file ... */
+      /* 
+       * Skip to the next block first, so we can get the file, FIXME, should
+       * be in get_file ...
+       * The 'finfo.size != 0' fix is from Bob Boehmer <boehmer@worldnet.att.net>
+       * Fixes bug where file size in tarfile is zero.
+       */
 
-      if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
+      if ((finfo.size != 0) && next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
        DEBUG(0, ("Short file, bailing out...\n"));
        return;
       }
@@ -1278,36 +1275,38 @@ static void do_tarput(void)
 /****************************************************************************
 Blocksize command
 ***************************************************************************/
-void cmd_block(void)
+int cmd_block(void)
 {
   fstring buf;
   int block;
 
-  if (!next_token(NULL,buf,NULL,sizeof(buf)))
+  if (!next_token_nr(NULL,buf,NULL,sizeof(buf)))
     {
       DEBUG(0, ("blocksize <n>\n"));
-      return;
+      return 1;
     }
 
   block=atoi(buf);
   if (block < 0 || block > 65535)
     {
       DEBUG(0, ("blocksize out of range"));
-      return;
+      return 1;
     }
 
   blocksize=block;
   DEBUG(2,("blocksize is now %d\n", blocksize));
+
+  return 0;
 }
 
 /****************************************************************************
 command to set incremental / reset mode
 ***************************************************************************/
-void cmd_tarmode(void)
+int cmd_tarmode(void)
 {
   fstring buf;
 
-  while (next_token(NULL,buf,NULL,sizeof(buf))) {
+  while (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
     if (strequal(buf, "full"))
       tar_inc=False;
     else if (strequal(buf, "inc"))
@@ -1338,12 +1337,13 @@ void cmd_tarmode(void)
            tar_reset ? "reset" : "noreset",
            tar_noisy ? "verbose" : "quiet"));
 
+  return 0;
 }
 
 /****************************************************************************
 Feeble attrib command
 ***************************************************************************/
-void cmd_setmode(void)
+int cmd_setmode(void)
 {
   char *q;
   fstring buf;
@@ -1353,16 +1353,16 @@ void cmd_setmode(void)
 
   attra[0] = attra[1] = 0;
 
-  if (!next_token(NULL,buf,NULL,sizeof(buf)))
+  if (!next_token_nr(NULL,buf,NULL,sizeof(buf)))
     {
       DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
-      return;
+      return 1;
     }
 
   safe_strcpy(fname, cur_dir, sizeof(pstring));
   safe_strcat(fname, buf, sizeof(pstring));
 
-  while (next_token(NULL,buf,NULL,sizeof(buf))) {
+  while (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
     q=buf;
 
     while(*q)
@@ -1380,43 +1380,47 @@ void cmd_setmode(void)
       case 'a': attra[direct]|=aARCH;
        break;
       default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
-       return;
+       return 1;
       }
   }
 
   if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
     {
       DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
-      return;
+      return 1;
     }
 
   DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
   do_setrattr(fname, attra[ATTRSET], ATTRSET);
   do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
+
+  return 0;
 }
 
 /****************************************************************************
 Principal command for creating / extracting
 ***************************************************************************/
-void cmd_tar(void)
+int cmd_tar(void)
 {
   fstring buf;
   char **argl;
   int argcl;
 
-  if (!next_token(NULL,buf,NULL,sizeof(buf)))
+  if (!next_token_nr(NULL,buf,NULL,sizeof(buf)))
     {
       DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
-      return;
+      return 1;
     }
 
   argl=toktocliplist(&argcl, NULL);
   if (!tar_parseargs(argcl, argl, buf, 0))
-    return;
+    return 1;
 
   process_tar();
 
-  free(argl);
+  SAFE_FREE(argl);
+
+  return 0;
 }
 
 /****************************************************************************
@@ -1433,7 +1437,7 @@ int process_tar(void)
 #else
     do_tarput();
 #endif
-    free(tarbuf);
+    SAFE_FREE(tarbuf);
     close(tarhandle);
     break;
   case 'r':
@@ -1449,7 +1453,7 @@ int process_tar(void)
          *(cliplist[i]+strlen(cliplist[i])-1)='\0';
        }
        
-       if (strrchr(cliplist[i], '\\')) {
+       if (strrchr_m(cliplist[i], '\\')) {
          pstring saved_dir;
          
          safe_strcpy(saved_dir, cur_dir, sizeof(pstring));
@@ -1461,7 +1465,7 @@ int process_tar(void)
            safe_strcat(tarmac, cliplist[i], sizeof(pstring));
          }
          safe_strcpy(cur_dir, tarmac, sizeof(pstring));
-         *(strrchr(cur_dir, '\\')+1)='\0';
+         *(strrchr_m(cur_dir, '\\')+1)='\0';
 
          DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
          do_list(tarmac,attribute,do_tar, False, True);
@@ -1476,26 +1480,26 @@ int process_tar(void)
     } else {
       pstring mask;
       safe_strcpy(mask,cur_dir, sizeof(pstring));
-      DEBUG(5, ("process_tar, do_list with mask: $s\n", mask));
+      DEBUG(5, ("process_tar, do_list with mask: %s\n", mask));
       safe_strcat(mask,"\\*", sizeof(pstring));
       do_list(mask,attribute,do_tar,False, True);
     }
     
     if (ntarf) dotareof(tarhandle);
     close(tarhandle);
-    free(tarbuf);
+    SAFE_FREE(tarbuf);
     
-    DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
-    DEBUG(0, ("Total bytes written: %d\n", ttarf));
+    DEBUG(0, ("tar: dumped %d files and directories\n", ntarf));
+    DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf));
     break;
   }
 
   if (must_free_cliplist) {
     int i;
     for (i = 0; i < clipn; ++i) {
-      free(cliplist[i]);
+      SAFE_FREE(cliplist[i]);
     }
-    free(cliplist);
+    SAFE_FREE(cliplist);
     cliplist = NULL;
     clipn = 0;
     must_free_cliplist = False;
@@ -1512,13 +1516,13 @@ static int clipfind(char **aret, int ret, char *tok)
   if (aret==NULL) return 0;
 
   /* ignore leading slashes or dots in token */
-  while(strchr("/\\.", *tok)) tok++;
+  while(strchr_m("/\\.", *tok)) tok++;
 
   while(ret--) {
     char *pkey=*aret++;
 
     /* ignore leading slashes or dots in list */
-    while(strchr("/\\.", *pkey)) pkey++;
+    while(strchr_m("/\\.", *pkey)) pkey++;
 
     if (!strslashcmp(pkey, tok)) return 1;
   }
@@ -1532,7 +1536,7 @@ accordingly.
 ***************************************************************************/
 static int read_inclusion_file(char *filename)
 {
-  FILE *inclusion = NULL;
+  XFILE *inclusion = NULL;
   char buf[MAXPATHLEN + 1];
   char *inclusion_buffer = NULL;
   int inclusion_buffer_size = 0;
@@ -1544,7 +1548,7 @@ static int read_inclusion_file(char *filename)
 
   clipn = 0;
   buf[MAXPATHLEN] = '\0'; /* guarantee null-termination */
-  if ((inclusion = sys_fopen(filename, "r")) == NULL) {
+  if ((inclusion = x_fopen(filename, O_RDONLY, 0)) == NULL) {
     /* XXX It would be better to include a reason for failure, but without
      * autoconf, it's hard to use strerror, sys_errlist, etc.
      */
@@ -1552,7 +1556,7 @@ static int read_inclusion_file(char *filename)
     return 0;
   }
 
-  while ((! error) && (fgets(buf, sizeof(buf)-1, inclusion))) {
+  while ((! error) && (x_fgets(buf, sizeof(buf)-1, inclusion))) {
     if (inclusion_buffer == NULL) {
       inclusion_buffer_size = 1024;
       if ((inclusion_buffer = malloc(inclusion_buffer_size)) == NULL) {
@@ -1567,21 +1571,23 @@ static int read_inclusion_file(char *filename)
     }
     
     if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
+      char *ib;
       inclusion_buffer_size *= 2;
-      inclusion_buffer = Realloc(inclusion_buffer,inclusion_buffer_size);
-      if (! inclusion_buffer) {
+      ib = Realloc(inclusion_buffer,inclusion_buffer_size);
+      if (! ib) {
        DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
                 inclusion_buffer_size));
        error = 1;
        break;
       }
+      else inclusion_buffer = ib;
     }
     
     safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
     inclusion_buffer_sofar += strlen(buf) + 1;
     clipn++;
   }
-  fclose(inclusion);
+  x_fclose(inclusion);
 
   if (! error) {
     /* Allocate an array of clipn + 1 char*'s for cliplist */
@@ -1602,7 +1608,7 @@ static int read_inclusion_file(char *filename)
        } else {
          unfixtarname(tmpstr, p, strlen(p) + 1, True);
          cliplist[i] = tmpstr;
-         if ((p = strchr(p, '\000')) == NULL) {
+         if ((p = strchr_m(p, '\000')) == NULL) {
            DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n"));
            abort();
          }
@@ -1613,17 +1619,15 @@ static int read_inclusion_file(char *filename)
     }
   }
 
-  if (inclusion_buffer) {
-    free(inclusion_buffer);
-  }
+  SAFE_FREE(inclusion_buffer);
   if (error) {
     if (cliplist) {
       char **pp;
       /* We know cliplist is always null-terminated */
       for (pp = cliplist; *pp; ++pp) {
-        free(*pp);
+        SAFE_FREE(*pp);
       }
-      free(cliplist);
+      SAFE_FREE(cliplist);
       cliplist = NULL;
       must_free_cliplist = False;
     }
@@ -1679,7 +1683,7 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
        SMB_STRUCT_STAT stbuf;
        extern time_t newer_than;
        
-       if (dos_stat(argv[Optind], &stbuf) == 0) {
+       if (sys_stat(argv[Optind], &stbuf) == 0) {
          newer_than = stbuf.st_mtime;
          DEBUG(1,("Getting files newer than %s",
                   asctime(LocalTime(&newer_than))));
@@ -1824,7 +1828,7 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
      * tar output
     */
     if (tarhandle == 1) 
-      dbf = stderr;
+      dbf = x_stderr;
   } else {
     if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0))
       {