1 /* Base64 encode/decode strings or files.
2 Copyright (C) 2004-2016 Free Software Foundation, Inc.
4 This file is part of Base64.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 /* Written by Simon Josefsson <simon@josefsson.org>. */
25 #include <sys/types.h>
33 #include "xdectoint.h"
36 #define AUTHORS proper_name ("Simon Josefsson")
40 # define PROGRAM_NAME "base32"
43 # define PROGRAM_NAME "base64"
47 static struct option
const long_options
[] =
49 {"decode", no_argument
, 0, 'd'},
50 {"wrap", required_argument
, 0, 'w'},
51 {"ignore-garbage", no_argument
, 0, 'i'},
53 {GETOPT_HELP_OPTION_DECL
},
54 {GETOPT_VERSION_OPTION_DECL
},
61 if (status
!= EXIT_SUCCESS
)
66 Usage: %s [OPTION]... [FILE]\n\
67 Base%d encode or decode FILE, or standard input, to standard output.\n\
68 "), program_name
, BASE_TYPE
);
71 emit_mandatory_arg_note ();
74 -d, --decode decode data\n\
75 -i, --ignore-garbage when decoding, ignore non-alphabet characters\n\
76 -w, --wrap=COLS wrap encoded lines after COLS character (default 76).\n\
77 Use 0 to disable line wrapping\n\
80 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
81 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
84 The data are encoded as described for the %s alphabet in RFC 4648.\n\
85 When decoding, the input may contain newlines in addition to the bytes of\n\
86 the formal %s alphabet. Use --ignore-garbage to attempt to recover\n\
87 from any other non-alphabet bytes in the encoded stream.\n"),
88 PROGRAM_NAME
, PROGRAM_NAME
);
89 emit_ancillary_info (PROGRAM_NAME
);
95 #define ENC_BLOCKSIZE (1024*3*10)
98 # define BASE_LENGTH BASE32_LENGTH
99 /* Note that increasing this may decrease performance if --ignore-garbage
100 is used, because of the memmove operation below. */
101 # define DEC_BLOCKSIZE (1024*5)
103 /* Ensure that BLOCKSIZE is a multiple of 5 and 8. */
104 verify (ENC_BLOCKSIZE
% 40 == 0); /* So padding chars only on last block. */
105 verify (DEC_BLOCKSIZE
% 40 == 0); /* So complete encoded blocks are used. */
107 # define base_encode base32_encode
108 # define base_decode_context base32_decode_context
109 # define base_decode_ctx_init base32_decode_ctx_init
110 # define base_decode_ctx base32_decode_ctx
111 # define isbase isbase32
113 # define BASE_LENGTH BASE64_LENGTH
114 /* Note that increasing this may decrease performance if --ignore-garbage
115 is used, because of the memmove operation below. */
116 # define DEC_BLOCKSIZE (1024*3)
118 /* Ensure that BLOCKSIZE is a multiple of 3 and 4. */
119 verify (ENC_BLOCKSIZE
% 12 == 0); /* So padding chars only on last block. */
120 verify (DEC_BLOCKSIZE
% 12 == 0); /* So complete encoded blocks are used. */
122 # define base_encode base64_encode
123 # define base_decode_context base64_decode_context
124 # define base_decode_ctx_init base64_decode_ctx_init
125 # define base_decode_ctx base64_decode_ctx
126 # define isbase isbase64
130 wrap_write (const char *buffer
, size_t len
,
131 uintmax_t wrap_column
, size_t *current_column
, FILE *out
)
135 if (wrap_column
== 0)
138 if (fwrite (buffer
, 1, len
, stdout
) < len
)
139 die (EXIT_FAILURE
, errno
, _("write error"));
142 for (written
= 0; written
< len
;)
144 uintmax_t cols_remaining
= wrap_column
- *current_column
;
145 size_t to_write
= MIN (cols_remaining
, SIZE_MAX
);
146 to_write
= MIN (to_write
, len
- written
);
150 if (fputc ('\n', out
) == EOF
)
151 die (EXIT_FAILURE
, errno
, _("write error"));
156 if (fwrite (buffer
+ written
, 1, to_write
, stdout
) < to_write
)
157 die (EXIT_FAILURE
, errno
, _("write error"));
158 *current_column
+= to_write
;
165 do_encode (FILE *in
, FILE *out
, uintmax_t wrap_column
)
167 size_t current_column
= 0;
168 char inbuf
[ENC_BLOCKSIZE
];
169 char outbuf
[BASE_LENGTH (ENC_BLOCKSIZE
)];
179 n
= fread (inbuf
+ sum
, 1, ENC_BLOCKSIZE
- sum
, in
);
182 while (!feof (in
) && !ferror (in
) && sum
< ENC_BLOCKSIZE
);
186 /* Process input one block at a time. Note that ENC_BLOCKSIZE
187 is sized so that no pad chars will appear in output. */
188 base_encode (inbuf
, sum
, outbuf
, BASE_LENGTH (sum
));
190 wrap_write (outbuf
, BASE_LENGTH (sum
), wrap_column
,
191 ¤t_column
, out
);
194 while (!feof (in
) && !ferror (in
) && sum
== ENC_BLOCKSIZE
);
196 /* When wrapping, terminate last line. */
197 if (wrap_column
&& current_column
> 0 && fputc ('\n', out
) == EOF
)
198 die (EXIT_FAILURE
, errno
, _("write error"));
201 die (EXIT_FAILURE
, errno
, _("read error"));
205 do_decode (FILE *in
, FILE *out
, bool ignore_garbage
)
207 char inbuf
[BASE_LENGTH (DEC_BLOCKSIZE
)];
208 char outbuf
[DEC_BLOCKSIZE
];
210 struct base_decode_context ctx
;
212 base_decode_ctx_init (&ctx
);
223 n
= fread (inbuf
+ sum
, 1, BASE_LENGTH (DEC_BLOCKSIZE
) - sum
, in
);
228 for (i
= 0; n
> 0 && i
< n
;)
229 if (isbase (inbuf
[sum
+ i
]) || inbuf
[sum
+ i
] == '=')
232 memmove (inbuf
+ sum
+ i
, inbuf
+ sum
+ i
+ 1, --n
- i
);
238 die (EXIT_FAILURE
, errno
, _("read error"));
240 while (sum
< BASE_LENGTH (DEC_BLOCKSIZE
) && !feof (in
));
242 /* The following "loop" is usually iterated just once.
243 However, when it processes the final input buffer, we want
244 to iterate it one additional time, but with an indicator
245 telling it to flush what is in CTX. */
246 for (k
= 0; k
< 1 + !!feof (in
); k
++)
248 if (k
== 1 && ctx
.i
== 0)
251 ok
= base_decode_ctx (&ctx
, inbuf
, (k
== 0 ? sum
: 0), outbuf
, &n
);
253 if (fwrite (outbuf
, 1, n
, out
) < n
)
254 die (EXIT_FAILURE
, errno
, _("write error"));
257 die (EXIT_FAILURE
, 0, _("invalid input"));
264 main (int argc
, char **argv
)
270 /* True if --decode has been given and we should decode data. */
272 /* True if we should ignore non-base-alphabetic characters. */
273 bool ignore_garbage
= false;
274 /* Wrap encoded data around the 76:th column, by default. */
275 uintmax_t wrap_column
= 76;
277 initialize_main (&argc
, &argv
);
278 set_program_name (argv
[0]);
279 setlocale (LC_ALL
, "");
280 bindtextdomain (PACKAGE
, LOCALEDIR
);
281 textdomain (PACKAGE
);
283 atexit (close_stdout
);
285 while ((opt
= getopt_long (argc
, argv
, "diw:", long_options
, NULL
)) != -1)
293 wrap_column
= xdectoumax (optarg
, 0, UINTMAX_MAX
, "",
294 _("invalid wrap size"), 0);
298 ignore_garbage
= true;
301 case_GETOPT_HELP_CHAR
;
303 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
306 usage (EXIT_FAILURE
);
310 if (argc
- optind
> 1)
312 error (0, 0, _("extra operand %s"), quote (argv
[optind
]));
313 usage (EXIT_FAILURE
);
317 infile
= argv
[optind
];
321 if (STREQ (infile
, "-"))
324 xfreopen (NULL
, "rb", stdin
);
329 input_fh
= fopen (infile
, "rb");
330 if (input_fh
== NULL
)
331 die (EXIT_FAILURE
, errno
, "%s", quotef (infile
));
334 fadvise (input_fh
, FADVISE_SEQUENTIAL
);
337 do_decode (input_fh
, stdout
, ignore_garbage
);
339 do_encode (input_fh
, stdout
, wrap_column
);
341 if (fclose (input_fh
) == EOF
)
343 if (STREQ (infile
, "-"))
344 die (EXIT_FAILURE
, errno
, _("closing standard input"));
346 die (EXIT_FAILURE
, errno
, "%s", quotef (infile
));