1 /* Base64, base32, and similar encoding/decoding strings or files.
2    Copyright (C) 2004-2023 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>. */
16 
17 /* Written by Simon Josefsson <simon@josefsson.org>.  */
18 
19 #include <config.h>
20 
21 #include <stdio.h>
22 #include <getopt.h>
23 #include <sys/types.h>
24 
25 #include "system.h"
26 #include "assure.h"
27 #include "c-ctype.h"
28 #include "fadvise.h"
29 #include "quote.h"
30 #include "xstrtol.h"
31 #include "xdectoint.h"
32 #include "xbinary-io.h"
33 
34 #if BASE_TYPE == 42
35 # define AUTHORS \
36   proper_name ("Simon Josefsson"), \
37   proper_name ("Assaf Gordon")
38 #else
39 # define AUTHORS proper_name ("Simon Josefsson")
40 #endif
41 
42 #if BASE_TYPE == 32
43 # include "base32.h"
44 # define PROGRAM_NAME "base32"
45 #elif BASE_TYPE == 64
46 # include "base64.h"
47 # define PROGRAM_NAME "base64"
48 #elif BASE_TYPE == 42
49 # include "base32.h"
50 # include "base64.h"
51 # include "assure.h"
52 # define PROGRAM_NAME "basenc"
53 #else
54 # error missing/invalid BASE_TYPE definition
55 #endif
56 
57 
58 
59 #if BASE_TYPE == 42
60 enum
61 {
62   BASE64_OPTION = CHAR_MAX + 1,
63   BASE64URL_OPTION,
64   BASE32_OPTION,
65   BASE32HEX_OPTION,
66   BASE16_OPTION,
67   BASE2MSBF_OPTION,
68   BASE2LSBF_OPTION,
69   Z85_OPTION
70 };
71 #endif
72 
73 static struct option const long_options[] =
74 {
75   {"decode", no_argument, 0, 'd'},
76   {"wrap", required_argument, 0, 'w'},
77   {"ignore-garbage", no_argument, 0, 'i'},
78 #if BASE_TYPE == 42
79   {"base64",    no_argument, 0, BASE64_OPTION},
80   {"base64url", no_argument, 0, BASE64URL_OPTION},
81   {"base32",    no_argument, 0, BASE32_OPTION},
82   {"base32hex", no_argument, 0, BASE32HEX_OPTION},
83   {"base16",    no_argument, 0, BASE16_OPTION},
84   {"base2msbf", no_argument, 0, BASE2MSBF_OPTION},
85   {"base2lsbf", no_argument, 0, BASE2LSBF_OPTION},
86   {"z85",       no_argument, 0, Z85_OPTION},
87 #endif
88   {GETOPT_HELP_OPTION_DECL},
89   {GETOPT_VERSION_OPTION_DECL},
90   {nullptr, 0, nullptr, 0}
91 };
92 
93 void
usage(int status)94 usage (int status)
95 {
96   if (status != EXIT_SUCCESS)
97     emit_try_help ();
98   else
99     {
100       printf (_("\
101 Usage: %s [OPTION]... [FILE]\n\
102 "), program_name);
103 
104 #if BASE_TYPE == 42
105       fputs (_("\
106 basenc encode or decode FILE, or standard input, to standard output.\n\
107 "), stdout);
108 #else
109       printf (_("\
110 Base%d encode or decode FILE, or standard input, to standard output.\n\
111 "), BASE_TYPE);
112 #endif
113 
114       emit_stdin_note ();
115       emit_mandatory_arg_note ();
116 #if BASE_TYPE == 42
117       fputs (_("\
118       --base64          same as 'base64' program (RFC4648 section 4)\n\
119 "), stdout);
120       fputs (_("\
121       --base64url       file- and url-safe base64 (RFC4648 section 5)\n\
122 "), stdout);
123       fputs (_("\
124       --base32          same as 'base32' program (RFC4648 section 6)\n\
125 "), stdout);
126       fputs (_("\
127       --base32hex       extended hex alphabet base32 (RFC4648 section 7)\n\
128 "), stdout);
129       fputs (_("\
130       --base16          hex encoding (RFC4648 section 8)\n\
131 "), stdout);
132       fputs (_("\
133       --base2msbf       bit string with most significant bit (msb) first\n\
134 "), stdout);
135       fputs (_("\
136       --base2lsbf       bit string with least significant bit (lsb) first\n\
137 "), stdout);
138 #endif
139       fputs (_("\
140   -d, --decode          decode data\n\
141   -i, --ignore-garbage  when decoding, ignore non-alphabet characters\n\
142   -w, --wrap=COLS       wrap encoded lines after COLS character (default 76).\n\
143                           Use 0 to disable line wrapping\n\
144 "), stdout);
145 #if BASE_TYPE == 42
146       fputs (_("\
147       --z85             ascii85-like encoding (ZeroMQ spec:32/Z85);\n\
148                         when encoding, input length must be a multiple of 4;\n\
149                         when decoding, input length must be a multiple of 5\n\
150 "), stdout);
151 #endif
152       fputs (HELP_OPTION_DESCRIPTION, stdout);
153       fputs (VERSION_OPTION_DESCRIPTION, stdout);
154 #if BASE_TYPE == 42
155       fputs (_("\
156 \n\
157 When decoding, the input may contain newlines in addition to the bytes of\n\
158 the formal alphabet.  Use --ignore-garbage to attempt to recover\n\
159 from any other non-alphabet bytes in the encoded stream.\n\
160 "), stdout);
161 #else
162       printf (_("\
163 \n\
164 The data are encoded as described for the %s alphabet in RFC 4648.\n\
165 When decoding, the input may contain newlines in addition to the bytes of\n\
166 the formal %s alphabet.  Use --ignore-garbage to attempt to recover\n\
167 from any other non-alphabet bytes in the encoded stream.\n"),
168               PROGRAM_NAME, PROGRAM_NAME);
169 #endif
170       emit_ancillary_info (PROGRAM_NAME);
171     }
172 
173   exit (status);
174 }
175 
176 #if BASE_TYPE != 64
177 static int
base32_required_padding(int len)178 base32_required_padding (int len)
179 {
180   int partial = len % 8;
181   return partial ? 8 - partial : 0;
182 }
183 #endif
184 
185 #if BASE_TYPE != 32
186 static int
base64_required_padding(int len)187 base64_required_padding (int len)
188 {
189   int partial = len % 4;
190   return partial ? 4 - partial : 0;
191 }
192 #endif
193 
194 #if BASE_TYPE == 42
195 static int
no_required_padding(int len)196 no_required_padding (int len)
197 {
198   return 0;
199 }
200 #endif
201 
202 #define ENC_BLOCKSIZE (1024 * 3 * 10)
203 
204 #if BASE_TYPE == 32
205 # define BASE_LENGTH BASE32_LENGTH
206 # define REQUIRED_PADDING base32_required_padding
207 /* Note that increasing this may decrease performance if --ignore-garbage
208    is used, because of the memmove operation below.  */
209 # define DEC_BLOCKSIZE (1024 * 5)
210 
211 /* Ensure that BLOCKSIZE is a multiple of 5 and 8.  */
212 static_assert (ENC_BLOCKSIZE % 40 == 0); /* Padding chars only on last block. */
213 static_assert (DEC_BLOCKSIZE % 40 == 0); /* Complete encoded blocks are used. */
214 
215 # define base_encode base32_encode
216 # define base_decode_context base32_decode_context
217 # define base_decode_ctx_init base32_decode_ctx_init
218 # define base_decode_ctx base32_decode_ctx
219 # define isubase isubase32
220 #elif BASE_TYPE == 64
221 # define BASE_LENGTH BASE64_LENGTH
222 # define REQUIRED_PADDING base64_required_padding
223 /* Note that increasing this may decrease performance if --ignore-garbage
224    is used, because of the memmove operation below.  */
225 # define DEC_BLOCKSIZE (1024 * 3)
226 
227 /* Ensure that BLOCKSIZE is a multiple of 3 and 4.  */
228 static_assert (ENC_BLOCKSIZE % 12 == 0); /* Padding chars only on last block. */
229 static_assert (DEC_BLOCKSIZE % 12 == 0); /* Complete encoded blocks are used. */
230 
231 # define base_encode base64_encode
232 # define base_decode_context base64_decode_context
233 # define base_decode_ctx_init base64_decode_ctx_init
234 # define base_decode_ctx base64_decode_ctx
235 # define isubase isubase64
236 #elif BASE_TYPE == 42
237 
238 
239 # define BASE_LENGTH base_length
240 # define REQUIRED_PADDING required_padding
241 
242 /* Note that increasing this may decrease performance if --ignore-garbage
243    is used, because of the memmove operation below.  */
244 # define DEC_BLOCKSIZE (4200)
245 static_assert (DEC_BLOCKSIZE % 40 == 0); /* complete encoded blocks for base32*/
246 static_assert (DEC_BLOCKSIZE % 12 == 0); /* complete encoded blocks for base64*/
247 
248 static int (*base_length) (int i);
249 static int (*required_padding) (int i);
250 static bool (*isubase) (unsigned char ch);
251 static void (*base_encode) (char const *restrict in, idx_t inlen,
252                             char *restrict out, idx_t outlen);
253 
254 struct base16_decode_context
255 {
256   /* Either a 4-bit nibble, or negative if we have no nibble.  */
257   signed char nibble;
258 };
259 
260 struct z85_decode_context
261 {
262   int i;
263   unsigned char octets[5];
264 };
265 
266 struct base2_decode_context
267 {
268   unsigned char octet;
269 };
270 
271 struct base_decode_context
272 {
273   int i; /* will be updated manually */
274   union {
275     struct base64_decode_context base64;
276     struct base32_decode_context base32;
277     struct base16_decode_context base16;
278     struct base2_decode_context base2;
279     struct z85_decode_context z85;
280   } ctx;
281   char *inbuf;
282   idx_t bufsize;
283 };
284 static void (*base_decode_ctx_init) (struct base_decode_context *ctx);
285 static bool (*base_decode_ctx) (struct base_decode_context *ctx,
286                                 char const *restrict in, idx_t inlen,
287                                 char *restrict out, idx_t *outlen);
288 #endif
289 
290 
291 
292 
293 #if BASE_TYPE == 42
294 
295 static int
base64_length_wrapper(int len)296 base64_length_wrapper (int len)
297 {
298   return BASE64_LENGTH (len);
299 }
300 
301 static void
base64_decode_ctx_init_wrapper(struct base_decode_context * ctx)302 base64_decode_ctx_init_wrapper (struct base_decode_context *ctx)
303 {
304   base64_decode_ctx_init (&ctx->ctx.base64);
305 }
306 
307 static bool
base64_decode_ctx_wrapper(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)308 base64_decode_ctx_wrapper (struct base_decode_context *ctx,
309                            char const *restrict in, idx_t inlen,
310                            char *restrict out, idx_t *outlen)
311 {
312   bool b = base64_decode_ctx (&ctx->ctx.base64, in, inlen, out, outlen);
313   ctx->i = ctx->ctx.base64.i;
314   return b;
315 }
316 
317 static void
init_inbuf(struct base_decode_context * ctx)318 init_inbuf (struct base_decode_context *ctx)
319 {
320   ctx->bufsize = DEC_BLOCKSIZE;
321   ctx->inbuf = xcharalloc (ctx->bufsize);
322 }
323 
324 static void
prepare_inbuf(struct base_decode_context * ctx,idx_t inlen)325 prepare_inbuf (struct base_decode_context *ctx, idx_t inlen)
326 {
327   if (ctx->bufsize < inlen)
328     {
329       ctx->bufsize = inlen * 2;
330       ctx->inbuf = xnrealloc (ctx->inbuf, ctx->bufsize, sizeof (char));
331     }
332 }
333 
334 
335 static void
base64url_encode(char const * restrict in,idx_t inlen,char * restrict out,idx_t outlen)336 base64url_encode (char const *restrict in, idx_t inlen,
337                   char *restrict out, idx_t outlen)
338 {
339   base64_encode (in, inlen, out, outlen);
340   /* translate 62nd and 63rd characters */
341   char *p = out;
342   while (outlen--)
343     {
344       if (*p == '+')
345         *p = '-';
346       else if (*p == '/')
347         *p = '_';
348       ++p;
349     }
350 }
351 
352 static bool
isubase64url(unsigned char ch)353 isubase64url (unsigned char ch)
354 {
355   return (ch == '-' || ch == '_'
356           || (ch != '+' && ch != '/' && isubase64 (ch)));
357 }
358 
359 static void
base64url_decode_ctx_init_wrapper(struct base_decode_context * ctx)360 base64url_decode_ctx_init_wrapper (struct base_decode_context *ctx)
361 {
362   base64_decode_ctx_init (&ctx->ctx.base64);
363   init_inbuf (ctx);
364 }
365 
366 
367 static bool
base64url_decode_ctx_wrapper(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)368 base64url_decode_ctx_wrapper (struct base_decode_context *ctx,
369                               char const *restrict in, idx_t inlen,
370                               char *restrict out, idx_t *outlen)
371 {
372   prepare_inbuf (ctx, inlen);
373   memcpy (ctx->inbuf, in, inlen);
374 
375   /* translate 62nd and 63rd characters */
376   idx_t i = inlen;
377   char *p = ctx->inbuf;
378   while (i--)
379     {
380       if (*p == '+' || *p == '/')
381         {
382           *outlen = 0;
383           return false; /* reject base64 input */
384         }
385       else if (*p == '-')
386         *p = '+';
387       else if (*p == '_')
388         *p = '/';
389       ++p;
390     }
391 
392   bool b = base64_decode_ctx (&ctx->ctx.base64, ctx->inbuf, inlen,
393                               out, outlen);
394   ctx->i = ctx->ctx.base64.i;
395 
396   return b;
397 }
398 
399 
400 
401 static int
base32_length_wrapper(int len)402 base32_length_wrapper (int len)
403 {
404   return BASE32_LENGTH (len);
405 }
406 
407 static void
base32_decode_ctx_init_wrapper(struct base_decode_context * ctx)408 base32_decode_ctx_init_wrapper (struct base_decode_context *ctx)
409 {
410   base32_decode_ctx_init (&ctx->ctx.base32);
411 }
412 
413 static bool
base32_decode_ctx_wrapper(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)414 base32_decode_ctx_wrapper (struct base_decode_context *ctx,
415                            char const *restrict in, idx_t inlen,
416                            char *restrict out, idx_t *outlen)
417 {
418   bool b = base32_decode_ctx (&ctx->ctx.base32, in, inlen, out, outlen);
419   ctx->i = ctx->ctx.base32.i;
420   return b;
421 }
422 
423 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
424      to
425    0123456789ABCDEFGHIJKLMNOPQRSTUV */
426 static const char base32_norm_to_hex[32 + 9] = {
427 /*0x32, 0x33, 0x34, 0x35, 0x36, 0x37, */
428   'Q',  'R',  'S',  'T',  'U',  'V',
429 
430   0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
431 
432 /*0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, */
433   '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
434 
435 /*0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, */
436   '8',  '9',  'A',  'B',  'C',  'D',  'E',  'F',
437 
438 /*0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, */
439   'G',  'H',  'I',  'J',  'K',  'L',  'M',  'N',
440 
441 /*0x59, 0x5a, */
442   'O',  'P',
443 };
444 
445 /* 0123456789ABCDEFGHIJKLMNOPQRSTUV
446      to
447    ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */
448 static const char base32_hex_to_norm[32 + 9] = {
449   /* from: 0x30 .. 0x39 ('0' to '9') */
450   /* to:*/ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
451 
452   0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
453 
454   /* from: 0x41 .. 0x4A ('A' to 'J') */
455   /* to:*/ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
456 
457   /* from: 0x4B .. 0x54 ('K' to 'T') */
458   /* to:*/ 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5',
459 
460   /* from: 0x55 .. 0x56 ('U' to 'V') */
461   /* to:*/ '6', '7'
462 };
463 
464 
465 inline static bool
isubase32hex(unsigned char ch)466 isubase32hex (unsigned char ch)
467 {
468   return ('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'V');
469 }
470 
471 
472 static void
base32hex_encode(char const * restrict in,idx_t inlen,char * restrict out,idx_t outlen)473 base32hex_encode (char const *restrict in, idx_t inlen,
474                   char *restrict out, idx_t outlen)
475 {
476   base32_encode (in, inlen, out, outlen);
477 
478   for (char *p = out; outlen--; p++)
479     {
480       affirm (0x32 <= *p && *p <= 0x5a);          /* LCOV_EXCL_LINE */
481       *p = base32_norm_to_hex[*p - 0x32];
482     }
483 }
484 
485 
486 static void
base32hex_decode_ctx_init_wrapper(struct base_decode_context * ctx)487 base32hex_decode_ctx_init_wrapper (struct base_decode_context *ctx)
488 {
489   base32_decode_ctx_init (&ctx->ctx.base32);
490   init_inbuf (ctx);
491 }
492 
493 
494 static bool
base32hex_decode_ctx_wrapper(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)495 base32hex_decode_ctx_wrapper (struct base_decode_context *ctx,
496                               char const *restrict in, idx_t inlen,
497                               char *restrict out, idx_t *outlen)
498 {
499   prepare_inbuf (ctx, inlen);
500 
501   idx_t i = inlen;
502   char *p = ctx->inbuf;
503   while (i--)
504     {
505       if (isubase32hex (*in))
506         *p = base32_hex_to_norm[*in - 0x30];
507       else
508         *p = *in;
509       ++p;
510       ++in;
511     }
512 
513   bool b = base32_decode_ctx (&ctx->ctx.base32, ctx->inbuf, inlen,
514                               out, outlen);
515   ctx->i = ctx->ctx.base32.i;
516 
517   return b;
518 }
519 /* With this approach this file works independent of the charset used
520    (think EBCDIC).  However, it does assume that the characters in the
521    Base32 alphabet (A-Z2-7) are encoded in 0..255.  POSIX
522    1003.1-2001 require that char and unsigned char are 8-bit
523    quantities, though, taking care of that problem.  But this may be a
524    potential problem on non-POSIX C99 platforms.
525 
526    IBM C V6 for AIX mishandles "#define B32(x) ...'x'...", so use "_"
527    as the formal parameter rather than "x".  */
528 #define B16(_)                                  \
529   ((_) == '0' ? 0                               \
530    : (_) == '1' ? 1                             \
531    : (_) == '2' ? 2                             \
532    : (_) == '3' ? 3                             \
533    : (_) == '4' ? 4                             \
534    : (_) == '5' ? 5                             \
535    : (_) == '6' ? 6                             \
536    : (_) == '7' ? 7                             \
537    : (_) == '8' ? 8                             \
538    : (_) == '9' ? 9                             \
539    : (_) == 'A' || (_) == 'a' ? 10              \
540    : (_) == 'B' || (_) == 'b' ? 11              \
541    : (_) == 'C' || (_) == 'c' ? 12              \
542    : (_) == 'D' || (_) == 'd' ? 13              \
543    : (_) == 'E' || (_) == 'e' ? 14              \
544    : (_) == 'F' || (_) == 'f' ? 15              \
545    : -1)
546 
547 static signed char const base16_to_int[256] = {
548   B16 (0), B16 (1), B16 (2), B16 (3),
549   B16 (4), B16 (5), B16 (6), B16 (7),
550   B16 (8), B16 (9), B16 (10), B16 (11),
551   B16 (12), B16 (13), B16 (14), B16 (15),
552   B16 (16), B16 (17), B16 (18), B16 (19),
553   B16 (20), B16 (21), B16 (22), B16 (23),
554   B16 (24), B16 (25), B16 (26), B16 (27),
555   B16 (28), B16 (29), B16 (30), B16 (31),
556   B16 (32), B16 (33), B16 (34), B16 (35),
557   B16 (36), B16 (37), B16 (38), B16 (39),
558   B16 (40), B16 (41), B16 (42), B16 (43),
559   B16 (44), B16 (45), B16 (46), B16 (47),
560   B16 (48), B16 (49), B16 (50), B16 (51),
561   B16 (52), B16 (53), B16 (54), B16 (55),
562   B16 (56), B16 (57), B16 (58), B16 (59),
563   B16 (60), B16 (61), B16 (62), B16 (63),
564   B16 (32), B16 (65), B16 (66), B16 (67),
565   B16 (68), B16 (69), B16 (70), B16 (71),
566   B16 (72), B16 (73), B16 (74), B16 (75),
567   B16 (76), B16 (77), B16 (78), B16 (79),
568   B16 (80), B16 (81), B16 (82), B16 (83),
569   B16 (84), B16 (85), B16 (86), B16 (87),
570   B16 (88), B16 (89), B16 (90), B16 (91),
571   B16 (92), B16 (93), B16 (94), B16 (95),
572   B16 (96), B16 (97), B16 (98), B16 (99),
573   B16 (100), B16 (101), B16 (102), B16 (103),
574   B16 (104), B16 (105), B16 (106), B16 (107),
575   B16 (108), B16 (109), B16 (110), B16 (111),
576   B16 (112), B16 (113), B16 (114), B16 (115),
577   B16 (116), B16 (117), B16 (118), B16 (119),
578   B16 (120), B16 (121), B16 (122), B16 (123),
579   B16 (124), B16 (125), B16 (126), B16 (127),
580   B16 (128), B16 (129), B16 (130), B16 (131),
581   B16 (132), B16 (133), B16 (134), B16 (135),
582   B16 (136), B16 (137), B16 (138), B16 (139),
583   B16 (140), B16 (141), B16 (142), B16 (143),
584   B16 (144), B16 (145), B16 (146), B16 (147),
585   B16 (148), B16 (149), B16 (150), B16 (151),
586   B16 (152), B16 (153), B16 (154), B16 (155),
587   B16 (156), B16 (157), B16 (158), B16 (159),
588   B16 (160), B16 (161), B16 (162), B16 (163),
589   B16 (132), B16 (165), B16 (166), B16 (167),
590   B16 (168), B16 (169), B16 (170), B16 (171),
591   B16 (172), B16 (173), B16 (174), B16 (175),
592   B16 (176), B16 (177), B16 (178), B16 (179),
593   B16 (180), B16 (181), B16 (182), B16 (183),
594   B16 (184), B16 (185), B16 (186), B16 (187),
595   B16 (188), B16 (189), B16 (190), B16 (191),
596   B16 (192), B16 (193), B16 (194), B16 (195),
597   B16 (196), B16 (197), B16 (198), B16 (199),
598   B16 (200), B16 (201), B16 (202), B16 (203),
599   B16 (204), B16 (205), B16 (206), B16 (207),
600   B16 (208), B16 (209), B16 (210), B16 (211),
601   B16 (212), B16 (213), B16 (214), B16 (215),
602   B16 (216), B16 (217), B16 (218), B16 (219),
603   B16 (220), B16 (221), B16 (222), B16 (223),
604   B16 (224), B16 (225), B16 (226), B16 (227),
605   B16 (228), B16 (229), B16 (230), B16 (231),
606   B16 (232), B16 (233), B16 (234), B16 (235),
607   B16 (236), B16 (237), B16 (238), B16 (239),
608   B16 (240), B16 (241), B16 (242), B16 (243),
609   B16 (244), B16 (245), B16 (246), B16 (247),
610   B16 (248), B16 (249), B16 (250), B16 (251),
611   B16 (252), B16 (253), B16 (254), B16 (255)
612 };
613 
614 static bool
isubase16(unsigned char ch)615 isubase16 (unsigned char ch)
616 {
617   return ch < sizeof base16_to_int && 0 <= base16_to_int[ch];
618 }
619 
620 static int
base16_length(int len)621 base16_length (int len)
622 {
623   return len * 2;
624 }
625 
626 
627 static void
base16_encode(char const * restrict in,idx_t inlen,char * restrict out,idx_t outlen)628 base16_encode (char const *restrict in, idx_t inlen,
629                char *restrict out, idx_t outlen)
630 {
631   static const char base16[16] = "0123456789ABCDEF";
632 
633   while (inlen--)
634     {
635       unsigned char c = *in;
636       *out++ = base16[c >> 4];
637       *out++ = base16[c & 0x0F];
638       ++in;
639     }
640 }
641 
642 
643 static void
base16_decode_ctx_init(struct base_decode_context * ctx)644 base16_decode_ctx_init (struct base_decode_context *ctx)
645 {
646   init_inbuf (ctx);
647   ctx->ctx.base16.nibble = -1;
648   ctx->i = 1;
649 }
650 
651 
652 static bool
base16_decode_ctx(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)653 base16_decode_ctx (struct base_decode_context *ctx,
654                    char const *restrict in, idx_t inlen,
655                    char *restrict out, idx_t *outlen)
656 {
657   bool ignore_lines = true;  /* for now, always ignore them */
658   char *out0 = out;
659   signed char nibble = ctx->ctx.base16.nibble;
660 
661   /* inlen==0 is request to flush output.
662      if there is a dangling high nibble - we are missing the low nibble,
663      so return false - indicating an invalid input.  */
664   if (inlen == 0)
665     {
666       *outlen = 0;
667       return nibble < 0;
668     }
669 
670   while (inlen--)
671     {
672       unsigned char c = *in++;
673       if (ignore_lines && c == '\n')
674         continue;
675 
676       if (sizeof base16_to_int <= c || base16_to_int[c] < 0)
677         {
678           *outlen = out - out0;
679           return false; /* garbage - return false */
680         }
681 
682       if (nibble < 0)
683         nibble = base16_to_int[c];
684       else
685         {
686           /* have both nibbles, write octet */
687           *out++ = (nibble << 4) + base16_to_int[c];
688           nibble = -1;
689         }
690     }
691 
692   ctx->ctx.base16.nibble = nibble;
693   *outlen = out - out0;
694   return true;
695 }
696 
697 
698 
699 
700 static int
z85_length(int len)701 z85_length (int len)
702 {
703   /* Z85 does not allow padding, so no need to round to highest integer.  */
704   int outlen = (len * 5) / 4;
705   return outlen;
706 }
707 
708 static bool
isuz85(unsigned char ch)709 isuz85 (unsigned char ch)
710 {
711   return c_isalnum (ch) || strchr (".-:+=^!/*?&<>()[]{}@%$#", ch) != nullptr;
712 }
713 
714 static char const z85_encoding[85] =
715   "0123456789"
716   "abcdefghijklmnopqrstuvwxyz"
717   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
718   ".-:+=^!/*?&<>()[]{}@%$#";
719 
720 static void
z85_encode(char const * restrict in,idx_t inlen,char * restrict out,idx_t outlen)721 z85_encode (char const *restrict in, idx_t inlen,
722             char *restrict out, idx_t outlen)
723 {
724   int i = 0;
725   unsigned char quad[4];
726   idx_t outidx = 0;
727 
728   while (true)
729     {
730       if (inlen == 0)
731         {
732           /* no more input, exactly on 4 octet boundary. */
733           if (i == 0)
734             return;
735 
736           /* currently, there's no way to return an error in encoding.  */
737           error (EXIT_FAILURE, 0,
738                  _("invalid input (length must be multiple of 4 characters)"));
739         }
740       else
741         {
742           quad[i++] = *in++;
743           --inlen;
744         }
745 
746       /* Got a quad, encode it */
747       if (i == 4)
748         {
749           int_fast64_t val = quad[0];
750           val = (val << 24) + (quad[1] << 16) + (quad[2] << 8) + quad[3];
751 
752           for (int j = 4; j >= 0; --j)
753             {
754               int c = val % 85;
755               val /= 85;
756 
757               /* NOTE: if there is padding (which is trimmed by z85
758                  before outputting the result), the output buffer 'out'
759                  might not include enough allocated bytes for the padding,
760                  so don't store them. */
761               if (outidx + j < outlen)
762                 out[j] = z85_encoding[c];
763             }
764           out += 5;
765           outidx += 5;
766           i = 0;
767         }
768     }
769 }
770 
771 static void
z85_decode_ctx_init(struct base_decode_context * ctx)772 z85_decode_ctx_init (struct base_decode_context *ctx)
773 {
774   init_inbuf (ctx);
775   ctx->ctx.z85.i = 0;
776   ctx->i = 1;
777 }
778 
779 
780 # define Z85_LO_CTX_TO_32BIT_VAL(ctx) \
781   (((ctx)->ctx.z85.octets[1] * 85 * 85 * 85) +      \
782    ((ctx)->ctx.z85.octets[2] * 85 * 85) +	    \
783    ((ctx)->ctx.z85.octets[3] * 85) +		    \
784    ((ctx)->ctx.z85.octets[4]))
785 
786 
787 # define Z85_HI_CTX_TO_32BIT_VAL(ctx) \
788   ((int_fast64_t) (ctx)->ctx.z85.octets[0] * 85 * 85 * 85 * 85 )
789 
790 /*
791  0 -  9:  0 1 2 3 4 5 6 7 8 9
792  10 - 19:  a b c d e f g h i j
793  20 - 29:  k l m n o p q r s t
794  30 - 39:  u v w x y z A B C D
795  40 - 49:  E F G H I J K L M N
796  50 - 59:  O P Q R S T U V W X
797  60 - 69:  Y Z . - : + = ^ ! /   #dummy comment to workaround syntax-check
798  70 - 79:  * ? & < > ( ) [ ] {
799  80 - 84:  } @ % $ #
800 */
801 static signed char const z85_decoding[93] = {
802   68, -1,  84,  83, 82,  72, -1,               /* ! " # $ % & ' */
803   75, 76,  70,  65, -1,  63, 62, 69,           /* ( ) * + , - . / */
804   0,  1,   2,   3,  4,   5,  6,   7,  8,  9,   /* '0' to '9' */
805   64, -1,  73,  66, 74,  71, 81,               /* : ; < =  > ? @ */
806   36, 37,  38,  39, 40,  41, 42,  43, 44, 45,  /* 'A' to 'J' */
807   46, 47,  48,  49, 50,  51, 52,  53, 54, 55,  /* 'K' to 'T' */
808   56, 57,  58,  59, 60,  61,                   /* 'U' to 'Z' */
809   77,  -1, 78,  67,  -1,  -1,                  /* [ \ ] ^ _ ` */
810   10, 11,  12,  13, 14,  15, 16,  17, 18, 19,  /* 'a' to 'j' */
811   20, 21,  22,  23, 24,  25, 26,  27, 28, 29,  /* 'k' to 't' */
812   30, 31,  32,  33, 34,  35,                   /* 'u' to 'z' */
813   79, -1,  80                                  /* { | } */
814 };
815 
816 static bool
z85_decode_ctx(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)817 z85_decode_ctx (struct base_decode_context *ctx,
818                 char const *restrict in, idx_t inlen,
819                 char *restrict out, idx_t *outlen)
820 {
821   bool ignore_lines = true;  /* for now, always ignore them */
822 
823   *outlen = 0;
824 
825   /* inlen==0 is request to flush output.
826      if there are dangling values - we are missing entries,
827      so return false - indicating an invalid input.  */
828   if (inlen == 0)
829     {
830       if (ctx->ctx.z85.i > 0)
831         {
832           /* Z85 variant does not allow padding - input must
833              be a multiple of 5 - so return error.  */
834           return false;
835         }
836       return true;
837     }
838 
839   while (inlen--)
840     {
841       if (ignore_lines && *in == '\n')
842         {
843           ++in;
844           continue;
845         }
846 
847       /* z85 decoding */
848       unsigned char c = *in;
849 
850       if (c >= 33 && c <= 125)
851         {
852           signed char ch = z85_decoding[c - 33];
853           if (ch < 0)
854             return false; /* garbage - return false */
855           c = ch;
856         }
857       else
858         return false; /* garbage - return false */
859 
860       ++in;
861 
862       ctx->ctx.z85.octets[ctx->ctx.z85.i++] = c;
863       if (ctx->ctx.z85.i == 5)
864         {
865           /* decode the lowest 4 octets, then check for overflows.  */
866           int_fast64_t val = Z85_LO_CTX_TO_32BIT_VAL (ctx);
867 
868           /* The Z85 spec and the reference implementation say nothing
869              about overflows. To be on the safe side, reject them.  */
870 
871           val += Z85_HI_CTX_TO_32BIT_VAL (ctx);
872           if ((val >> 24) & ~0xFF)
873             return false;
874 
875           *out++ = val >> 24;
876           *out++ = (val >> 16) & 0xFF;
877           *out++ = (val >> 8) & 0xFF;
878           *out++ = val & 0xFF;
879 
880           *outlen += 4;
881 
882           ctx->ctx.z85.i = 0;
883         }
884     }
885   ctx->i = ctx->ctx.z85.i;
886   return true;
887 }
888 
889 
890 inline static bool
isubase2(unsigned char ch)891 isubase2 (unsigned char ch)
892 {
893   return ch == '0' || ch == '1';
894 }
895 
896 static int
base2_length(int len)897 base2_length (int len)
898 {
899   return len * 8;
900 }
901 
902 
903 inline static void
base2msbf_encode(char const * restrict in,idx_t inlen,char * restrict out,idx_t outlen)904 base2msbf_encode (char const *restrict in, idx_t inlen,
905                   char *restrict out, idx_t outlen)
906 {
907   while (inlen--)
908     {
909       unsigned char c = *in;
910       for (int i = 0; i < 8; i++)
911         {
912           *out++ = c & 0x80 ? '1' : '0';
913           c <<= 1;
914         }
915       outlen -= 8;
916       ++in;
917     }
918 }
919 
920 inline static void
base2lsbf_encode(char const * restrict in,idx_t inlen,char * restrict out,idx_t outlen)921 base2lsbf_encode (char const *restrict in, idx_t inlen,
922                   char *restrict out, idx_t outlen)
923 {
924   while (inlen--)
925     {
926       unsigned char c = *in;
927       for (int i = 0; i < 8; i++)
928         {
929           *out++ = c & 0x01 ? '1' : '0';
930           c >>= 1;
931         }
932       outlen -= 8;
933       ++in;
934     }
935 }
936 
937 
938 static void
base2_decode_ctx_init(struct base_decode_context * ctx)939 base2_decode_ctx_init (struct base_decode_context *ctx)
940 {
941   init_inbuf (ctx);
942   ctx->ctx.base2.octet = 0;
943   ctx->i = 0;
944 }
945 
946 
947 static bool
base2lsbf_decode_ctx(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)948 base2lsbf_decode_ctx (struct base_decode_context *ctx,
949                       char const *restrict in, idx_t inlen,
950                       char *restrict out, idx_t *outlen)
951 {
952   bool ignore_lines = true;  /* for now, always ignore them */
953 
954   *outlen = 0;
955 
956   /* inlen==0 is request to flush output.
957      if there is a dangling bit - we are missing some bits,
958      so return false - indicating an invalid input.  */
959   if (inlen == 0)
960     return ctx->i == 0;
961 
962   while (inlen--)
963     {
964       if (ignore_lines && *in == '\n')
965         {
966           ++in;
967           continue;
968         }
969 
970       if (!isubase2 (*in))
971         return false;
972 
973       bool bit = (*in == '1');
974       ctx->ctx.base2.octet |= bit << ctx->i;
975       ++ctx->i;
976 
977       if (ctx->i == 8)
978         {
979           *out++ = ctx->ctx.base2.octet;
980           ctx->ctx.base2.octet = 0;
981           ++*outlen;
982           ctx->i = 0;
983         }
984 
985       ++in;
986     }
987 
988   return true;
989 }
990 
991 static bool
base2msbf_decode_ctx(struct base_decode_context * ctx,char const * restrict in,idx_t inlen,char * restrict out,idx_t * outlen)992 base2msbf_decode_ctx (struct base_decode_context *ctx,
993                       char const *restrict in, idx_t inlen,
994                       char *restrict out, idx_t *outlen)
995 {
996   bool ignore_lines = true;  /* for now, always ignore them */
997 
998   *outlen = 0;
999 
1000   /* inlen==0 is request to flush output.
1001      if there is a dangling bit - we are missing some bits,
1002      so return false - indicating an invalid input.  */
1003   if (inlen == 0)
1004     return ctx->i == 0;
1005 
1006   while (inlen--)
1007     {
1008       if (ignore_lines && *in == '\n')
1009         {
1010           ++in;
1011           continue;
1012         }
1013 
1014       if (!isubase2 (*in))
1015         return false;
1016 
1017       bool bit = (*in == '1');
1018       if (ctx->i == 0)
1019         ctx->i = 8;
1020       --ctx->i;
1021       ctx->ctx.base2.octet |= bit << ctx->i;
1022 
1023       if (ctx->i == 0)
1024         {
1025           *out++ = ctx->ctx.base2.octet;
1026           ctx->ctx.base2.octet = 0;
1027           ++*outlen;
1028           ctx->i = 0;
1029         }
1030 
1031       ++in;
1032     }
1033 
1034   return true;
1035 }
1036 
1037 #endif /* BASE_TYPE == 42, i.e., "basenc"*/
1038 
1039 
1040 
1041 static void
wrap_write(char const * buffer,idx_t len,idx_t wrap_column,idx_t * current_column,FILE * out)1042 wrap_write (char const *buffer, idx_t len,
1043             idx_t wrap_column, idx_t *current_column, FILE *out)
1044 {
1045   if (wrap_column == 0)
1046     {
1047       /* Simple write. */
1048       if (fwrite (buffer, 1, len, stdout) < len)
1049         write_error ();
1050     }
1051   else
1052     for (idx_t written = 0; written < len; )
1053       {
1054         idx_t to_write = MIN (wrap_column - *current_column, len - written);
1055 
1056         if (to_write == 0)
1057           {
1058             if (fputc ('\n', out) == EOF)
1059               write_error ();
1060             *current_column = 0;
1061           }
1062         else
1063           {
1064             if (fwrite (buffer + written, 1, to_write, stdout) < to_write)
1065               write_error ();
1066             *current_column += to_write;
1067             written += to_write;
1068           }
1069       }
1070 }
1071 
1072 static _Noreturn void
finish_and_exit(FILE * in,char const * infile)1073 finish_and_exit (FILE *in, char const *infile)
1074 {
1075   if (fclose (in) != 0)
1076     {
1077       if (STREQ (infile, "-"))
1078         error (EXIT_FAILURE, errno, _("closing standard input"));
1079       else
1080         error (EXIT_FAILURE, errno, "%s", quotef (infile));
1081     }
1082 
1083   exit (EXIT_SUCCESS);
1084 }
1085 
1086 static _Noreturn void
do_encode(FILE * in,char const * infile,FILE * out,idx_t wrap_column)1087 do_encode (FILE *in, char const *infile, FILE *out, idx_t wrap_column)
1088 {
1089   idx_t current_column = 0;
1090   char *inbuf, *outbuf;
1091   idx_t sum;
1092 
1093   inbuf = xmalloc (ENC_BLOCKSIZE);
1094   outbuf = xmalloc (BASE_LENGTH (ENC_BLOCKSIZE));
1095 
1096   do
1097     {
1098       idx_t n;
1099 
1100       sum = 0;
1101       do
1102         {
1103           n = fread (inbuf + sum, 1, ENC_BLOCKSIZE - sum, in);
1104           sum += n;
1105         }
1106       while (!feof (in) && !ferror (in) && sum < ENC_BLOCKSIZE);
1107 
1108       if (sum > 0)
1109         {
1110           /* Process input one block at a time.  Note that ENC_BLOCKSIZE
1111              is sized so that no pad chars will appear in output. */
1112           base_encode (inbuf, sum, outbuf, BASE_LENGTH (sum));
1113 
1114           wrap_write (outbuf, BASE_LENGTH (sum), wrap_column,
1115                       &current_column, out);
1116         }
1117     }
1118   while (!feof (in) && !ferror (in) && sum == ENC_BLOCKSIZE);
1119 
1120   /* When wrapping, terminate last line. */
1121   if (wrap_column && current_column > 0 && fputc ('\n', out) == EOF)
1122     write_error ();
1123 
1124   if (ferror (in))
1125     error (EXIT_FAILURE, errno, _("read error"));
1126 
1127   finish_and_exit (in, infile);
1128 }
1129 
1130 static _Noreturn void
do_decode(FILE * in,char const * infile,FILE * out,bool ignore_garbage)1131 do_decode (FILE *in, char const *infile, FILE *out, bool ignore_garbage)
1132 {
1133   char *inbuf, *outbuf;
1134   idx_t sum;
1135   struct base_decode_context ctx;
1136 
1137   char padbuf[8] = "========";
1138   inbuf = xmalloc (BASE_LENGTH (DEC_BLOCKSIZE));
1139   outbuf = xmalloc (DEC_BLOCKSIZE);
1140 
1141 #if BASE_TYPE == 42
1142   ctx.inbuf = nullptr;
1143 #endif
1144   base_decode_ctx_init (&ctx);
1145 
1146   do
1147     {
1148       bool ok;
1149 
1150       sum = 0;
1151       do
1152         {
1153           idx_t n = fread (inbuf + sum,
1154                            1, BASE_LENGTH (DEC_BLOCKSIZE) - sum, in);
1155 
1156           if (ignore_garbage)
1157             {
1158               for (idx_t i = 0; n > 0 && i < n;)
1159                 {
1160                   if (isubase (inbuf[sum + i]) || inbuf[sum + i] == '=')
1161                     i++;
1162                   else
1163                     memmove (inbuf + sum + i, inbuf + sum + i + 1, --n - i);
1164                 }
1165             }
1166 
1167           sum += n;
1168 
1169           if (ferror (in))
1170             error (EXIT_FAILURE, errno, _("read error"));
1171         }
1172       while (sum < BASE_LENGTH (DEC_BLOCKSIZE) && !feof (in));
1173 
1174       /* The following "loop" is usually iterated just once.
1175          However, when it processes the final input buffer, we want
1176          to iterate it one additional time, but with an indicator
1177          telling it to flush what is in CTX.  */
1178       for (int k = 0; k < 1 + !!feof (in); k++)
1179         {
1180           if (k == 1)
1181             {
1182               if (ctx.i == 0)
1183                 break;
1184 
1185               /* auto pad input (at eof).  */
1186               idx_t auto_padding = REQUIRED_PADDING (ctx.i);
1187               if (auto_padding && (sum == 0 || inbuf[sum - 1] != '='))
1188                 {
1189                   affirm (auto_padding <= sizeof (padbuf));
1190                   IF_LINT (free (inbuf));
1191                   sum = auto_padding;
1192                   inbuf = padbuf;
1193                 }
1194               else
1195                 sum = 0;  /* process ctx buffer only */
1196             }
1197           idx_t n = DEC_BLOCKSIZE;
1198           ok = base_decode_ctx (&ctx, inbuf, sum, outbuf, &n);
1199 
1200           if (fwrite (outbuf, 1, n, out) < n)
1201             write_error ();
1202 
1203           if (!ok)
1204             error (EXIT_FAILURE, 0, _("invalid input"));
1205         }
1206     }
1207   while (!feof (in));
1208 
1209   finish_and_exit (in, infile);
1210 }
1211 
1212 int
main(int argc,char ** argv)1213 main (int argc, char **argv)
1214 {
1215   int opt;
1216   FILE *input_fh;
1217   char const *infile;
1218 
1219   /* True if --decode has been given and we should decode data. */
1220   bool decode = false;
1221   /* True if we should ignore non-base-alphabetic characters. */
1222   bool ignore_garbage = false;
1223   /* Wrap encoded data around the 76th column, by default. */
1224   idx_t wrap_column = 76;
1225 
1226 #if BASE_TYPE == 42
1227   int base_type = 0;
1228 #endif
1229 
1230   initialize_main (&argc, &argv);
1231   set_program_name (argv[0]);
1232   setlocale (LC_ALL, "");
1233   bindtextdomain (PACKAGE, LOCALEDIR);
1234   textdomain (PACKAGE);
1235 
1236   atexit (close_stdout);
1237 
1238   while ((opt = getopt_long (argc, argv, "diw:", long_options, nullptr)) != -1)
1239     switch (opt)
1240       {
1241       case 'd':
1242         decode = true;
1243         break;
1244 
1245       case 'w':
1246         {
1247           intmax_t w;
1248           strtol_error s_err = xstrtoimax (optarg, nullptr, 10, &w, "");
1249           if (LONGINT_OVERFLOW < s_err || w < 0)
1250             error (EXIT_FAILURE, 0, "%s: %s",
1251                    _("invalid wrap size"), quote (optarg));
1252           wrap_column = s_err == LONGINT_OVERFLOW || IDX_MAX < w ? 0 : w;
1253         }
1254         break;
1255 
1256       case 'i':
1257         ignore_garbage = true;
1258         break;
1259 
1260 #if BASE_TYPE == 42
1261       case BASE64_OPTION:
1262       case BASE64URL_OPTION:
1263       case BASE32_OPTION:
1264       case BASE32HEX_OPTION:
1265       case BASE16_OPTION:
1266       case BASE2MSBF_OPTION:
1267       case BASE2LSBF_OPTION:
1268       case Z85_OPTION:
1269         base_type = opt;
1270         break;
1271 #endif
1272 
1273       case_GETOPT_HELP_CHAR;
1274 
1275       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1276 
1277       default:
1278         usage (EXIT_FAILURE);
1279         break;
1280       }
1281 
1282 #if BASE_TYPE == 42
1283   switch (base_type)
1284     {
1285     case BASE64_OPTION:
1286       base_length = base64_length_wrapper;
1287       required_padding = base64_required_padding;
1288       isubase = isubase64;
1289       base_encode = base64_encode;
1290       base_decode_ctx_init = base64_decode_ctx_init_wrapper;
1291       base_decode_ctx = base64_decode_ctx_wrapper;
1292       break;
1293 
1294     case BASE64URL_OPTION:
1295       base_length = base64_length_wrapper;
1296       required_padding = base64_required_padding;
1297       isubase = isubase64url;
1298       base_encode = base64url_encode;
1299       base_decode_ctx_init = base64url_decode_ctx_init_wrapper;
1300       base_decode_ctx = base64url_decode_ctx_wrapper;
1301       break;
1302 
1303     case BASE32_OPTION:
1304       base_length = base32_length_wrapper;
1305       required_padding = base32_required_padding;
1306       isubase = isubase32;
1307       base_encode = base32_encode;
1308       base_decode_ctx_init = base32_decode_ctx_init_wrapper;
1309       base_decode_ctx = base32_decode_ctx_wrapper;
1310       break;
1311 
1312     case BASE32HEX_OPTION:
1313       base_length = base32_length_wrapper;
1314       required_padding = base32_required_padding;
1315       isubase = isubase32hex;
1316       base_encode = base32hex_encode;
1317       base_decode_ctx_init = base32hex_decode_ctx_init_wrapper;
1318       base_decode_ctx = base32hex_decode_ctx_wrapper;
1319       break;
1320 
1321     case BASE16_OPTION:
1322       base_length = base16_length;
1323       required_padding = no_required_padding;
1324       isubase = isubase16;
1325       base_encode = base16_encode;
1326       base_decode_ctx_init = base16_decode_ctx_init;
1327       base_decode_ctx = base16_decode_ctx;
1328       break;
1329 
1330     case BASE2MSBF_OPTION:
1331       base_length = base2_length;
1332       required_padding = no_required_padding;
1333       isubase = isubase2;
1334       base_encode = base2msbf_encode;
1335       base_decode_ctx_init = base2_decode_ctx_init;
1336       base_decode_ctx = base2msbf_decode_ctx;
1337       break;
1338 
1339     case BASE2LSBF_OPTION:
1340       base_length = base2_length;
1341       required_padding = no_required_padding;
1342       isubase = isubase2;
1343       base_encode = base2lsbf_encode;
1344       base_decode_ctx_init = base2_decode_ctx_init;
1345       base_decode_ctx = base2lsbf_decode_ctx;
1346       break;
1347 
1348     case Z85_OPTION:
1349       base_length = z85_length;
1350       required_padding = no_required_padding;
1351       isubase = isuz85;
1352       base_encode = z85_encode;
1353       base_decode_ctx_init = z85_decode_ctx_init;
1354       base_decode_ctx = z85_decode_ctx;
1355       break;
1356 
1357     default:
1358       error (0, 0, _("missing encoding type"));
1359       usage (EXIT_FAILURE);
1360     }
1361 #endif
1362 
1363   if (argc - optind > 1)
1364     {
1365       error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
1366       usage (EXIT_FAILURE);
1367     }
1368 
1369   if (optind < argc)
1370     infile = argv[optind];
1371   else
1372     infile = "-";
1373 
1374   if (STREQ (infile, "-"))
1375     {
1376       xset_binary_mode (STDIN_FILENO, O_BINARY);
1377       input_fh = stdin;
1378     }
1379   else
1380     {
1381       input_fh = fopen (infile, "rb");
1382       if (input_fh == nullptr)
1383         error (EXIT_FAILURE, errno, "%s", quotef (infile));
1384     }
1385 
1386   fadvise (input_fh, FADVISE_SEQUENTIAL);
1387 
1388   if (decode)
1389     do_decode (input_fh, infile, stdout, ignore_garbage);
1390   else
1391     do_encode (input_fh, infile, stdout, wrap_column);
1392 }
1393