root/source3/torture/smbiconv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. process_block
  2. process_fd
  3. main

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    Charset module tester
   4 
   5    Copyright (C) Jelmer Vernooij 2003
   6    Based on iconv/icon_prog.c from the GNU C Library, 
   7       Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
   8 
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 #undef realloc
  25 
  26 static int
  27 process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output)
     /* [<][>][^][v][top][bottom][index][help] */
  28 {
  29 #define OUTBUF_SIZE     32768
  30   const char *start = addr;
  31   char outbuf[OUTBUF_SIZE];
  32   char *outptr;
  33   size_t outlen;
  34   size_t n;
  35 
  36   while (len > 0)
  37     {
  38       outptr = outbuf;
  39       outlen = OUTBUF_SIZE;
  40       n = smb_iconv (cd,  &addr, &len, &outptr, &outlen);
  41 
  42       if (outptr != outbuf)
  43         {
  44           /* We have something to write out.  */
  45           int errno_save = errno;
  46 
  47           if (fwrite (outbuf, 1, outptr - outbuf, output)
  48               < (size_t) (outptr - outbuf)
  49               || ferror (output))
  50             {
  51               /* Error occurred while printing the result.  */
  52               DEBUG (0, ("conversion stopped due to problem in writing the output"));
  53               return -1;
  54             }
  55 
  56           errno = errno_save;
  57         }
  58 
  59       if (errno != E2BIG)
  60         {
  61           /* iconv() ran into a problem.  */
  62           switch (errno)
  63             {
  64             case EILSEQ:
  65               DEBUG(0,("illegal input sequence at position %ld", 
  66                      (long) (addr - start)));
  67               break;
  68             case EINVAL:
  69               DEBUG(0, ("\
  70 incomplete character or shift sequence at end of buffer"));
  71               break;
  72             case EBADF:
  73               DEBUG(0, ("internal error (illegal descriptor)"));
  74               break;
  75             default:
  76               DEBUG(0, ("unknown iconv() error %d", errno));
  77               break;
  78             }
  79 
  80           return -1;
  81         }
  82     }
  83 
  84   return 0;
  85 }
  86 
  87 
  88 static int
  89 process_fd (smb_iconv_t cd, int fd, FILE *output)
     /* [<][>][^][v][top][bottom][index][help] */
  90 {
  91   /* we have a problem with reading from a descriptor since we must not
  92      provide the iconv() function an incomplete character or shift
  93      sequence at the end of the buffer.  Since we have to deal with
  94      arbitrary encodings we must read the whole text in a buffer and
  95      process it in one step.  */
  96   static char *inbuf = NULL;
  97   static size_t maxlen = 0;
  98   char *inptr = NULL;
  99   size_t actlen = 0;
 100 
 101   while (actlen < maxlen)
 102     {
 103       ssize_t n = read (fd, inptr, maxlen - actlen);
 104 
 105       if (n == 0)
 106         /* No more text to read.  */
 107         break;
 108 
 109       if (n == -1)
 110         {
 111           /* Error while reading.  */
 112           DEBUG(0, ("error while reading the input"));
 113           return -1;
 114         }
 115 
 116       inptr += n;
 117       actlen += n;
 118     }
 119 
 120   if (actlen == maxlen)
 121     while (1)
 122       {
 123         ssize_t n;
 124         char *new_inbuf;
 125 
 126         /* Increase the buffer.  */
 127         new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
 128         if (new_inbuf == NULL)
 129           {
 130             DEBUG(0, ("unable to allocate buffer for input"));
 131             return -1;
 132           }
 133         inbuf = new_inbuf;
 134         maxlen += 32768;
 135         inptr = inbuf + actlen;
 136 
 137         do
 138           {
 139             n = read (fd, inptr, maxlen - actlen);
 140 
 141             if (n == 0)
 142               /* No more text to read.  */
 143               break;
 144 
 145             if (n == -1)
 146               {
 147                 /* Error while reading.  */
 148                 DEBUG(0, ("error while reading the input"));
 149                 return -1;
 150               }
 151 
 152             inptr += n;
 153             actlen += n;
 154           }
 155         while (actlen < maxlen);
 156 
 157         if (n == 0)
 158           /* Break again so we leave both loops.  */
 159           break;
 160       }
 161 
 162   /* Now we have all the input in the buffer.  Process it in one run.  */
 163   return process_block (cd, inbuf, actlen, output);
 164 }
 165 
 166 /* Main function */
 167 
 168 int main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 169 {
 170         const char *file = NULL;
 171         const char *from = "";
 172         const char *to = "";
 173         char *output = NULL;
 174         const char *preload_modules[] = {NULL, NULL};
 175         FILE *out = stdout;
 176         int fd;
 177         smb_iconv_t cd;
 178 
 179         /* make sure the vars that get altered (4th field) are in
 180            a fixed location or certain compilers complain */
 181         poptContext pc;
 182         struct poptOption long_options[] = {
 183                 POPT_AUTOHELP
 184                 { "from-code", 'f', POPT_ARG_STRING, &from, 0, "Encoding of original text" },
 185                 { "to-code", 't', POPT_ARG_STRING, &to, 0, "Encoding for output" },
 186                 { "output", 'o', POPT_ARG_STRING, &output, 0, "Write output to this file" },
 187                 { "preload-modules", 'p', POPT_ARG_STRING, &preload_modules[0], 0, "Modules to load" },
 188                 POPT_COMMON_SAMBA
 189                 POPT_TABLEEND
 190         };
 191 
 192         setlinebuf(stdout);
 193 
 194         pc = poptGetContext("smbiconv", argc, (const char **) argv,
 195                             long_options, 0);
 196 
 197         poptSetOtherOptionHelp(pc, "[FILE] ...");
 198         
 199         while(poptGetNextOpt(pc) != -1);
 200 
 201         /* the following functions are part of the Samba debugging
 202            facilities.  See lib/debug.c */
 203         setup_logging("smbiconv", True);
 204 
 205         if (preload_modules[0]) smb_load_modules(preload_modules);
 206 
 207         if(output) {
 208                 out = fopen(output, "w");
 209 
 210                 if(!out) {
 211                         DEBUG(0, ("Can't open output file '%s': %s, exiting...\n", output, strerror(errno)));
 212                         return 1;
 213                 }
 214         }
 215 
 216         cd = smb_iconv_open(to, from);
 217         if (cd == (smb_iconv_t)-1) {
 218                 DEBUG(0,("unable to find from or to encoding, exiting...\n"));
 219                 if (out != stdout) fclose(out);
 220                 return 1;
 221         }
 222 
 223         while((file = poptGetArg(pc))) {
 224                 if(strcmp(file, "-") == 0) fd = 0;
 225                 else {
 226                         fd = open(file, O_RDONLY);
 227                         
 228                         if(!fd) {
 229                                 DEBUG(0, ("Can't open input file '%s': %s, ignoring...\n", file, strerror(errno)));
 230                                 continue;
 231                         }
 232                 }
 233 
 234                 /* Loop thru all arguments */
 235                 process_fd(cd, fd, out);
 236 
 237                 close(fd);
 238         }
 239         poptFreeContext(pc);
 240 
 241         fclose(out);
 242 
 243         return 0;
 244 }

/* [<][>][^][v][top][bottom][index][help] */