~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/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
#undef realloc
 
25
 
 
26
static int
 
27
process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output)
 
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)
 
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[])
 
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
}