s3-net: add command registry convert
[Samba.git] / source3 / torture / smbiconv.c
blobd5d580c30be0ec21b614a50269ce564aaf8d7c2d
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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "popt_common.h"
25 #undef realloc
27 static int
28 process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output)
30 #define OUTBUF_SIZE 32768
31 const char *start = addr;
32 char outbuf[OUTBUF_SIZE];
33 char *outptr;
34 size_t outlen;
35 size_t n;
37 while (len > 0)
39 outptr = outbuf;
40 outlen = OUTBUF_SIZE;
41 n = smb_iconv (cd, &addr, &len, &outptr, &outlen);
43 if (outptr != outbuf)
45 /* We have something to write out. */
46 int errno_save = errno;
48 if (fwrite (outbuf, 1, outptr - outbuf, output)
49 < (size_t) (outptr - outbuf)
50 || ferror (output))
52 /* Error occurred while printing the result. */
53 DEBUG (0, ("conversion stopped due to problem in writing the output"));
54 return -1;
57 errno = errno_save;
60 if (errno != E2BIG)
62 /* iconv() ran into a problem. */
63 switch (errno)
65 case EILSEQ:
66 DEBUG(0,("illegal input sequence at position %ld",
67 (long) (addr - start)));
68 break;
69 case EINVAL:
70 DEBUG(0, ("\
71 incomplete character or shift sequence at end of buffer"));
72 break;
73 case EBADF:
74 DEBUG(0, ("internal error (illegal descriptor)"));
75 break;
76 default:
77 DEBUG(0, ("unknown iconv() error %d", errno));
78 break;
81 return -1;
85 return 0;
89 static int
90 process_fd (smb_iconv_t cd, int fd, FILE *output)
92 /* we have a problem with reading from a descriptor since we must not
93 provide the iconv() function an incomplete character or shift
94 sequence at the end of the buffer. Since we have to deal with
95 arbitrary encodings we must read the whole text in a buffer and
96 process it in one step. */
97 static char *inbuf = NULL;
98 static size_t maxlen = 0;
99 char *inptr = NULL;
100 size_t actlen = 0;
102 while (actlen < maxlen)
104 ssize_t n = read (fd, inptr, maxlen - actlen);
106 if (n == 0)
107 /* No more text to read. */
108 break;
110 if (n == -1)
112 /* Error while reading. */
113 DEBUG(0, ("error while reading the input"));
114 return -1;
117 inptr += n;
118 actlen += n;
121 if (actlen == maxlen)
122 while (1)
124 ssize_t n;
125 char *new_inbuf;
127 /* Increase the buffer. */
128 new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
129 if (new_inbuf == NULL)
131 DEBUG(0, ("unable to allocate buffer for input"));
132 return -1;
134 inbuf = new_inbuf;
135 maxlen += 32768;
136 inptr = inbuf + actlen;
140 n = read (fd, inptr, maxlen - actlen);
142 if (n == 0)
143 /* No more text to read. */
144 break;
146 if (n == -1)
148 /* Error while reading. */
149 DEBUG(0, ("error while reading the input"));
150 return -1;
153 inptr += n;
154 actlen += n;
156 while (actlen < maxlen);
158 if (n == 0)
159 /* Break again so we leave both loops. */
160 break;
163 /* Now we have all the input in the buffer. Process it in one run. */
164 return process_block (cd, inbuf, actlen, output);
167 /* Main function */
169 int main(int argc, char *argv[])
171 const char *file = NULL;
172 const char *from = "";
173 const char *to = "";
174 char *output = NULL;
175 const char *preload_modules[] = {NULL, NULL};
176 FILE *out = stdout;
177 int fd;
178 smb_iconv_t cd;
180 /* make sure the vars that get altered (4th field) are in
181 a fixed location or certain compilers complain */
182 poptContext pc;
183 struct poptOption long_options[] = {
184 POPT_AUTOHELP
185 { "from-code", 'f', POPT_ARG_STRING, &from, 0, "Encoding of original text" },
186 { "to-code", 't', POPT_ARG_STRING, &to, 0, "Encoding for output" },
187 { "output", 'o', POPT_ARG_STRING, &output, 0, "Write output to this file" },
188 { "preload-modules", 'p', POPT_ARG_STRING, &preload_modules[0], 0, "Modules to load" },
189 POPT_COMMON_SAMBA
190 POPT_TABLEEND
193 setlinebuf(stdout);
195 pc = poptGetContext("smbiconv", argc, (const char **) argv,
196 long_options, 0);
198 poptSetOtherOptionHelp(pc, "[FILE] ...");
200 while(poptGetNextOpt(pc) != -1);
202 /* the following functions are part of the Samba debugging
203 facilities. See lib/debug.c */
204 setup_logging("smbiconv", True);
206 if (preload_modules[0]) smb_load_modules(preload_modules);
208 if(output) {
209 out = fopen(output, "w");
211 if(!out) {
212 DEBUG(0, ("Can't open output file '%s': %s, exiting...\n", output, strerror(errno)));
213 return 1;
217 cd = smb_iconv_open(to, from);
218 if (cd == (smb_iconv_t)-1) {
219 DEBUG(0,("unable to find from or to encoding, exiting...\n"));
220 if (out != stdout) fclose(out);
221 return 1;
224 while((file = poptGetArg(pc))) {
225 if(strcmp(file, "-") == 0) fd = 0;
226 else {
227 fd = open(file, O_RDONLY);
229 if(!fd) {
230 DEBUG(0, ("Can't open input file '%s': %s, ignoring...\n", file, strerror(errno)));
231 continue;
235 /* Loop thru all arguments */
236 process_fd(cd, fd, out);
238 close(fd);
240 poptFreeContext(pc);
242 fclose(out);
244 return 0;