source: branches/samba-3.5.x/source4/torture/smbiconv.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 16 years ago

Samba 3.5.0: Initial import

File size: 5.5 KB
Line 
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
25static 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, ("\
68incomplete 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
86static 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
165int 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}
Note: See TracBrowser for help on using the repository browser.