updated the 3.0 branch from the head branch - ready for alpha18
[kai/samba.git] / source3 / client / clitar.c
index efa4fa8815edccc705f24a9294d73659e454a384..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 */
@@ -88,25 +84,25 @@ static char *tarbuf, *buffer_p;
 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;
@@ -121,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);
@@ -181,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);
@@ -189,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=%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 */
@@ -421,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 = get_character_len(*fp);
-    if(skip != 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, '\\', '/');
 }
 
 /****************************************************************************
@@ -552,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';
@@ -729,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) {
@@ -736,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;
@@ -867,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 = get_character_len(*fp);
-    if(skip != 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, '/', '\\');
 }
 
 
@@ -1219,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;
 
@@ -1307,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"))
@@ -1367,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;
@@ -1382,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)
@@ -1409,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;
 }
 
 /****************************************************************************
@@ -1462,7 +1437,7 @@ int process_tar(void)
 #else
     do_tarput();
 #endif
-    free(tarbuf);
+    SAFE_FREE(tarbuf);
     close(tarhandle);
     break;
   case 'r':
@@ -1478,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));
@@ -1490,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);
@@ -1512,7 +1487,7 @@ int process_tar(void)
     
     if (ntarf) dotareof(tarhandle);
     close(tarhandle);
-    free(tarbuf);
+    SAFE_FREE(tarbuf);
     
     DEBUG(0, ("tar: dumped %d files and directories\n", ntarf));
     DEBUG(0, ("Total bytes written: %.0f\n", (double)ttarf));
@@ -1522,9 +1497,9 @@ int process_tar(void)
   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;
@@ -1541,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;
   }
@@ -1561,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;
@@ -1573,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.
      */
@@ -1581,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) {
@@ -1596,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 */
@@ -1631,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();
          }
@@ -1642,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;
     }
@@ -1708,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))));
@@ -1853,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))
       {