tests: add fold(1) test for --bytes option
[coreutils.git] / src / blake2 / b2sum.c
blob5d69ff8d4cde22d74d0550077740a3e2d5daf7dd
1 /*
2 BLAKE2 reference source code package - b2sum tool
4 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
5 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6 your option. The terms of these licenses can be found at:
8 - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
9 - OpenSSL license : https://www.openssl.org/source/license.html
10 - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
12 More information about the BLAKE2 hash function can be found at
13 https://blake2.net.
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
20 #include <stdio.h>
21 #include <stdlib.h>
23 #include "blake2.h"
25 #if 0
26 /* This will help compatibility with coreutils */
27 int blake2s_stream( FILE *stream, void *resstream, size_t outbytes )
29 int ret = -1;
30 size_t sum, n;
31 blake2s_state S[1];
32 static const size_t buffer_length = 32768;
33 uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
35 if( !buffer ) return -1;
37 blake2s_init( S, outbytes );
39 while( 1 )
41 sum = 0;
43 while( 1 )
45 n = fread( buffer + sum, 1, buffer_length - sum, stream );
46 sum += n;
48 if( buffer_length == sum )
49 break;
51 if( 0 == n )
53 if( ferror( stream ) )
54 goto cleanup_buffer;
56 goto final_process;
59 if( feof( stream ) )
60 goto final_process;
63 blake2s_update( S, buffer, buffer_length );
66 final_process:;
68 if( sum > 0 ) blake2s_update( S, buffer, sum );
70 blake2s_final( S, resstream, outbytes );
71 ret = 0;
72 cleanup_buffer:
73 free( buffer );
74 return ret;
76 #endif
78 int blake2b_stream( FILE *stream, void *resstream, size_t outbytes )
80 int ret = -1;
81 size_t sum, n;
82 blake2b_state S[1];
83 static const size_t buffer_length = 32768;
84 uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
86 if( !buffer ) return -1;
88 blake2b_init( S, outbytes );
90 while( 1 )
92 sum = 0;
94 while( 1 )
96 n = fread( buffer + sum, 1, buffer_length - sum, stream );
97 sum += n;
99 if( buffer_length == sum )
100 break;
102 if( 0 == n )
104 if( ferror( stream ) )
105 goto cleanup_buffer;
107 goto final_process;
110 if( feof( stream ) )
111 goto final_process;
114 blake2b_update( S, buffer, buffer_length );
117 final_process:;
119 if( sum > 0 ) blake2b_update( S, buffer, sum );
121 blake2b_final( S, resstream, outbytes );
122 ret = 0;
123 cleanup_buffer:
124 free( buffer );
125 return ret;
128 #if 0
130 #include <errno.h>
131 #include <getopt.h>
132 #include <string.h>
133 #include <unistd.h>
135 int blake2sp_stream( FILE *stream, void *resstream, size_t outbytes )
137 int ret = -1;
138 size_t sum, n;
139 blake2sp_state S[1];
140 static const size_t buffer_length = 16 * ( 1UL << 20 );
141 uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
143 if( !buffer ) return -1;
145 blake2sp_init( S, outbytes );
147 while( 1 )
149 sum = 0;
151 while( 1 )
153 n = fread( buffer + sum, 1, buffer_length - sum, stream );
154 sum += n;
156 if( buffer_length == sum )
157 break;
159 if( 0 == n )
161 if( ferror( stream ) )
162 goto cleanup_buffer;
164 goto final_process;
167 if( feof( stream ) )
168 goto final_process;
171 blake2sp_update( S, buffer, buffer_length );
174 final_process:;
176 if( sum > 0 ) blake2sp_update( S, buffer, sum );
178 blake2sp_final( S, resstream, outbytes );
179 ret = 0;
180 cleanup_buffer:
181 free( buffer );
182 return ret;
186 int blake2bp_stream( FILE *stream, void *resstream, size_t outbytes )
188 int ret = -1;
189 size_t sum, n;
190 blake2bp_state S[1];
191 static const size_t buffer_length = 16 * ( 1UL << 20 );
192 uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
194 if( !buffer ) return -1;
196 blake2bp_init( S, outbytes );
198 while( 1 )
200 sum = 0;
202 while( 1 )
204 n = fread( buffer + sum, 1, buffer_length - sum, stream );
205 sum += n;
207 if( buffer_length == sum )
208 break;
210 if( 0 == n )
212 if( ferror( stream ) )
213 goto cleanup_buffer;
215 goto final_process;
218 if( feof( stream ) )
219 goto final_process;
222 blake2bp_update( S, buffer, buffer_length );
225 final_process:;
227 if( sum > 0 ) blake2bp_update( S, buffer, sum );
229 blake2bp_final( S, resstream, outbytes );
230 ret = 0;
231 cleanup_buffer:
232 free( buffer );
233 return ret;
236 typedef int ( *blake2fn )( FILE *, void *, size_t );
239 static void usage( char **argv, int errcode )
241 FILE *out = errcode ? stderr : stdout;
242 fprintf( out, "Usage: %s [OPTION]... [FILE]...\n", argv[0] );
243 fprintf( out, "\n" );
244 fprintf( out, "With no FILE, or when FILE is -, read standard input.\n" );
245 fprintf( out, "\n" );
246 fprintf( out, " -a <algo> hash algorithm (blake2b is default): \n"
247 " [blake2b|blake2s|blake2bp|blake2sp]\n" );
248 fprintf( out, " -l <length> digest length in bits, must not exceed the maximum for\n"
249 " the selected algorithm and must be a multiple of 8\n" );
250 fprintf( out, " --tag create a BSD-style checksum\n" );
251 fprintf( out, " --help display this help and exit\n" );
252 exit( errcode );
256 int main( int argc, char **argv )
258 blake2fn blake2_stream = blake2b_stream;
259 unsigned long maxbytes = BLAKE2B_OUTBYTES;
260 const char *algorithm = "BLAKE2b";
261 unsigned long outbytes = 0;
262 unsigned char hash[BLAKE2B_OUTBYTES] = {0};
263 bool bsdstyle = false;
264 int c, i;
265 opterr = 1;
267 while( 1 )
269 int option_index = 0;
270 char *end = nullptr;
271 unsigned long outbits;
272 static struct option long_options[] = {
273 { "help", no_argument, 0, 0 },
274 { "tag", no_argument, 0, 0 },
275 { nullptr, 0, nullptr, 0 }
278 c = getopt_long( argc, argv, "a:l:", long_options, &option_index );
279 if( c == -1 ) break;
280 switch( c )
282 case 'a':
283 if( 0 == strcmp( optarg, "blake2b" ) )
285 blake2_stream = blake2b_stream;
286 maxbytes = BLAKE2B_OUTBYTES;
287 algorithm = "BLAKE2b";
289 else if ( 0 == strcmp( optarg, "blake2s" ) )
291 blake2_stream = blake2s_stream;
292 maxbytes = BLAKE2S_OUTBYTES;
293 algorithm = "BLAKE2s";
295 else if ( 0 == strcmp( optarg, "blake2bp" ) )
297 blake2_stream = blake2bp_stream;
298 maxbytes = BLAKE2B_OUTBYTES;
299 algorithm = "BLAKE2bp";
301 else if ( 0 == strcmp( optarg, "blake2sp" ) )
303 blake2_stream = blake2sp_stream;
304 maxbytes = BLAKE2S_OUTBYTES;
305 algorithm = "BLAKE2sp";
307 else
309 printf( "Invalid function name: `%s'\n", optarg );
310 usage( argv, 111 );
313 break;
315 case 'l':
316 outbits = strtoul(optarg, &end, 10);
317 if( !end || *end != '\0' || outbits % 8 != 0)
319 printf( "Invalid length argument: `%s'\n", optarg);
320 usage( argv, 111 );
322 outbytes = outbits / 8;
323 break;
325 case 0:
326 if( 0 == strcmp( "help", long_options[option_index].name ) )
327 usage( argv, 0 );
328 else if( 0 == strcmp( "tag", long_options[option_index].name ) )
329 bsdstyle = true;
330 break;
332 case '?':
333 usage( argv, 1 );
334 break;
338 if(outbytes > maxbytes)
340 printf( "Invalid length argument: %lu\n", outbytes * 8 );
341 printf( "Maximum digest length for %s is %lu\n", algorithm, maxbytes * 8 );
342 usage( argv, 111 );
344 else if( outbytes == 0 )
345 outbytes = maxbytes;
347 if( optind == argc )
348 argv[argc++] = (char *) "-";
350 for( i = optind; i < argc; ++i )
352 FILE *f = nullptr;
353 if( argv[i][0] == '-' && argv[i][1] == '\0' )
354 f = stdin;
355 else
356 f = fopen( argv[i], "rb" );
358 if( !f )
360 fprintf( stderr, "Could not open `%s': %s\n", argv[i], strerror( errno ) );
361 continue;
364 if( blake2_stream( f, hash, outbytes ) < 0 )
366 fprintf( stderr, "Failed to hash `%s'\n", argv[i] );
368 else
370 size_t j;
371 if( bsdstyle )
373 if( outbytes < maxbytes )
374 printf( "%s-%lu (%s) = ", algorithm, outbytes * 8, argv[i] );
375 else
376 printf( "%s (%s) = ", algorithm, argv[i] );
379 for( j = 0; j < outbytes; ++j )
380 printf( "%02x", hash[j] );
382 if( bsdstyle )
383 printf( "\n" );
384 else
385 printf( " %s\n", argv[i] );
388 if( f == stdin )
389 clearerr( f );
390 else if( fclose( f ) != 0 )
391 fprintf( stderr, "Could not close `%s': %s\n", argv[i], strerror( errno ) );
394 return 0;
396 #endif