common: Fix typo.
[gnupg.git] / common / t-zb32.c
1 /* t-zb32.c - Module tests for zb32.c
2  * Copyright (C) 2014  Werner Koch
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <https://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #ifdef HAVE_DOSISH_SYSTEM
38 # include <fcntl.h>
39 #endif
40
41 #include "zb32.h"
42 #include "t-support.h"
43
44 #define PGM "t-zb32"
45
46 static int verbose;
47 static int debug;
48 static int errcount;
49
50
51 static void
52 test_zb32enc (void)
53 {
54   static struct {
55     size_t datalen;
56     char *data;
57     const char *expected;
58   } tests[] = {
59     /* From the DESIGN document.  */
60     {  1, "\x00", "y" },
61     {  1, "\x80", "o" },
62     {  2, "\x40", "e" },
63     {  2, "\xc0", "a" },
64     { 10, "\x00\x00", "yy" },
65     { 10, "\x80\x80", "on" },
66     { 20, "\x8b\x88\x80", "tqre" },
67     { 24, "\xf0\xbf\xc7", "6n9hq" },
68     { 24, "\xd4\x7a\x04", "4t7ye" },
69     /* The next vector is strange: The DESIGN document from 2007 gives
70        "8ik66o" as result, the revision from 2009 gives "6im5sd".  I
71        look at it for quite some time and came to the conclusion that
72        "6im54d" is the right encoding.  */
73     { 30, "\xf5\x57\xbd\x0c", "6im54d" },
74     /* From ccrtp's Java code.  */
75     { 40, "\x01\x01\x01\x01\x01", "yryonyeb" },
76     { 15, "\x01\x01", "yry" },
77     { 80, "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", "yryonyebyryonyeb" },
78     { 15, "\x81\x81", "ogy" },
79     { 16, "\x81\x81", "ogyo" },
80     { 20, "\x81\x81\x81", "ogya" },
81     { 64, "\x81\x81\x81\x81\x81\x81\x81\x81", "ogyadycbogyan" },
82     /* More tests.  */
83     { 160, "\x80\x61\x58\x70\xF5\xBA\xD6\x90\x33\x36"
84       /* */"\x86\xD0\xF2\xAD\x85\xAC\x1E\x42\xB3\x67",
85       /* */"oboioh8izmmjyc3so5exfmcfioxrfc58" },
86     { 0,  "", "" }
87   };
88   int tidx;
89   char *output;
90
91   for (tidx = 0; tidx < DIM(tests); tidx++)
92     {
93       output = zb32_encode (tests[tidx].data, tests[tidx].datalen);
94       if (!output)
95         {
96           fprintf (stderr, PGM": error encoding test %d: %s\n",
97                    tidx, strerror (errno));
98           exit (1);
99         }
100       /* puts (output); */
101       if (strcmp (output, tests[tidx].expected))
102         fail (tidx);
103       xfree (output);
104     }
105 }
106
107
108 /* Read the file FNAME or stdin if FNAME is NULL and return a malloced
109    buffer with the content.  R_LENGTH received the length of the file.
110    Print a diagnostic and returns NULL on error.  */
111 static char *
112 read_file (const char *fname, size_t *r_length)
113 {
114   FILE *fp;
115   char *buf;
116   size_t buflen;
117
118   if (!fname)
119     {
120       size_t nread, bufsize = 0;
121
122       fp = stdin;
123 #ifdef HAVE_DOSISH_SYSTEM
124       setmode (fileno(fp) , O_BINARY );
125 #endif
126       buf = NULL;
127       buflen = 0;
128 #define NCHUNK 8192
129       do
130         {
131           bufsize += NCHUNK;
132           if (!buf)
133             buf = xmalloc (bufsize);
134           else
135             buf = xrealloc (buf, bufsize);
136
137           nread = fread (buf+buflen, 1, NCHUNK, fp);
138           if (nread < NCHUNK && ferror (fp))
139             {
140               fprintf (stderr, PGM": error reading '[stdin]': %s\n",
141                        strerror (errno));
142               xfree (buf);
143               return NULL;
144             }
145           buflen += nread;
146         }
147       while (nread == NCHUNK);
148 #undef NCHUNK
149
150     }
151   else
152     {
153       struct stat st;
154
155       fp = fopen (fname, "rb");
156       if (!fp)
157         {
158           fprintf (stderr, PGM": can't open '%s': %s\n",
159                    fname, strerror (errno));
160           return NULL;
161         }
162
163       if (fstat (fileno(fp), &st))
164         {
165           fprintf (stderr, PGM": can't stat '%s': %s\n",
166                    fname, strerror (errno));
167           fclose (fp);
168           return NULL;
169         }
170
171       buflen = st.st_size;
172       buf = xmalloc (buflen+1);
173       if (fread (buf, buflen, 1, fp) != 1)
174         {
175           fprintf (stderr, PGM": error reading '%s': %s\n",
176                    fname, strerror (errno));
177           fclose (fp);
178           xfree (buf);
179           return NULL;
180         }
181       fclose (fp);
182     }
183
184   *r_length = buflen;
185   return buf;
186 }
187
188
189 /* Debug helper to encode or decode to/from zb32.  */
190 static void
191 endecode_file (const char *fname, int decode)
192 {
193   char *buffer;
194   size_t buflen;
195   char *result;
196
197   if (decode)
198     {
199       fprintf (stderr, PGM": decode mode has not yet been implemented\n");
200       errcount++;
201       return;
202     }
203
204 #ifdef HAVE_DOSISH_SYSTEM
205   if (decode)
206     setmode (fileno (stdout), O_BINARY);
207 #endif
208
209
210   buffer = read_file (fname, &buflen);
211   if (!buffer)
212     {
213       errcount++;
214       return;
215     }
216
217   result = zb32_encode (buffer, 8 * buflen);
218   if (!result)
219     {
220       fprintf (stderr, PGM": error encoding data: %s\n", strerror (errno));
221       errcount++;
222       xfree (buffer);
223       return;
224     }
225
226   fputs (result, stdout);
227   putchar ('\n');
228
229   xfree (result);
230   xfree (buffer);
231 }
232
233
234 int
235 main (int argc, char **argv)
236 {
237   int last_argc = -1;
238   int opt_endecode = 0;
239
240   no_exit_on_fail = 1;
241
242   if (argc)
243     { argc--; argv++; }
244   while (argc && last_argc != argc )
245     {
246       last_argc = argc;
247       if (!strcmp (*argv, "--"))
248         {
249           argc--; argv++;
250           break;
251         }
252       else if (!strcmp (*argv, "--help"))
253         {
254           fputs ("usage: " PGM " [FILE]\n"
255                  "Options:\n"
256                  "  --verbose         Print timings etc.\n"
257                  "  --debug           Flyswatter\n"
258                  "  --encode          Encode FILE or stdin\n"
259                  "  --decode          Decode FILE or stdin\n"
260                  , stdout);
261           exit (0);
262         }
263       else if (!strcmp (*argv, "--verbose"))
264         {
265           verbose++;
266           argc--; argv++;
267         }
268       else if (!strcmp (*argv, "--debug"))
269         {
270           verbose += 2;
271           debug++;
272           argc--; argv++;
273         }
274       else if (!strcmp (*argv, "--encode"))
275         {
276           opt_endecode = 1;
277           argc--; argv++;
278         }
279       else if (!strcmp (*argv, "--decode"))
280         {
281           opt_endecode = -1;
282           argc--; argv++;
283         }
284       else if (!strncmp (*argv, "--", 2))
285         {
286           fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
287           exit (1);
288         }
289     }
290
291   if (argc > 1)
292     {
293       fprintf (stderr, PGM ": to many arguments given\n");
294       exit (1);
295     }
296
297   if (opt_endecode)
298     {
299       endecode_file (argc? *argv : NULL, (opt_endecode < 0));
300     }
301   else
302     test_zb32enc ();
303
304   return !!errcount;
305 }