/* * Copyright (c) 2003 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ #include "config.h" #include #include #include #ifdef __APPLE__ #include #endif /* __APPLE__ */ #include #include #include #include #include #include #include #include "applefile.h" #include "cksum.h" #include "base64.h" /* * do_cksum calculates the checksum for PATH and returns it base64 encoded * in cksum_b64 which must be of size SZ_BASE64_E( EVP_MAX_MD_SIZE ). * * return values: * < 0 system error: errno set, no message given * >= 0 number of bytes check summed */ off_t do_fcksum( int fd, char *cksum_b64 ) { unsigned int md_len; ssize_t rr; off_t size = 0; unsigned char buf[ 8192 ]; extern EVP_MD *md; EVP_MD_CTX mdctx; unsigned char md_value[ EVP_MAX_MD_SIZE ]; EVP_DigestInit( &mdctx, md ); while (( rr = read( fd, buf, sizeof( buf ))) > 0 ) { size += rr; EVP_DigestUpdate( &mdctx, buf, (unsigned int)rr ); } if ( rr < 0 ) { return( -1 ); } EVP_DigestFinal( &mdctx, md_value, &md_len ); base64_e( md_value, md_len, cksum_b64 ); return( size ); } off_t do_cksum( char *path, char *cksum_b64 ) { int fd; off_t size = 0; if (( fd = open( path, O_RDONLY, 0 )) < 0 ) { return( -1 ); } size = do_fcksum( fd, cksum_b64 ); if ( close( fd ) != 0 ) { return( -1 ); } return( size ); } #ifdef __APPLE__ /* * do_acksum calculates the checksum for the encoded apple single file of PATH * and returns it base64 encoded in cksum_b64 which must be of size * SZ_BASE64_E( EVP_MAX_MD_SIZE ). * * return values: * >= 0 number of bytes check summed * < 0 system error: errno set, no message given * * do_acksum should only be called on native HFS+ system. */ off_t do_acksum( char *path, char *cksum_b64, struct applefileinfo *afinfo ) { int dfd, rfd, rc; char buf[ 8192 ], rsrc_path[ MAXPATHLEN ]; off_t size = 0; extern struct as_header as_header; struct as_entry as_entries_endian[ 3 ]; unsigned int md_len; extern EVP_MD *md; EVP_MD_CTX mdctx; unsigned char md_value[ EVP_MAX_MD_SIZE ]; EVP_DigestInit( &mdctx, md ); /* checksum applesingle header */ EVP_DigestUpdate( &mdctx, (char *)&as_header, AS_HEADERLEN ); size += (size_t)AS_HEADERLEN; /* endian handling, sum big-endian header entries */ memcpy( &as_entries_endian, &afinfo->as_ents, ( 3 * sizeof( struct as_entry ))); as_entry_netswap( &as_entries_endian[ AS_FIE ] ); as_entry_netswap( &as_entries_endian[ AS_RFE ] ); as_entry_netswap( &as_entries_endian[ AS_DFE ] ); /* checksum header entries */ EVP_DigestUpdate( &mdctx, (char *)&as_entries_endian, (unsigned int)( 3 * sizeof( struct as_entry ))); size += sizeof( 3 * sizeof( struct as_entry )); /* checksum finder info data */ EVP_DigestUpdate( &mdctx, afinfo->ai.ai_data, FINFOLEN ); size += FINFOLEN; /* checksum rsrc fork data */ if ( afinfo->as_ents[ AS_RFE ].ae_length > 0 ) { if ( snprintf( rsrc_path, MAXPATHLEN, "%s%s", path, _PATH_RSRCFORKSPEC ) >= MAXPATHLEN ) { errno = ENAMETOOLONG; return( -1 ); } if (( rfd = open( rsrc_path, O_RDONLY )) < 0 ) { return( -1 ); } while (( rc = read( rfd, buf, sizeof( buf ))) > 0 ) { EVP_DigestUpdate( &mdctx, buf, (unsigned int)rc ); size += (size_t)rc; } if ( close( rfd ) < 0 ) { return( -1 ); } if ( rc < 0 ) { return( -1 ); } } if (( dfd = open( path, O_RDONLY, 0 )) < 0 ) { return( -1 ); } /* checksum data fork */ while (( rc = read( dfd, buf, sizeof( buf ))) > 0 ) { EVP_DigestUpdate( &mdctx, buf, (unsigned int)rc ); size += (size_t)rc; } if ( rc < 0 ) { return( -1 ); } if ( close( dfd ) < 0 ) { return( -1 ); } EVP_DigestFinal( &mdctx, md_value, &md_len ); base64_e( ( char*)&md_value, md_len, cksum_b64 ); return( size ); } #else /* __APPLE__ */ /* * stub fuction for non-hfs+ machines. * * return values: * -1 system error: non hfs+ system */ off_t do_acksum( char *path, char *cksum_b64, struct applefileinfo *afino ) { errno = EOPNOTSUPP; return( -1 ); } #endif /* __APPLE__ */