s3:idmap_autorid: add an allocation range to autorid
[Samba/gebeck_regimport.git] / source3 / torture / smbiconv.c
blob88ad6fef60976f69d5a317d515670d4cf5e15932
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 "system/filesys.h"
25 #include "popt_common.h"
26 #undef realloc
28 static int
29 process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output)
31 #define OUTBUF_SIZE 32768
32 const char *start = addr;
33 char outbuf[OUTBUF_SIZE];
34 char *outptr;
35 size_t outlen;
36 size_t n;
38 while (len > 0)
40 outptr = outbuf;
41 outlen = OUTBUF_SIZE;
42 n = smb_iconv (cd, &addr, &len, &outptr, &outlen);
44 if (outptr != outbuf)
46 /* We have something to write out. */
47 int errno_save = errno;
49 if (fwrite (outbuf, 1, outptr - outbuf, output)
50 < (size_t) (outptr - outbuf)
51 || ferror (output))
53 /* Error occurred while printing the result. */
54 DEBUG (0, ("conversion stopped due to problem in writing the output"));
55 return -1;
58 errno = errno_save;
61 if (errno != E2BIG)
63 /* iconv() ran into a problem. */
64 switch (errno)
66 case EILSEQ:
67 DEBUG(0,("illegal input sequence at position %ld",
68 (long) (addr - start)));
69 break;
70 case EINVAL:
71 DEBUG(0, ("\
72 incomplete character or shift sequence at end of buffer"));
73 break;
74 case EBADF:
75 DEBUG(0, ("internal error (illegal descriptor)"));
76 break;
77 default:
78 DEBUG(0, ("unknown iconv() error %d", errno));
79 break;
82 return -1;
86 return 0;
90 static int
91 process_fd (smb_iconv_t cd, int fd, FILE *output)
93 /* we have a problem with reading from a descriptor since we must not
94 provide the iconv() function an incomplete character or shift
95 sequence at the end of the buffer. Since we have to deal with
96 arbitrary encodings we must read the whole text in a buffer and
97 process it in one step. */
98 static char *inbuf = NULL;
99 static size_t maxlen = 0;
100 char *inptr = NULL;
101 size_t actlen = 0;
103 while (actlen < maxlen)
105 ssize_t n = read (fd, inptr, maxlen - actlen);
107 if (n == 0)
108 /* No more text to read. */
109 break;
111 if (n == -1)
113 /* Error while reading. */
114 DEBUG(0, ("error while reading the input"));
115 return -1;
118 inptr += n;
119 actlen += n;
122 if (actlen == maxlen)
123 while (1)
125 ssize_t n;
126 char *new_inbuf;
128 /* Increase the buffer. */
129 new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
130 if (new_inbuf == NULL)
132 DEBUG(0, ("unable to allocate buffer for input"));
133 return -1;
135 inbuf = new_inbuf;
136 maxlen += 32768;
137 inptr = inbuf + actlen;
141 n = read (fd, inptr, maxlen - actlen);
143 if (n == 0)
144 /* No more text to read. */
145 break;
147 if (n == -1)
149 /* Error while reading. */
150 DEBUG(0, ("error while reading the input"));
151 return -1;
154 inptr += n;
155 actlen += n;
157 while (actlen < maxlen);
159 if (n == 0)
160 /* Break again so we leave both loops. */
161 break;
164 /* Now we have all the input in the buffer. Process it in one run. */
165 return process_block (cd, inbuf, actlen, output);
168 /* Main function */
170 int main(int argc, char *argv[])
172 const char *file = NULL;
173 const char *from = "";
174 const char *to = "";
175 char *output = NULL;
176 const char *preload_modules[] = {NULL, NULL};
177 FILE *out = stdout;
178 int fd;
179 smb_iconv_t cd;
181 /* make sure the vars that get altered (4th field) are in
182 a fixed location or certain compilers complain */
183 poptContext pc;
184 struct poptOption long_options[] = {
185 POPT_AUTOHELP
186 { "from-code", 'f', POPT_ARG_STRING, &from, 0, "Encoding of original text" },
187 { "to-code", 't', POPT_ARG_STRING, &to, 0, "Encoding for output" },
188 { "output", 'o', POPT_ARG_STRING, &output, 0, "Write output to this file" },
189 { "preload-modules", 'p', POPT_ARG_STRING, &preload_modules[0], 0, "Modules to load" },
190 POPT_COMMON_SAMBA
191 POPT_TABLEEND
194 setlinebuf(stdout);
196 pc = poptGetContext("smbiconv", argc, (const char **) argv,
197 long_options, 0);
199 poptSetOtherOptionHelp(pc, "[FILE] ...");
201 while(poptGetNextOpt(pc) != -1);
203 /* the following functions are part of the Samba debugging
204 facilities. See lib/debug.c */
205 setup_logging("smbiconv", DEBUG_STDOUT);
207 if (preload_modules[0]) smb_load_modules(preload_modules);
209 if(output) {
210 out = fopen(output, "w");
212 if(!out) {
213 DEBUG(0, ("Can't open output file '%s': %s, exiting...\n", output, strerror(errno)));
214 return 1;
218 cd = smb_iconv_open(to, from);
219 if (cd == (smb_iconv_t)-1) {
220 DEBUG(0,("unable to find from or to encoding, exiting...\n"));
221 if (out != stdout) fclose(out);
222 return 1;
225 while((file = poptGetArg(pc))) {
226 if(strcmp(file, "-") == 0) fd = 0;
227 else {
228 fd = open(file, O_RDONLY);
230 if(!fd) {
231 DEBUG(0, ("Can't open input file '%s': %s, ignoring...\n", file, strerror(errno)));
232 continue;
236 /* Loop thru all arguments */
237 process_fd(cd, fd, out);
239 close(fd);
241 poptFreeContext(pc);
243 fclose(out);
245 return 0;