source: vendor/3.5.0/source3/torture/smbiconv.c

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

Samba 3.5.0: Initial import

File size: 5.6 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#undef realloc
25
26static int
27process_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, ("\
70incomplete 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
88static int
89process_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
168int 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}
Note: See TracBrowser for help on using the repository browser.