root/source4/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 
  25 static int process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output)
     /* [<][>][^][v][top][bottom][index][help] */
  26 {
  27 #define OUTBUF_SIZE     32768
  28   const char *start = addr;
  29   char outbuf[OUTBUF_SIZE];
  30   char *outptr;
  31   size_t outlen;
  32   size_t n;
  33 
  34   while (len > 0)
  35     {
  36       outptr = outbuf;
  37       outlen = OUTBUF_SIZE;
  38       n = smb_iconv (cd,  &addr, &len, &outptr, &outlen);
  39 
  40       if (outptr != outbuf)
  41         {
  42           /* We have something to write out.  */
  43           int errno_save = errno;
  44 
  45           if (fwrite (outbuf, 1, outptr - outbuf, output)
  46               < (size_t) (outptr - outbuf)
  47               || ferror (output))
  48             {
  49               /* Error occurred while printing the result.  */
  50               DEBUG (0, ("conversion stopped due to problem in writing the output"));
  51               return -1;
  52             }
  53 
  54           errno = errno_save;
  55         }
  56 
  57       if (errno != E2BIG)
  58         {
  59           /* iconv() ran into a problem.  */
  60           switch (errno)
  61             {
  62             case EILSEQ:
  63               DEBUG(0,("illegal input sequence at position %ld", 
  64                      (long) (addr - start)));
  65               break;
  66             case EINVAL:
  67               DEBUG(0, ("\
  68 incomplete character or shift sequence at end of buffer"));
  69               break;
  70             case EBADF:
  71               DEBUG(0, ("internal error (illegal descriptor)"));
  72               break;
  73             default:
  74               DEBUG(0, ("unknown iconv() error %d", errno));
  75               break;
  76             }
  77 
  78           return -1;
  79         }
  80     }
  81 
  82   return 0;
  83 }
  84 
  85 
  86 static int process_fd (iconv_t cd, int fd, FILE *output)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88   /* we have a problem with reading from a descriptor since we must not
  89      provide the iconv() function an incomplete character or shift
  90      sequence at the end of the buffer.  Since we have to deal with
  91      arbitrary encodings we must read the whole text in a buffer and
  92      process it in one step.  */
  93   static char *inbuf = NULL;
  94   static size_t maxlen = 0;
  95   char *inptr = NULL;
  96   size_t actlen = 0;
  97 
  98   while (actlen < maxlen)
  99     {
 100       ssize_t n = read (fd, inptr, maxlen - actlen);
 101 
 102       if (n == 0)
 103         /* No more text to read.  */
 104         break;
 105 
 106       if (n == -1)
 107         {
 108           /* Error while reading.  */
 109           DEBUG(0, ("error while reading the input"));
 110           return -1;
 111         }
 112 
 113       inptr += n;
 114       actlen += n;
 115     }
 116 
 117   if (actlen == maxlen)
 118     while (1)
 119       {
 120         ssize_t n;
 121         char *new_inbuf;
 122 
 123         /* Increase the buffer.  */
 124         new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
 125         if (new_inbuf == NULL)
 126           {
 127             DEBUG(0, ("unable to allocate buffer for input"));
 128             return -1;
 129           }
 130         inbuf = new_inbuf;
 131         maxlen += 32768;
 132         inptr = inbuf + actlen;
 133 
 134         do
 135           {
 136             n = read (fd, inptr, maxlen - actlen);
 137 
 138             if (n == 0)
 139               /* No more text to read.  */
 140               break;
 141 
 142             if (n == -1)
 143               {
 144                 /* Error while reading.  */
 145                 DEBUG(0, ("error while reading the input"));
 146                 return -1;
 147               }
 148 
 149             inptr += n;
 150             actlen += n;
 151           }
 152         while (actlen < maxlen);
 153 
 154         if (n == 0)
 155           /* Break again so we leave both loops.  */
 156           break;
 157       }
 158 
 159   /* Now we have all the input in the buffer.  Process it in one run.  */
 160   return process_block (cd, inbuf, actlen, output);
 161 }
 162 
 163 /* Main function */
 164 
 165 int main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 166 {
 167         const char *file = NULL;
 168         char *from = "";
 169         char *to = "";
 170         char *output = NULL;
 171         const char *preload_modules[] = {NULL, NULL};
 172         FILE *out = stdout;
 173         int fd;
 174         smb_iconv_t cd;
 175 
 176         /* make sure the vars that get altered (4th field) are in
 177            a fixed location or certain compilers complain */
 178         poptContext pc;
 179         struct poptOption long_options[] = {
 180                 POPT_AUTOHELP
 181                 { "from-code", 'f', POPT_ARG_STRING, &from, 0, "Encoding of original text" },
 182                 { "to-code", 't', POPT_ARG_STRING, &to, 0, "Encoding for output" },
 183                 { "output", 'o', POPT_ARG_STRING, &output, 0, "Write output to this file" },
 184                 { "preload-modules", 'p', POPT_ARG_STRING, &preload_modules[0], 0, "Modules to load" },
 185                 { NULL }
 186         };
 187 
 188         setlinebuf(stdout);
 189 
 190         pc = poptGetContext("smbiconv", argc, (const char **) argv,
 191                             long_options, 0);
 192 
 193         poptSetOtherOptionHelp(pc, "[FILE] ...");
 194         
 195         while(poptGetNextOpt(pc) != -1);
 196 
 197         if (preload_modules[0]) smb_load_modules(preload_modules);
 198 
 199         if(output) {
 200                 out = fopen(output, "w");
 201 
 202                 if(!out) {
 203                         DEBUG(0, ("Can't open output file '%s': %s, exiting...\n", output, strerror(errno)));
 204                         return 1;
 205                 }
 206         }
 207 
 208         cd = smb_iconv_open_ex(tctx, to, from, lp_parm_bool(tctx->lp_ctx, NULL, "iconv", "native", true));
 209         if((int)cd == -1) {
 210                 DEBUG(0,("unable to find from or to encoding, exiting...\n"));
 211                 if (out != stdout) fclose(out);
 212                 return 1;
 213         }
 214 
 215         while((file = poptGetArg(pc))) {
 216                 if(strcmp(file, "-") == 0) fd = 0;
 217                 else {
 218                         fd = open(file, O_RDONLY);
 219                         
 220                         if(!fd) {
 221                                 DEBUG(0, ("Can't open input file '%s': %s, ignoring...\n", file, strerror(errno)));
 222                                 continue;
 223                         }
 224                 }
 225 
 226                 /* Loop thru all arguments */
 227                 process_fd(cd, fd, out);
 228 
 229                 close(fd);
 230         }
 231         poptFreeContext(pc);
 232 
 233         fclose(out);
 234 
 235         return 0;
 236 }

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