~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/smbiconv.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
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)
 
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[])
 
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
}