2023-06-04 22:41:52 +00:00
/*
* * This utility program reads the " manifest " and " manifest.uuid " files
2023-06-05 01:05:46 +00:00
* * in a Fossil - generated source tree ( where the repository has the
* * " manifest " setting turned on - this is true for SQLite and Fossil itself )
* * and verifies that the source code files are complete and unaltered by
* * checking the SHA1 and SHA3 hashes of the source files contained in the
* * " manifest " file .
2023-06-04 22:56:31 +00:00
* *
2023-06-05 01:05:46 +00:00
* * On success it prints : " OK $HASH " where $ HASH is the SHA3 - 256 hash of
* * the check - in for the source tree . If it finds any discrepencies , it
* * prints " Derived from $HASH with changes to: " followed by a list of files
* * which have been altered .
2023-06-04 22:56:31 +00:00
* *
2023-06-05 01:05:46 +00:00
* * USAGE :
2023-06-04 22:56:31 +00:00
* *
2023-06-08 15:27:35 +00:00
* * src - verify [ - x ] [ - v ] $ ( ROOT )
2023-06-05 01:05:46 +00:00
* *
* * Where ROOT is the root of the source tree - the directory that contains
* * the " manifest " and " manifest.uuid " files . Add the " -v " option for
2023-06-08 15:27:35 +00:00
* * some debugging output . With the - x option , the output is in a format
* * that is intended to be read by a script rather by a human . The - x output
* * format always has the SHA3 hash of the source check - in on the first line
* * and lists files that have changed on subsequent lines .
* *
* * Additional debugging options :
2023-06-05 01:05:46 +00:00
* *
* * src - verify - - sha1 FILE . . .
* * src - verify - - sha3 FILE . . .
* *
* * Compute the SHA1 or SHA3 - 256 hashes for all of the FILEs named
* *
* * COMPILING :
* *
* * This utility is self - contained . It uses only the standard library .
* * There are no other dependencies . Just compile it and run it .
* *
* * LIMITATIONS :
* *
* * * This utility assumes that the check - in hash uses SHA3 - 256.
* * It is ok for individual file hashes to be SHA1 , but the
* * check - in itself must use a SHA3 - 256 hash .
2023-06-04 22:41:52 +00:00
*/
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# if !defined(_WIN32)
# include <unistd.h>
# else
# include <io.h>
2023-08-15 18:08:14 +00:00
# ifndef R_OK
# define R_OK 04
# endif
# ifndef access
# define access(f,m) _access((f),(m))
# endif
2023-06-04 22:41:52 +00:00
# endif
typedef unsigned long long int u64 ;
/*
* * The SHA1 implementation below is adapted from :
* *
* * $ NetBSD : sha1 . c , v 1.6 2009 / 11 / 06 20 : 31 : 18 joerg Exp $
* * $ OpenBSD : sha1 . c , v 1.9 1997 / 07 / 23 21 : 12 : 32 kstailey Exp $
* *
* * SHA - 1 in C
* * By Steve Reid < steve @ edmweb . com >
* * 100 % Public Domain
*/
typedef struct SHA1Context SHA1Context ;
struct SHA1Context {
unsigned int state [ 5 ] ;
unsigned int count [ 2 ] ;
unsigned char buffer [ 64 ] ;
} ;
/*
* blk0 ( ) and blk ( ) perform the initial expand .
* I got the idea of expanding during the round function from SSLeay
*
* blk0le ( ) for little - endian and blk0be ( ) for big - endian .
*/
# define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
# define rol(x,k) SHA_ROT(x,k,32-(k))
# define ror(x,k) SHA_ROT(x,32-(k),k)
# define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
| ( rol ( block [ i ] , 8 ) & 0x00FF00FF ) )
# define blk0be(i) block[i]
# define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
^ block [ ( i + 2 ) & 15 ] ^ block [ i & 15 ] , 1 ) )
/*
* ( R0 + R1 ) , R2 , R3 , R4 are the different operations ( rounds ) used in SHA1
*
* Rl0 ( ) for little - endian and Rb0 ( ) for big - endian . Endianness is
* determined at run - time .
*/
# define Rl0(v,w,x,y,z,i) \
z + = ( ( w & ( x ^ y ) ) ^ y ) + blk0le ( i ) + 0x5A827999 + rol ( v , 5 ) ; w = ror ( w , 2 ) ;
# define Rb0(v,w,x,y,z,i) \
z + = ( ( w & ( x ^ y ) ) ^ y ) + blk0be ( i ) + 0x5A827999 + rol ( v , 5 ) ; w = ror ( w , 2 ) ;
# define R1(v,w,x,y,z,i) \
z + = ( ( w & ( x ^ y ) ) ^ y ) + blk ( i ) + 0x5A827999 + rol ( v , 5 ) ; w = ror ( w , 2 ) ;
# define R2(v,w,x,y,z,i) \
z + = ( w ^ x ^ y ) + blk ( i ) + 0x6ED9EBA1 + rol ( v , 5 ) ; w = ror ( w , 2 ) ;
# define R3(v,w,x,y,z,i) \
z + = ( ( ( w | x ) & y ) | ( w & x ) ) + blk ( i ) + 0x8F1BBCDC + rol ( v , 5 ) ; w = ror ( w , 2 ) ;
# define R4(v,w,x,y,z,i) \
z + = ( w ^ x ^ y ) + blk ( i ) + 0xCA62C1D6 + rol ( v , 5 ) ; w = ror ( w , 2 ) ;
/*
* Hash a single 512 - bit block . This is the core of the algorithm .
*/
# define a qq[0]
# define b qq[1]
# define c qq[2]
# define d qq[3]
# define e qq[4]
void SHA1Transform ( unsigned int state [ 5 ] , const unsigned char buffer [ 64 ] )
{
unsigned int qq [ 5 ] ; /* a, b, c, d, e; */
static int one = 1 ;
unsigned int block [ 16 ] ;
memcpy ( block , buffer , 64 ) ;
memcpy ( qq , state , 5 * sizeof ( unsigned int ) ) ;
/* Copy context->state[] to working vars */
/*
a = state [ 0 ] ;
b = state [ 1 ] ;
c = state [ 2 ] ;
d = state [ 3 ] ;
e = state [ 4 ] ;
*/
/* 4 rounds of 20 operations each. Loop unrolled. */
if ( 1 = = * ( unsigned char * ) & one ) {
Rl0 ( a , b , c , d , e , 0 ) ; Rl0 ( e , a , b , c , d , 1 ) ; Rl0 ( d , e , a , b , c , 2 ) ; Rl0 ( c , d , e , a , b , 3 ) ;
Rl0 ( b , c , d , e , a , 4 ) ; Rl0 ( a , b , c , d , e , 5 ) ; Rl0 ( e , a , b , c , d , 6 ) ; Rl0 ( d , e , a , b , c , 7 ) ;
Rl0 ( c , d , e , a , b , 8 ) ; Rl0 ( b , c , d , e , a , 9 ) ; Rl0 ( a , b , c , d , e , 10 ) ; Rl0 ( e , a , b , c , d , 11 ) ;
Rl0 ( d , e , a , b , c , 12 ) ; Rl0 ( c , d , e , a , b , 13 ) ; Rl0 ( b , c , d , e , a , 14 ) ; Rl0 ( a , b , c , d , e , 15 ) ;
} else {
Rb0 ( a , b , c , d , e , 0 ) ; Rb0 ( e , a , b , c , d , 1 ) ; Rb0 ( d , e , a , b , c , 2 ) ; Rb0 ( c , d , e , a , b , 3 ) ;
Rb0 ( b , c , d , e , a , 4 ) ; Rb0 ( a , b , c , d , e , 5 ) ; Rb0 ( e , a , b , c , d , 6 ) ; Rb0 ( d , e , a , b , c , 7 ) ;
Rb0 ( c , d , e , a , b , 8 ) ; Rb0 ( b , c , d , e , a , 9 ) ; Rb0 ( a , b , c , d , e , 10 ) ; Rb0 ( e , a , b , c , d , 11 ) ;
Rb0 ( d , e , a , b , c , 12 ) ; Rb0 ( c , d , e , a , b , 13 ) ; Rb0 ( b , c , d , e , a , 14 ) ; Rb0 ( a , b , c , d , e , 15 ) ;
}
R1 ( e , a , b , c , d , 16 ) ; R1 ( d , e , a , b , c , 17 ) ; R1 ( c , d , e , a , b , 18 ) ; R1 ( b , c , d , e , a , 19 ) ;
R2 ( a , b , c , d , e , 20 ) ; R2 ( e , a , b , c , d , 21 ) ; R2 ( d , e , a , b , c , 22 ) ; R2 ( c , d , e , a , b , 23 ) ;
R2 ( b , c , d , e , a , 24 ) ; R2 ( a , b , c , d , e , 25 ) ; R2 ( e , a , b , c , d , 26 ) ; R2 ( d , e , a , b , c , 27 ) ;
R2 ( c , d , e , a , b , 28 ) ; R2 ( b , c , d , e , a , 29 ) ; R2 ( a , b , c , d , e , 30 ) ; R2 ( e , a , b , c , d , 31 ) ;
R2 ( d , e , a , b , c , 32 ) ; R2 ( c , d , e , a , b , 33 ) ; R2 ( b , c , d , e , a , 34 ) ; R2 ( a , b , c , d , e , 35 ) ;
R2 ( e , a , b , c , d , 36 ) ; R2 ( d , e , a , b , c , 37 ) ; R2 ( c , d , e , a , b , 38 ) ; R2 ( b , c , d , e , a , 39 ) ;
R3 ( a , b , c , d , e , 40 ) ; R3 ( e , a , b , c , d , 41 ) ; R3 ( d , e , a , b , c , 42 ) ; R3 ( c , d , e , a , b , 43 ) ;
R3 ( b , c , d , e , a , 44 ) ; R3 ( a , b , c , d , e , 45 ) ; R3 ( e , a , b , c , d , 46 ) ; R3 ( d , e , a , b , c , 47 ) ;
R3 ( c , d , e , a , b , 48 ) ; R3 ( b , c , d , e , a , 49 ) ; R3 ( a , b , c , d , e , 50 ) ; R3 ( e , a , b , c , d , 51 ) ;
R3 ( d , e , a , b , c , 52 ) ; R3 ( c , d , e , a , b , 53 ) ; R3 ( b , c , d , e , a , 54 ) ; R3 ( a , b , c , d , e , 55 ) ;
R3 ( e , a , b , c , d , 56 ) ; R3 ( d , e , a , b , c , 57 ) ; R3 ( c , d , e , a , b , 58 ) ; R3 ( b , c , d , e , a , 59 ) ;
R4 ( a , b , c , d , e , 60 ) ; R4 ( e , a , b , c , d , 61 ) ; R4 ( d , e , a , b , c , 62 ) ; R4 ( c , d , e , a , b , 63 ) ;
R4 ( b , c , d , e , a , 64 ) ; R4 ( a , b , c , d , e , 65 ) ; R4 ( e , a , b , c , d , 66 ) ; R4 ( d , e , a , b , c , 67 ) ;
R4 ( c , d , e , a , b , 68 ) ; R4 ( b , c , d , e , a , 69 ) ; R4 ( a , b , c , d , e , 70 ) ; R4 ( e , a , b , c , d , 71 ) ;
R4 ( d , e , a , b , c , 72 ) ; R4 ( c , d , e , a , b , 73 ) ; R4 ( b , c , d , e , a , 74 ) ; R4 ( a , b , c , d , e , 75 ) ;
R4 ( e , a , b , c , d , 76 ) ; R4 ( d , e , a , b , c , 77 ) ; R4 ( c , d , e , a , b , 78 ) ; R4 ( b , c , d , e , a , 79 ) ;
/* Add the working vars back into context.state[] */
state [ 0 ] + = a ;
state [ 1 ] + = b ;
state [ 2 ] + = c ;
state [ 3 ] + = d ;
state [ 4 ] + = e ;
}
/*
* SHA1Init - Initialize new context
*/
static void SHA1Init ( SHA1Context * context ) {
/* SHA1 initialization constants */
context - > state [ 0 ] = 0x67452301 ;
context - > state [ 1 ] = 0xEFCDAB89 ;
context - > state [ 2 ] = 0x98BADCFE ;
context - > state [ 3 ] = 0x10325476 ;
context - > state [ 4 ] = 0xC3D2E1F0 ;
context - > count [ 0 ] = context - > count [ 1 ] = 0 ;
}
/*
* Run your data through this .
*/
static void SHA1Update (
SHA1Context * context ,
const unsigned char * data ,
unsigned int len
) {
unsigned int i , j ;
j = context - > count [ 0 ] ;
if ( ( context - > count [ 0 ] + = len < < 3 ) < j )
context - > count [ 1 ] + = ( len > > 29 ) + 1 ;
j = ( j > > 3 ) & 63 ;
if ( ( j + len ) > 63 ) {
( void ) memcpy ( & context - > buffer [ j ] , data , ( i = 64 - j ) ) ;
SHA1Transform ( context - > state , context - > buffer ) ;
for ( ; i + 63 < len ; i + = 64 )
SHA1Transform ( context - > state , & data [ i ] ) ;
j = 0 ;
} else {
i = 0 ;
}
( void ) memcpy ( & context - > buffer [ j ] , & data [ i ] , len - i ) ;
}
/*
* Add padding and return the message digest .
*/
static void SHA1Final ( unsigned char * digest , SHA1Context * context ) {
unsigned int i ;
unsigned char finalcount [ 8 ] ;
for ( i = 0 ; i < 8 ; i + + ) {
finalcount [ i ] = ( unsigned char ) ( ( context - > count [ ( i > = 4 ? 0 : 1 ) ]
> > ( ( 3 - ( i & 3 ) ) * 8 ) ) & 255 ) ; /* Endian independent */
}
SHA1Update ( context , ( const unsigned char * ) " \200 " , 1 ) ;
while ( ( context - > count [ 0 ] & 504 ) ! = 448 )
SHA1Update ( context , ( const unsigned char * ) " \0 " , 1 ) ;
SHA1Update ( context , finalcount , 8 ) ; /* Should cause a SHA1Transform() */
if ( digest ) {
for ( i = 0 ; i < 20 ; i + + )
digest [ i ] = ( unsigned char )
( ( context - > state [ i > > 2 ] > > ( ( 3 - ( i & 3 ) ) * 8 ) ) & 255 ) ;
}
}
/*
* * Macros to determine whether the machine is big or little endian ,
* * and whether or not that determination is run - time or compile - time .
* *
* * For best performance , an attempt is made to guess at the byte - order
* * using C - preprocessor macros . If that is unsuccessful , or if
* * - DSHA3_BYTEORDER = 0 is set , then byte - order is determined
* * at run - time .
*/
# ifndef SHA3_BYTEORDER
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined ( __x86_64 ) | | defined ( __x86_64__ ) | | defined ( _M_X64 ) | | \
defined ( _M_AMD64 ) | | defined ( _M_ARM ) | | defined ( __x86 ) | | \
defined ( __arm__ )
# define SHA3_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__)
# define SHA3_BYTEORDER 4321
# else
# define SHA3_BYTEORDER 0
# endif
# endif
/*
* * State structure for a SHA3 hash in progress
*/
typedef struct SHA3Context SHA3Context ;
struct SHA3Context {
union {
u64 s [ 25 ] ; /* Keccak state. 5x5 lines of 64 bits each */
unsigned char x [ 1600 ] ; /* ... or 1600 bytes */
} u ;
unsigned nRate ; /* Bytes of input accepted per Keccak iteration */
unsigned nLoaded ; /* Input bytes loaded into u.x[] so far this cycle */
unsigned ixMask ; /* Insert next input into u.x[nLoaded^ixMask]. */
} ;
/*
* * A single step of the Keccak mixing function for a 1600 - bit state
*/
static void KeccakF1600Step ( SHA3Context * p ) {
int i ;
u64 B0 , B1 , B2 , B3 , B4 ;
u64 C0 , C1 , C2 , C3 , C4 ;
u64 D0 , D1 , D2 , D3 , D4 ;
static const u64 RC [ ] = {
0x0000000000000001ULL , 0x0000000000008082ULL ,
0x800000000000808aULL , 0x8000000080008000ULL ,
0x000000000000808bULL , 0x0000000080000001ULL ,
0x8000000080008081ULL , 0x8000000000008009ULL ,
0x000000000000008aULL , 0x0000000000000088ULL ,
0x0000000080008009ULL , 0x000000008000000aULL ,
0x000000008000808bULL , 0x800000000000008bULL ,
0x8000000000008089ULL , 0x8000000000008003ULL ,
0x8000000000008002ULL , 0x8000000000000080ULL ,
0x000000000000800aULL , 0x800000008000000aULL ,
0x8000000080008081ULL , 0x8000000000008080ULL ,
0x0000000080000001ULL , 0x8000000080008008ULL
} ;
# define A00 (p->u.s[0])
# define A01 (p->u.s[1])
# define A02 (p->u.s[2])
# define A03 (p->u.s[3])
# define A04 (p->u.s[4])
# define A10 (p->u.s[5])
# define A11 (p->u.s[6])
# define A12 (p->u.s[7])
# define A13 (p->u.s[8])
# define A14 (p->u.s[9])
# define A20 (p->u.s[10])
# define A21 (p->u.s[11])
# define A22 (p->u.s[12])
# define A23 (p->u.s[13])
# define A24 (p->u.s[14])
# define A30 (p->u.s[15])
# define A31 (p->u.s[16])
# define A32 (p->u.s[17])
# define A33 (p->u.s[18])
# define A34 (p->u.s[19])
# define A40 (p->u.s[20])
# define A41 (p->u.s[21])
# define A42 (p->u.s[22])
# define A43 (p->u.s[23])
# define A44 (p->u.s[24])
# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
for ( i = 0 ; i < 24 ; i + = 4 ) {
C0 = A00 ^ A10 ^ A20 ^ A30 ^ A40 ;
C1 = A01 ^ A11 ^ A21 ^ A31 ^ A41 ;
C2 = A02 ^ A12 ^ A22 ^ A32 ^ A42 ;
C3 = A03 ^ A13 ^ A23 ^ A33 ^ A43 ;
C4 = A04 ^ A14 ^ A24 ^ A34 ^ A44 ;
D0 = C4 ^ ROL64 ( C1 , 1 ) ;
D1 = C0 ^ ROL64 ( C2 , 1 ) ;
D2 = C1 ^ ROL64 ( C3 , 1 ) ;
D3 = C2 ^ ROL64 ( C4 , 1 ) ;
D4 = C3 ^ ROL64 ( C0 , 1 ) ;
B0 = ( A00 ^ D0 ) ;
B1 = ROL64 ( ( A11 ^ D1 ) , 44 ) ;
B2 = ROL64 ( ( A22 ^ D2 ) , 43 ) ;
B3 = ROL64 ( ( A33 ^ D3 ) , 21 ) ;
B4 = ROL64 ( ( A44 ^ D4 ) , 14 ) ;
A00 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A00 ^ = RC [ i ] ;
A11 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A22 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A33 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A44 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B2 = ROL64 ( ( A20 ^ D0 ) , 3 ) ;
B3 = ROL64 ( ( A31 ^ D1 ) , 45 ) ;
B4 = ROL64 ( ( A42 ^ D2 ) , 61 ) ;
B0 = ROL64 ( ( A03 ^ D3 ) , 28 ) ;
B1 = ROL64 ( ( A14 ^ D4 ) , 20 ) ;
A20 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A31 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A42 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A03 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A14 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B4 = ROL64 ( ( A40 ^ D0 ) , 18 ) ;
B0 = ROL64 ( ( A01 ^ D1 ) , 1 ) ;
B1 = ROL64 ( ( A12 ^ D2 ) , 6 ) ;
B2 = ROL64 ( ( A23 ^ D3 ) , 25 ) ;
B3 = ROL64 ( ( A34 ^ D4 ) , 8 ) ;
A40 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A01 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A12 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A23 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A34 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B1 = ROL64 ( ( A10 ^ D0 ) , 36 ) ;
B2 = ROL64 ( ( A21 ^ D1 ) , 10 ) ;
B3 = ROL64 ( ( A32 ^ D2 ) , 15 ) ;
B4 = ROL64 ( ( A43 ^ D3 ) , 56 ) ;
B0 = ROL64 ( ( A04 ^ D4 ) , 27 ) ;
A10 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A21 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A32 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A43 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A04 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B3 = ROL64 ( ( A30 ^ D0 ) , 41 ) ;
B4 = ROL64 ( ( A41 ^ D1 ) , 2 ) ;
B0 = ROL64 ( ( A02 ^ D2 ) , 62 ) ;
B1 = ROL64 ( ( A13 ^ D3 ) , 55 ) ;
B2 = ROL64 ( ( A24 ^ D4 ) , 39 ) ;
A30 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A41 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A02 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A13 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A24 = B4 ^ ( ( ~ B0 ) & B1 ) ;
C0 = A00 ^ A20 ^ A40 ^ A10 ^ A30 ;
C1 = A11 ^ A31 ^ A01 ^ A21 ^ A41 ;
C2 = A22 ^ A42 ^ A12 ^ A32 ^ A02 ;
C3 = A33 ^ A03 ^ A23 ^ A43 ^ A13 ;
C4 = A44 ^ A14 ^ A34 ^ A04 ^ A24 ;
D0 = C4 ^ ROL64 ( C1 , 1 ) ;
D1 = C0 ^ ROL64 ( C2 , 1 ) ;
D2 = C1 ^ ROL64 ( C3 , 1 ) ;
D3 = C2 ^ ROL64 ( C4 , 1 ) ;
D4 = C3 ^ ROL64 ( C0 , 1 ) ;
B0 = ( A00 ^ D0 ) ;
B1 = ROL64 ( ( A31 ^ D1 ) , 44 ) ;
B2 = ROL64 ( ( A12 ^ D2 ) , 43 ) ;
B3 = ROL64 ( ( A43 ^ D3 ) , 21 ) ;
B4 = ROL64 ( ( A24 ^ D4 ) , 14 ) ;
A00 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A00 ^ = RC [ i + 1 ] ;
A31 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A12 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A43 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A24 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B2 = ROL64 ( ( A40 ^ D0 ) , 3 ) ;
B3 = ROL64 ( ( A21 ^ D1 ) , 45 ) ;
B4 = ROL64 ( ( A02 ^ D2 ) , 61 ) ;
B0 = ROL64 ( ( A33 ^ D3 ) , 28 ) ;
B1 = ROL64 ( ( A14 ^ D4 ) , 20 ) ;
A40 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A21 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A02 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A33 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A14 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B4 = ROL64 ( ( A30 ^ D0 ) , 18 ) ;
B0 = ROL64 ( ( A11 ^ D1 ) , 1 ) ;
B1 = ROL64 ( ( A42 ^ D2 ) , 6 ) ;
B2 = ROL64 ( ( A23 ^ D3 ) , 25 ) ;
B3 = ROL64 ( ( A04 ^ D4 ) , 8 ) ;
A30 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A11 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A42 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A23 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A04 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B1 = ROL64 ( ( A20 ^ D0 ) , 36 ) ;
B2 = ROL64 ( ( A01 ^ D1 ) , 10 ) ;
B3 = ROL64 ( ( A32 ^ D2 ) , 15 ) ;
B4 = ROL64 ( ( A13 ^ D3 ) , 56 ) ;
B0 = ROL64 ( ( A44 ^ D4 ) , 27 ) ;
A20 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A01 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A32 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A13 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A44 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B3 = ROL64 ( ( A10 ^ D0 ) , 41 ) ;
B4 = ROL64 ( ( A41 ^ D1 ) , 2 ) ;
B0 = ROL64 ( ( A22 ^ D2 ) , 62 ) ;
B1 = ROL64 ( ( A03 ^ D3 ) , 55 ) ;
B2 = ROL64 ( ( A34 ^ D4 ) , 39 ) ;
A10 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A41 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A22 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A03 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A34 = B4 ^ ( ( ~ B0 ) & B1 ) ;
C0 = A00 ^ A40 ^ A30 ^ A20 ^ A10 ;
C1 = A31 ^ A21 ^ A11 ^ A01 ^ A41 ;
C2 = A12 ^ A02 ^ A42 ^ A32 ^ A22 ;
C3 = A43 ^ A33 ^ A23 ^ A13 ^ A03 ;
C4 = A24 ^ A14 ^ A04 ^ A44 ^ A34 ;
D0 = C4 ^ ROL64 ( C1 , 1 ) ;
D1 = C0 ^ ROL64 ( C2 , 1 ) ;
D2 = C1 ^ ROL64 ( C3 , 1 ) ;
D3 = C2 ^ ROL64 ( C4 , 1 ) ;
D4 = C3 ^ ROL64 ( C0 , 1 ) ;
B0 = ( A00 ^ D0 ) ;
B1 = ROL64 ( ( A21 ^ D1 ) , 44 ) ;
B2 = ROL64 ( ( A42 ^ D2 ) , 43 ) ;
B3 = ROL64 ( ( A13 ^ D3 ) , 21 ) ;
B4 = ROL64 ( ( A34 ^ D4 ) , 14 ) ;
A00 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A00 ^ = RC [ i + 2 ] ;
A21 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A42 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A13 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A34 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B2 = ROL64 ( ( A30 ^ D0 ) , 3 ) ;
B3 = ROL64 ( ( A01 ^ D1 ) , 45 ) ;
B4 = ROL64 ( ( A22 ^ D2 ) , 61 ) ;
B0 = ROL64 ( ( A43 ^ D3 ) , 28 ) ;
B1 = ROL64 ( ( A14 ^ D4 ) , 20 ) ;
A30 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A01 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A22 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A43 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A14 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B4 = ROL64 ( ( A10 ^ D0 ) , 18 ) ;
B0 = ROL64 ( ( A31 ^ D1 ) , 1 ) ;
B1 = ROL64 ( ( A02 ^ D2 ) , 6 ) ;
B2 = ROL64 ( ( A23 ^ D3 ) , 25 ) ;
B3 = ROL64 ( ( A44 ^ D4 ) , 8 ) ;
A10 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A31 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A02 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A23 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A44 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B1 = ROL64 ( ( A40 ^ D0 ) , 36 ) ;
B2 = ROL64 ( ( A11 ^ D1 ) , 10 ) ;
B3 = ROL64 ( ( A32 ^ D2 ) , 15 ) ;
B4 = ROL64 ( ( A03 ^ D3 ) , 56 ) ;
B0 = ROL64 ( ( A24 ^ D4 ) , 27 ) ;
A40 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A11 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A32 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A03 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A24 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B3 = ROL64 ( ( A20 ^ D0 ) , 41 ) ;
B4 = ROL64 ( ( A41 ^ D1 ) , 2 ) ;
B0 = ROL64 ( ( A12 ^ D2 ) , 62 ) ;
B1 = ROL64 ( ( A33 ^ D3 ) , 55 ) ;
B2 = ROL64 ( ( A04 ^ D4 ) , 39 ) ;
A20 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A41 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A12 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A33 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A04 = B4 ^ ( ( ~ B0 ) & B1 ) ;
C0 = A00 ^ A30 ^ A10 ^ A40 ^ A20 ;
C1 = A21 ^ A01 ^ A31 ^ A11 ^ A41 ;
C2 = A42 ^ A22 ^ A02 ^ A32 ^ A12 ;
C3 = A13 ^ A43 ^ A23 ^ A03 ^ A33 ;
C4 = A34 ^ A14 ^ A44 ^ A24 ^ A04 ;
D0 = C4 ^ ROL64 ( C1 , 1 ) ;
D1 = C0 ^ ROL64 ( C2 , 1 ) ;
D2 = C1 ^ ROL64 ( C3 , 1 ) ;
D3 = C2 ^ ROL64 ( C4 , 1 ) ;
D4 = C3 ^ ROL64 ( C0 , 1 ) ;
B0 = ( A00 ^ D0 ) ;
B1 = ROL64 ( ( A01 ^ D1 ) , 44 ) ;
B2 = ROL64 ( ( A02 ^ D2 ) , 43 ) ;
B3 = ROL64 ( ( A03 ^ D3 ) , 21 ) ;
B4 = ROL64 ( ( A04 ^ D4 ) , 14 ) ;
A00 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A00 ^ = RC [ i + 3 ] ;
A01 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A02 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A03 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A04 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B2 = ROL64 ( ( A10 ^ D0 ) , 3 ) ;
B3 = ROL64 ( ( A11 ^ D1 ) , 45 ) ;
B4 = ROL64 ( ( A12 ^ D2 ) , 61 ) ;
B0 = ROL64 ( ( A13 ^ D3 ) , 28 ) ;
B1 = ROL64 ( ( A14 ^ D4 ) , 20 ) ;
A10 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A11 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A12 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A13 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A14 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B4 = ROL64 ( ( A20 ^ D0 ) , 18 ) ;
B0 = ROL64 ( ( A21 ^ D1 ) , 1 ) ;
B1 = ROL64 ( ( A22 ^ D2 ) , 6 ) ;
B2 = ROL64 ( ( A23 ^ D3 ) , 25 ) ;
B3 = ROL64 ( ( A24 ^ D4 ) , 8 ) ;
A20 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A21 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A22 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A23 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A24 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B1 = ROL64 ( ( A30 ^ D0 ) , 36 ) ;
B2 = ROL64 ( ( A31 ^ D1 ) , 10 ) ;
B3 = ROL64 ( ( A32 ^ D2 ) , 15 ) ;
B4 = ROL64 ( ( A33 ^ D3 ) , 56 ) ;
B0 = ROL64 ( ( A34 ^ D4 ) , 27 ) ;
A30 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A31 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A32 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A33 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A34 = B4 ^ ( ( ~ B0 ) & B1 ) ;
B3 = ROL64 ( ( A40 ^ D0 ) , 41 ) ;
B4 = ROL64 ( ( A41 ^ D1 ) , 2 ) ;
B0 = ROL64 ( ( A42 ^ D2 ) , 62 ) ;
B1 = ROL64 ( ( A43 ^ D3 ) , 55 ) ;
B2 = ROL64 ( ( A44 ^ D4 ) , 39 ) ;
A40 = B0 ^ ( ( ~ B1 ) & B2 ) ;
A41 = B1 ^ ( ( ~ B2 ) & B3 ) ;
A42 = B2 ^ ( ( ~ B3 ) & B4 ) ;
A43 = B3 ^ ( ( ~ B4 ) & B0 ) ;
A44 = B4 ^ ( ( ~ B0 ) & B1 ) ;
}
}
/*
* * Initialize a new hash . iSize determines the size of the hash
* * in bits and should be one of 224 , 256 , 384 , or 512. Or iSize
* * can be zero to use the default hash size of 256 bits .
*/
static void SHA3Init ( SHA3Context * p , int iSize ) {
memset ( p , 0 , sizeof ( * p ) ) ;
if ( iSize > = 128 & & iSize < = 512 ) {
p - > nRate = ( 1600 - ( ( iSize + 31 ) & ~ 31 ) * 2 ) / 8 ;
} else {
p - > nRate = ( 1600 - 2 * 256 ) / 8 ;
}
# if SHA3_BYTEORDER==1234
/* Known to be little-endian at compile-time. No-op */
# elif SHA3_BYTEORDER==4321
p - > ixMask = 7 ; /* Big-endian */
# else
{
static unsigned int one = 1 ;
if ( 1 = = * ( unsigned char * ) & one ) {
/* Little endian. No byte swapping. */
p - > ixMask = 0 ;
} else {
/* Big endian. Byte swap. */
p - > ixMask = 7 ;
}
}
# endif
}
/*
* * Make consecutive calls to the SHA3Update function to add new content
* * to the hash
*/
static void SHA3Update (
SHA3Context * p ,
const unsigned char * aData ,
unsigned int nData
) {
unsigned int i = 0 ;
# if SHA3_BYTEORDER==1234
if ( ( p - > nLoaded % 8 ) = = 0 & & ( ( aData - ( const unsigned char * ) 0 ) & 7 ) = = 0 ) {
for ( ; i + 7 < nData ; i + = 8 ) {
p - > u . s [ p - > nLoaded / 8 ] ^ = * ( u64 * ) & aData [ i ] ;
p - > nLoaded + = 8 ;
if ( p - > nLoaded > = p - > nRate ) {
KeccakF1600Step ( p ) ;
p - > nLoaded = 0 ;
}
}
}
# endif
for ( ; i < nData ; i + + ) {
# if SHA3_BYTEORDER==1234
p - > u . x [ p - > nLoaded ] ^ = aData [ i ] ;
# elif SHA3_BYTEORDER==4321
p - > u . x [ p - > nLoaded ^ 0x07 ] ^ = aData [ i ] ;
# else
p - > u . x [ p - > nLoaded ^ p - > ixMask ] ^ = aData [ i ] ;
# endif
p - > nLoaded + + ;
if ( p - > nLoaded = = p - > nRate ) {
KeccakF1600Step ( p ) ;
p - > nLoaded = 0 ;
}
}
}
/*
* * After all content has been added , invoke SHA3Final ( ) to compute
* * the final hash . The function returns a pointer to the binary
* * hash value .
*/
static unsigned char * SHA3Final ( SHA3Context * p ) {
unsigned int i ;
if ( p - > nLoaded = = p - > nRate - 1 ) {
const unsigned char c1 = 0x86 ;
SHA3Update ( p , & c1 , 1 ) ;
} else {
const unsigned char c2 = 0x06 ;
const unsigned char c3 = 0x80 ;
SHA3Update ( p , & c2 , 1 ) ;
p - > nLoaded = p - > nRate - 1 ;
SHA3Update ( p , & c3 , 1 ) ;
}
for ( i = 0 ; i < p - > nRate ; i + + ) {
p - > u . x [ i + p - > nRate ] = p - > u . x [ i ^ p - > ixMask ] ;
}
return & p - > u . x [ p - > nRate ] ;
}
/*
* * Convert a digest into base - 16.
*/
static void DigestToBase16 ( unsigned char * digest , char * zBuf , int nByte ) {
static const char zEncode [ ] = " 0123456789abcdef " ;
int ix ;
for ( ix = 0 ; ix < nByte ; ix + + ) {
* zBuf + + = zEncode [ ( * digest > > 4 ) & 0xf ] ;
* zBuf + + = zEncode [ * digest + + & 0xf ] ;
}
* zBuf = ' \0 ' ;
}
/*
* * Compute the SHA3 - 256 checksum of a file on disk . Store the resulting
* * checksum in the zCksum .
* *
* * Return the number of errors .
*/
void sha3sum_file ( const char * zFilename , char * zCksum ) {
FILE * in ;
SHA3Context ctx ;
char zBuf [ 10240 ] ;
in = fopen ( zFilename , " rb " ) ;
if ( in = = 0 ) {
zCksum [ 0 ] = 0 ;
return ;
}
SHA3Init ( & ctx , 256 ) ;
for ( ; ; ) {
2023-06-04 22:59:20 +00:00
size_t n ;
2023-06-04 22:41:52 +00:00
n = fread ( zBuf , 1 , sizeof ( zBuf ) , in ) ;
if ( n < = 0 ) break ;
SHA3Update ( & ctx , ( unsigned char * ) zBuf , ( unsigned ) n ) ;
}
fclose ( in ) ;
DigestToBase16 ( SHA3Final ( & ctx ) , zCksum , 32 ) ;
}
/*
* * Compute the SHA1 checksum of a file on disk . Store the resulting
* * checksum in the zCksum .
* *
* * Return the number of errors .
*/
void sha1sum_file ( const char * zFilename , char * zCksum ) {
FILE * in ;
SHA1Context ctx ;
unsigned char zResult [ 20 ] ;
char zBuf [ 10240 ] ;
in = fopen ( zFilename , " rb " ) ;
if ( in = = 0 ) {
zCksum [ 0 ] = 0 ;
return ;
}
SHA1Init ( & ctx ) ;
for ( ; ; ) {
2023-06-04 22:59:20 +00:00
size_t n ;
2023-06-04 22:41:52 +00:00
n = fread ( zBuf , 1 , sizeof ( zBuf ) , in ) ;
if ( n < = 0 ) break ;
SHA1Update ( & ctx , ( unsigned char * ) zBuf , ( unsigned ) n ) ;
}
fclose ( in ) ;
SHA1Final ( zResult , & ctx ) ;
DigestToBase16 ( zResult , zCksum , 20 ) ;
}
2023-06-05 01:05:46 +00:00
/*
* * Decode a fossilized string in - place .
*/
void defossilize ( char * z ) {
2023-06-05 17:12:33 +00:00
int i , j , cc ;
2023-06-05 01:05:46 +00:00
char * zSlash = strchr ( z , ' \\ ' ) ;
if ( zSlash = = 0 ) return ;
i = zSlash - z ;
2023-06-05 17:12:33 +00:00
for ( j = i ; ( cc = z [ i ] ) ! = 0 ; i + + ) {
if ( cc = = ' \\ ' & & z [ i + 1 ] ) {
2023-06-05 01:05:46 +00:00
i + + ;
switch ( z [ i ] ) {
2023-06-05 17:12:33 +00:00
case ' n ' : cc = ' \n ' ; break ;
case ' s ' : cc = ' ' ; break ;
case ' t ' : cc = ' \t ' ; break ;
case ' r ' : cc = ' \r ' ; break ;
case ' v ' : cc = ' \v ' ; break ;
case ' f ' : cc = ' \f ' ; break ;
case ' 0 ' : cc = 0 ; break ;
case ' \\ ' : cc = ' \\ ' ; break ;
default : cc = z [ i ] ; break ;
2023-06-05 01:05:46 +00:00
}
}
2023-06-05 17:12:33 +00:00
z [ j + + ] = cc ;
2023-06-05 01:05:46 +00:00
}
if ( z [ j ] ) z [ j ] = 0 ;
}
2023-06-04 22:41:52 +00:00
/*
* * Report that a single file is incorrect .
*/
static void errorMsg ( int * pnErr , const char * zVers , const char * zFile ) {
if ( * pnErr = = 0 ) {
2023-06-04 22:56:31 +00:00
printf ( " Derived from %.25s with changes to: \n " , zVers ) ;
2023-06-04 22:41:52 +00:00
}
printf ( " %s \n " , zFile ) ;
( * pnErr ) + + ;
}
2023-06-08 15:27:35 +00:00
static void errorMsgNH ( int * pnErr , const char * zVers , const char * zFile ) {
if ( * pnErr = = 0 ) {
printf ( " %s \n " , zVers ) ;
}
printf ( " %s \n " , zFile ) ;
( * pnErr ) + + ;
}
2023-06-04 22:41:52 +00:00
int main ( int argc , char * * argv ) {
int i , j ;
int nDir ;
FILE * in ;
int bDebug = 0 ;
2023-06-08 15:27:35 +00:00
int bNonHuman = 0 ;
2023-06-08 16:19:21 +00:00
int bSeenManifestErr = 0 ;
2023-06-04 22:41:52 +00:00
int nErr = 0 ;
SHA3Context ctx3 ;
2023-06-08 15:27:35 +00:00
const char * zDir = 0 ;
void ( * xErr ) ( int * , const char * , const char * ) ;
2023-06-04 22:41:52 +00:00
char zHash [ 100 ] ;
char zCk [ 100 ] ;
char zVers [ 100 ] ;
2023-06-05 01:05:46 +00:00
char zLine [ 40000 ] ;
char zFile [ 40000 ] ;
2023-06-08 15:27:35 +00:00
xErr = errorMsg ;
for ( i = 1 ; i < argc ; i + + ) {
const char * z = argv [ i ] ;
if ( z [ 0 ] ! = ' - ' ) {
if ( zDir ! = 0 ) {
fprintf ( stderr , " bad argument: %s \n " , z ) ;
return 1 ;
}
zDir = z ;
continue ;
2023-06-04 22:41:52 +00:00
}
2023-06-08 15:27:35 +00:00
if ( z [ 1 ] = = ' - ' & & z [ 2 ] ! = 0 ) z + + ;
if ( strcmp ( argv [ 1 ] , " -sha1 " ) = = 0 ) {
/* For testing purposes, if the first argument is --sha1, then simply
* * compute and print the SHA1 checksum of all subsequent arguments . */
for ( i + + ; i < argc ; i + + ) {
sha1sum_file ( argv [ i ] , zHash ) ;
printf ( " %s %s \n " , zHash , argv [ i ] ) ;
}
return 0 ;
}
if ( strcmp ( argv [ 1 ] , " -sha3 " ) = = 0 ) {
/* For testing purposes, if the first argument is --sha3, then simply
* * compute and print the SHA3 - 256 checksum of all subsequent arguments . */
for ( i + + ; i < argc ; i + + ) {
sha3sum_file ( argv [ i ] , zHash ) ;
printf ( " %s %s \n " , zHash , argv [ i ] ) ;
}
return 0 ;
}
if ( strcmp ( z , " -v " ) = = 0 ) {
bDebug = 1 ;
continue ;
}
if ( strcmp ( z , " -x " ) = = 0 ) {
bNonHuman = 1 ;
xErr = errorMsgNH ;
continue ;
2023-06-04 22:41:52 +00:00
}
fprintf ( stderr , " Usage: %s DIRECTORY \n "
" or: %s --sha1 FILE ... \n "
" or: %s --sha3 FILE ... \n " ,
argv [ 0 ] , argv [ 0 ] , argv [ 0 ] ) ;
return 1 ;
}
if ( strlen ( zDir ) > 1000 ) {
2023-06-08 15:27:35 +00:00
fprintf ( stderr , " Directory argument too big: [%s] \n " , zDir ) ;
2023-06-04 22:41:52 +00:00
return 1 ;
}
nDir = ( int ) strlen ( zDir ) ;
if ( nDir < 0 ) {
2023-06-08 15:27:35 +00:00
fprintf ( stderr , " Directory argument too short. \n " ) ;
2023-06-04 22:41:52 +00:00
return 1 ;
}
memcpy ( zFile , zDir , nDir ) ;
if ( zFile [ nDir - 1 ] ! = ' / ' ) {
zFile [ nDir + + ] = ' / ' ;
}
memcpy ( & zFile [ nDir ] , " manifest " , 9 ) ;
if ( bDebug ) {
printf ( " manifest file: [%s] \n " , zFile ) ;
}
in = fopen ( zFile , " rb " ) ;
if ( in = = 0 ) {
2023-06-08 16:19:21 +00:00
fprintf ( stderr , " missing manifest: \" %s \" \n " , zFile ) ;
2023-06-04 22:41:52 +00:00
return 1 ;
}
SHA3Init ( & ctx3 , 256 ) ;
while ( fgets ( zLine , sizeof ( zLine ) , in ) ) {
if ( zLine [ 0 ] = = ' # ' ) break ;
2023-06-04 22:59:20 +00:00
SHA3Update ( & ctx3 , ( unsigned char * ) zLine , ( int ) strlen ( zLine ) ) ;
2023-06-04 22:41:52 +00:00
}
DigestToBase16 ( SHA3Final ( & ctx3 ) , zVers , 32 ) ;
2023-06-04 22:56:31 +00:00
2023-06-04 22:41:52 +00:00
rewind ( in ) ;
while ( fgets ( zLine , sizeof ( zLine ) , in ) ) {
if ( zLine [ 0 ] ! = ' F ' ) continue ;
if ( zLine [ 1 ] ! = ' ' ) continue ;
for ( i = 2 , j = nDir ; zLine [ i ] ! = 0 & & zLine [ i ] ! = ' ' ; i + + , j + + ) {
if ( j < sizeof ( zFile ) ) zFile [ j ] = zLine [ i ] ;
}
if ( j < sizeof ( zFile ) ) zFile [ j ] = 0 ;
zFile [ sizeof ( zFile ) - 1 ] = 0 ;
2023-06-05 01:05:46 +00:00
defossilize ( & zFile [ nDir ] ) ;
2023-06-04 22:41:52 +00:00
if ( zLine [ i ] ! = ' ' ) {
2023-06-08 16:19:21 +00:00
bSeenManifestErr = 1 ;
continue ;
2023-06-04 22:41:52 +00:00
}
for ( i + + , j = 0 ; zLine [ i ] > = ' 0 ' & & zLine [ i ] < = ' f ' ; i + + , j + + ) {
if ( j < sizeof ( zHash ) ) zHash [ j ] = zLine [ i ] ;
}
if ( j < sizeof ( zHash ) ) zHash [ j ] = 0 ;
zHash [ sizeof ( zHash ) - 1 ] = 0 ;
if ( bDebug ) {
printf ( " %s %s \n " , zFile , zHash ) ;
}
if ( access ( zFile , R_OK ) ! = 0 ) {
2023-06-08 15:27:35 +00:00
xErr ( & nErr , zVers , & zFile [ nDir ] ) ;
2023-06-04 22:41:52 +00:00
continue ;
}
if ( strlen ( zHash ) = = 40 ) {
sha1sum_file ( zFile , zCk ) ;
if ( strcmp ( zHash , zCk ) ! = 0 ) {
2023-06-08 15:27:35 +00:00
xErr ( & nErr , zVers , & zFile [ nDir ] ) ;
2023-06-04 22:41:52 +00:00
}
} else if ( strlen ( zHash ) = = 64 ) {
sha3sum_file ( zFile , zCk ) ;
if ( strcmp ( zHash , zCk ) ! = 0 ) {
2023-06-08 15:27:35 +00:00
xErr ( & nErr , zVers , & zFile [ nDir ] ) ;
2023-06-04 22:41:52 +00:00
}
} else {
2023-06-08 16:19:21 +00:00
bSeenManifestErr = 1 ;
xErr ( & nErr , zVers , & zFile [ nDir ] ) ;
2023-06-04 22:41:52 +00:00
}
}
fclose ( in ) ;
2023-06-04 22:56:31 +00:00
in = 0 ;
2023-06-08 16:19:21 +00:00
if ( bSeenManifestErr ) xErr ( & nErr , zVers , " manifest " ) ;
2023-06-04 22:56:31 +00:00
memcpy ( & zFile [ nDir ] , " manifest.uuid " , 14 ) ;
if ( access ( zFile , R_OK ) ! = 0
| | ( in = fopen ( zFile , " rb " ) ) = = 0
| | fgets ( zLine , sizeof ( zLine ) , in ) = = 0
| | strlen ( zLine ) ! = 65
| | zLine [ 64 ] ! = ' \n '
| | memcmp ( zLine , zVers , 64 ) ! = 0
) {
2023-06-08 15:27:35 +00:00
xErr ( & nErr , zVers , & zFile [ nDir ] ) ;
2023-06-04 22:56:31 +00:00
}
if ( in ) fclose ( in ) ;
2023-06-08 16:19:21 +00:00
2023-06-08 15:27:35 +00:00
if ( bNonHuman ) {
if ( nErr ) return 0 ;
printf ( " %s \n " , zVers ) ;
} else {
if ( nErr ) return nErr ;
printf ( " OK %.25s \n " , zVers ) ;
}
2023-06-04 22:41:52 +00:00
return 0 ;
}