r21325: delete children in reverse order since the array is manipulated during the...
[Samba.git] / source4 / torture / smbiconv.c
blob02f053395d67514d370ee1515d414ef69803f6ba
1 /*
2 Unix SMB/CIFS implementation.
3 Charset module tester
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.
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 2 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 static int process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output)
28 #define OUTBUF_SIZE 32768
29 const char *start = addr;
30 char outbuf[OUTBUF_SIZE];
31 char *outptr;
32 size_t outlen;
33 size_t n;
35 while (len > 0)
37 outptr = outbuf;
38 outlen = OUTBUF_SIZE;
39 n = smb_iconv (cd, &addr, &len, &outptr, &outlen);
41 if (outptr != outbuf)
43 /* We have something to write out. */
44 int errno_save = errno;
46 if (fwrite (outbuf, 1, outptr - outbuf, output)
47 < (size_t) (outptr - outbuf)
48 || ferror (output))
50 /* Error occurred while printing the result. */
51 DEBUG (0, ("conversion stopped due to problem in writing the output"));
52 return -1;
55 errno = errno_save;
58 if (errno != E2BIG)
60 /* iconv() ran into a problem. */
61 switch (errno)
63 case EILSEQ:
64 DEBUG(0,("illegal input sequence at position %ld",
65 (long) (addr - start)));
66 break;
67 case EINVAL:
68 DEBUG(0, ("\
69 incomplete character or shift sequence at end of buffer"));
70 break;
71 case EBADF:
72 DEBUG(0, ("internal error (illegal descriptor)"));
73 break;
74 default:
75 DEBUG(0, ("unknown iconv() error %d", errno));
76 break;
79 return -1;
83 return 0;
87 static int process_fd (iconv_t cd, int fd, FILE *output)
89 /* we have a problem with reading from a descriptor since we must not
90 provide the iconv() function an incomplete character or shift
91 sequence at the end of the buffer. Since we have to deal with
92 arbitrary encodings we must read the whole text in a buffer and
93 process it in one step. */
94 static char *inbuf = NULL;
95 static size_t maxlen = 0;
96 char *inptr = NULL;
97 size_t actlen = 0;
99 while (actlen < maxlen)
101 ssize_t n = read (fd, inptr, maxlen - actlen);
103 if (n == 0)
104 /* No more text to read. */
105 break;
107 if (n == -1)
109 /* Error while reading. */
110 DEBUG(0, ("error while reading the input"));
111 return -1;
114 inptr += n;
115 actlen += n;
118 if (actlen == maxlen)
119 while (1)
121 ssize_t n;
122 char *new_inbuf;
124 /* Increase the buffer. */
125 new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
126 if (new_inbuf == NULL)
128 DEBUG(0, ("unable to allocate buffer for input"));
129 return -1;
131 inbuf = new_inbuf;
132 maxlen += 32768;
133 inptr = inbuf + actlen;
137 n = read (fd, inptr, maxlen - actlen);
139 if (n == 0)
140 /* No more text to read. */
141 break;
143 if (n == -1)
145 /* Error while reading. */
146 DEBUG(0, ("error while reading the input"));
147 return -1;
150 inptr += n;
151 actlen += n;
153 while (actlen < maxlen);
155 if (n == 0)
156 /* Break again so we leave both loops. */
157 break;
160 /* Now we have all the input in the buffer. Process it in one run. */
161 return process_block (cd, inbuf, actlen, output);
164 /* Main function */
166 int main(int argc, char *argv[])
168 const char *file = NULL;
169 char *from = "";
170 char *to = "";
171 char *output = NULL;
172 const char *preload_modules[] = {NULL, NULL};
173 FILE *out = stdout;
174 int fd;
175 smb_iconv_t cd;
177 /* make sure the vars that get altered (4th field) are in
178 a fixed location or certain compilers complain */
179 poptContext pc;
180 struct poptOption long_options[] = {
181 POPT_AUTOHELP
182 { "from-code", 'f', POPT_ARG_STRING, &from, 0, "Encoding of original text" },
183 { "to-code", 't', POPT_ARG_STRING, &to, 0, "Encoding for output" },
184 { "output", 'o', POPT_ARG_STRING, &output, 0, "Write output to this file" },
185 { "preload-modules", 'p', POPT_ARG_STRING, &preload_modules[0], 0, "Modules to load" },
186 { NULL }
189 setlinebuf(stdout);
191 pc = poptGetContext("smbiconv", argc, (const char **) argv,
192 long_options, 0);
194 poptSetOtherOptionHelp(pc, "[FILE] ...");
196 while(poptGetNextOpt(pc) != -1);
198 if (preload_modules[0]) smb_load_modules(preload_modules);
200 if(output) {
201 out = fopen(output, "w");
203 if(!out) {
204 DEBUG(0, ("Can't open output file '%s': %s, exiting...\n", output, strerror(errno)));
205 return 1;
209 cd = smb_iconv_open(to, from);
210 if((int)cd == -1) {
211 DEBUG(0,("unable to find from or to encoding, exiting...\n"));
212 return 1;
215 while((file = poptGetArg(pc))) {
216 if(strcmp(file, "-") == 0) fd = 0;
217 else {
218 fd = open(file, O_RDONLY);
220 if(!fd) {
221 DEBUG(0, ("Can't open input file '%s': %s, ignoring...\n", file, strerror(errno)));
222 continue;
226 /* Loop thru all arguments */
227 process_fd(cd, fd, out);
229 close(fd);
231 poptFreeContext(pc);
233 fclose(out);
235 return 0;