X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=bin%2Fmegatron%2Fmacbin.c;h=51b7ac5f616ede35aeb604892e423e3bbf4a35e6;hb=dc0f3a5d97e0878f6f0e85ae3ae74ad68be6c037;hp=f149dc7b0ceeb013a35b57d84a262766e26d18dc;hpb=31843674b7bd32eabcce3a1ad6159b4f94921f79;p=netatalk.git diff --git a/bin/megatron/macbin.c b/bin/megatron/macbin.c index f149dc7b..51b7ac5f 100644 --- a/bin/megatron/macbin.c +++ b/bin/megatron/macbin.c @@ -1,11 +1,19 @@ +/* + * $Id: macbin.c,v 1.15 2010-01-27 21:27:53 didg Exp $ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + #include #include #include #include #include #include +#include #include -#include #include #include #include @@ -13,15 +21,20 @@ #include #include #include "megatron.h" +#include "macbin.h" +#include "updcrc.h" -#define DEBUG 0 +/* This allows megatron to generate .bin files that won't choke other + well-known converter apps. It also makes sure that checksums + always match. (RLB) */ +#define MACBINARY_PLAY_NICE_WITH_OTHERS /* String used to indicate standard input instead of a disk file. Should be a string not normally used for a file */ #ifndef STDIN # define STDIN "-" -#endif +#endif /* STDIN */ /* Yes and no */ @@ -32,13 +45,11 @@ */ #define HEADBUFSIZ 128 -u_short updcrc(); - /* Both input and output routines use this struct and the following globals; therefore this module can only be used for one of the two functions at a time. */ -struct bin_file_data { +static struct bin_file_data { u_int32_t forklen[ NUMFORKS ]; char path[ MAXPATHLEN + 1]; int filed; @@ -47,7 +58,7 @@ struct bin_file_data { } bin; extern char *forkname[]; -u_char head_buf[HEADBUFSIZ]; +static u_char head_buf[HEADBUFSIZ]; /* * bin_open must be called first. pass it a filename that is supposed @@ -55,10 +66,7 @@ u_char head_buf[HEADBUFSIZ]; * somewhat initialized; bin_filed is set. */ -bin_open( binfile, flags, fh, options ) - char *binfile; - int flags, options; - struct FHeader *fh; +int bin_open(char *binfile, int flags, struct FHeader *fh, int options) { int maxlen; int rc; @@ -67,15 +75,16 @@ bin_open( binfile, flags, fh, options ) #if DEBUG fprintf( stderr, "entering bin_open\n" ); -#endif +#endif /* DEBUG */ /* call localtime so that we get the timezone offset */ bin.gmtoff = 0; #ifndef NO_STRUCT_TM_GMTOFF time(&t); - if (tp = localtime(&t)) + tp = localtime(&t); + if (tp) bin.gmtoff = tp->tm_gmtoff; -#endif +#endif /* ! NO_STRUCT_TM_GMTOFF */ if ( flags == O_RDONLY ) { /* input */ if ( strcmp( binfile, STDIN ) == 0 ) { @@ -86,7 +95,7 @@ bin_open( binfile, flags, fh, options ) } #if DEBUG fprintf( stderr, "opened %s for read\n", binfile ); -#endif +#endif /* DEBUG */ if ((( rc = test_header() ) > 0 ) && ( bin_header_read( fh, rc ) == 0 )) { return( 0 ); @@ -101,7 +110,7 @@ bin_open( binfile, flags, fh, options ) #if DEBUG fprintf( stderr, "sizeof bin.path\t\t\t%d\n", sizeof( bin.path )); fprintf( stderr, "maxlen \t\t\t\t%d\n", maxlen ); -#endif +#endif /* DEBUG */ strncpy( bin.path, fh->name, maxlen ); strncpy( bin.path, mtoupath( bin.path ), maxlen ); strncat( bin.path, ".bin", maxlen - strlen( bin.path )); @@ -112,7 +121,7 @@ bin_open( binfile, flags, fh, options ) #if DEBUG fprintf( stderr, "opened %s for write\n", (options & OPTION_STDOUT) ? "(stdout)" : bin.path ); -#endif +#endif /* DEBUG */ } if ( bin_header_write( fh ) != 0 ) { @@ -130,12 +139,11 @@ bin_open( binfile, flags, fh, options ) * Otherwise, a value of -1 is returned. */ -bin_close( keepflag ) - int keepflag; +int bin_close(int keepflag) { #if DEBUG fprintf( stderr, "entering bin_close\n" ); -#endif +#endif /* DEBUG */ if ( keepflag == KEEP ) { return( close( bin.filed )); } else if ( keepflag == TRASH ) { @@ -155,24 +163,21 @@ bin_close( keepflag ) * return zero and no more than that. */ -bin_read( fork, buffer, length ) - int fork; - char *buffer; - int length; +ssize_t bin_read( int fork, char *buffer, size_t length) { char *buf_ptr; - int readlen; - int cc = 1; + size_t readlen; + ssize_t cc = 1; off_t pos; #if DEBUG >= 3 fprintf( stderr, "bin_read: fork is %s\n", forkname[ fork ] ); fprintf( stderr, "bin_read: remaining length is %d\n", bin.forklen[fork] ); -#endif +#endif /* DEBUG >= 3 */ - if ( bin.forklen[ fork ] < 0 ) { - fprintf( stderr, "This should never happen, dude!\n" ); - return( bin.forklen[ fork ] ); + if (bin.forklen[fork] > 0x7FFFFFFF) { + fprintf(stderr, "This should never happen, dude! fork length == %u\n", bin.forklen[fork]); + return -1; } if ( bin.forklen[ fork ] == 0 ) { @@ -180,13 +185,14 @@ bin_read( fork, buffer, length ) pos = lseek( bin.filed, 0, SEEK_CUR ); #if DEBUG fprintf( stderr, "current position is %ld\n", pos ); -#endif - if (pos = pos % HEADBUFSIZ) { +#endif /* DEBUG */ + pos %= HEADBUFSIZ; + if (pos != 0) { pos = lseek( bin.filed, HEADBUFSIZ - pos, SEEK_CUR ); } #if DEBUG fprintf( stderr, "current position is %ld\n", pos ); -#endif +#endif /* DEBUG */ } return( 0 ); } @@ -199,14 +205,14 @@ bin_read( fork, buffer, length ) #if DEBUG >= 3 fprintf( stderr, "bin_read: readlen is %d\n", readlen ); fprintf( stderr, "bin_read: cc is %d\n", cc ); -#endif +#endif /* DEBUG >= 3 */ buf_ptr = buffer; while (( readlen > 0 ) && ( cc > 0 )) { if (( cc = read( bin.filed, buf_ptr, readlen )) > 0 ) { #if DEBUG >= 3 fprintf( stderr, "bin_read: cc is %d\n", cc ); -#endif +#endif /* DEBUG >= 3 */ readlen -= cc; buf_ptr += cc; } @@ -218,7 +224,7 @@ bin_read( fork, buffer, length ) #if DEBUG >= 3 fprintf( stderr, "bin_read: chars read is %d\n", cc ); -#endif +#endif /* DEBUG >= 3 */ return( cc ); } @@ -226,21 +232,20 @@ bin_read( fork, buffer, length ) * bin_write */ -bin_write( fork, buffer, length ) - int fork; - char *buffer; - int length; +ssize_t bin_write(int fork, char *buffer, size_t length) { char *buf_ptr; - int writelen; - int cc = 0; + ssize_t writelen; + ssize_t cc = 0; off_t pos; - u_char padchar = 0; + u_char padchar = 0x7f; + /* Not sure why, but it seems this must be 0x7f to match + other converters, not 0. (RLB) */ #if DEBUG >= 3 fprintf( stderr, "bin_write: fork is %s\n", forkname[ fork ] ); fprintf( stderr, "bin_write: remaining length is %d\n", bin.forklen[fork] ); -#endif +#endif /* DEBUG >= 3 */ if (( fork == RESOURCE ) && ( bin.forklen[ DATA ] != 0 )) { fprintf( stderr, "Forklength error.\n" ); @@ -257,7 +262,7 @@ bin_write( fork, buffer, length ) #if DEBUG >= 3 fprintf( stderr, "bin_write: write length is %d\n", writelen ); -#endif +#endif /* DEBUG >= 3 */ while (( writelen > 0 ) && ( cc >= 0 )) { cc = write( bin.filed, buf_ptr, writelen ); @@ -268,12 +273,8 @@ bin_write( fork, buffer, length ) perror( "Couldn't write to macbinary file:" ); return( cc ); } - bin.forklen[ fork ] -= length; - if ( bin.forklen[ fork ] < 0 ) { - fprintf( stderr, "This should never happen, dude!\n" ); - return( bin.forklen[ fork ] ); - } + bin.forklen[fork] -= length; /* * add the padding at end of data and resource forks @@ -283,8 +284,9 @@ bin_write( fork, buffer, length ) pos = lseek( bin.filed, 0, SEEK_CUR ); #if DEBUG fprintf( stderr, "current position is %ld\n", pos ); -#endif - if (pos = pos % HEADBUFSIZ) { /* pad only if we need to */ +#endif /* DEBUG */ + pos %= HEADBUFSIZ; + if (pos != 0) { /* pad only if we need to */ pos = lseek( bin.filed, HEADBUFSIZ - pos - 1, SEEK_CUR ); if ( write( bin.filed, &padchar, 1 ) != 1 ) { perror( "Couldn't write to macbinary file:" ); @@ -293,12 +295,12 @@ bin_write( fork, buffer, length ) } #if DEBUG fprintf( stderr, "current position is %ld\n", pos ); -#endif +#endif /* DEBUG */ } #if DEBUG fprintf( stderr, "\n" ); -#endif +#endif /* DEBUG */ return( length ); } @@ -309,9 +311,7 @@ bin_write( fork, buffer, length ) * of the bytes of the other two forks can be read, as well. */ -bin_header_read( fh, revision ) - struct FHeader *fh; - int revision; +int bin_header_read(struct FHeader *fh, int revision) { u_short mask; @@ -350,8 +350,14 @@ bin_header_read( fh, revision ) fh->mod_date = AD_DATE_FROM_UNIX(fh->mod_date); fh->backup_date = AD_DATE_START; memcpy( &fh->finder_info, head_buf + 65, 8 ); + +#ifndef MACBINARY_PLAY_NICE_WITH_OTHERS /* (RLB) */ memcpy( &fh->finder_info.fdFlags, head_buf + 73, 1 ); fh->finder_info.fdFlags &= mask; +#else /* ! MACBINARY_PLAY_NICE_WITH_OTHERS */ + memcpy( &fh->finder_info.fdFlags, head_buf + 73, 2 ); +#endif /* ! MACBINARY_PLAY_NICE_WITH_OTHERS */ + memcpy(&fh->finder_info.fdLocation, head_buf + 75, 4 ); memcpy(&fh->finder_info.fdFldr, head_buf + 79, 2 ); memcpy(&fh->forklen[ DATA ], head_buf + 83, 4 ); @@ -368,6 +374,7 @@ bin_header_read( fh, revision ) #if DEBUG >= 5 { short flags; + long flags_long; fprintf( stderr, "Values read by bin_header_read\n" ); fprintf( stderr, "name length\t\t%d\n", head_buf[ 1 ] ); @@ -381,11 +388,18 @@ bin_header_read( fh, revision ) memcpy( &flags, &fh->finder_info.fdFlags, sizeof( flags )); flags = ntohs( flags ); fprintf( stderr, "flags\t\t\t%x\n", flags ); + + /* Show fdLocation too (RLB) */ + memcpy( &flags_long, &fh->finder_info.fdLocation, + sizeof( flags_long )); + flags_long = ntohl( flags_long ); + fprintf( stderr, "location flags\t\t%lx\n", flags_long ); + fprintf( stderr, "data fork length\t%ld\n", bin.forklen[DATA] ); fprintf( stderr, "resource fork length\t%ld\n", bin.forklen[RESOURCE] ); fprintf( stderr, "\n" ); } -#endif +#endif /* DEBUG >= 5 */ return( 0 ); } @@ -397,8 +411,7 @@ bin_header_read( fh, revision ) * bin_header_write and bin_header_read are opposites. */ -bin_header_write( fh ) - struct FHeader *fh; +int bin_header_write(struct FHeader *fh) { char *write_ptr; u_int32_t t; @@ -409,7 +422,13 @@ bin_header_write( fh ) head_buf[ 1 ] = (u_char)strlen( fh->name ); memcpy( head_buf + 2, fh->name, head_buf[ 1 ] ); memcpy( head_buf + 65, &fh->finder_info, 8 ); - memcpy( head_buf + 73, &fh->finder_info.fdFlags, 1); + +#ifndef MACBINARY_PLAY_NICE_WITH_OTHERS /* (RLB) */ + memcpy( head_buf + 73, &fh->finder_info.fdFlags, 1 ); +#else /* ! MACBINARY_PLAY_NICE_WITH_OTHERS */ + memcpy( head_buf + 73, &fh->finder_info.fdFlags, 2 ); +#endif /* ! MACBINARY_PLAY_NICE_WITH_OTHERS */ + memcpy( head_buf + 75, &fh->finder_info.fdLocation, 4 ); memcpy( head_buf + 79, &fh->finder_info.fdFldr, 2 ); memcpy( head_buf + 83, &fh->forklen[ DATA ], 4 ); @@ -438,16 +457,30 @@ bin_header_write( fh ) #if DEBUG >= 5 { + short flags; + long flags_long; + fprintf( stderr, "Values written by bin_header_write\n" ); fprintf( stderr, "name length\t\t%d\n", head_buf[ 1 ] ); fprintf( stderr, "file name\t\t%s\n", (char *)&head_buf[ 2 ] ); fprintf( stderr, "type\t\t\t%.4s\n", (char *)&head_buf[ 65 ] ); fprintf( stderr, "creator\t\t\t%.4s\n", (char *)&head_buf[ 69 ] ); + + memcpy( &flags, &fh->finder_info.fdFlags, sizeof( flags )); + flags = ntohs( flags ); + fprintf( stderr, "flags\t\t\t%x\n", flags ); + + /* Show fdLocation too (RLB) */ + memcpy( &flags_long, &fh->finder_info.fdLocation, + sizeof( flags_long )); + flags_long = ntohl( flags_long ); + fprintf( stderr, "location flags\t\t%ldx\n", flags_long ); + fprintf( stderr, "data fork length\t%ld\n", bin.forklen[DATA] ); fprintf( stderr, "resource fork length\t%ld\n", bin.forklen[RESOURCE] ); fprintf( stderr, "\n" ); } -#endif +#endif /* DEBUG >= 5 */ write_ptr = (char *)head_buf; wc = sizeof( head_buf ); @@ -483,16 +516,16 @@ bin_header_write( fh ) * so, the check for byte 74 isn't very useful. */ -test_header() +int test_header(void) { const char zeros[25] = ""; - u_int32_t cc; + ssize_t cc; u_short header_crc; u_char namelen; #if DEBUG fprintf( stderr, "entering test_header\n" ); -#endif +#endif /* DEBUG */ cc = read( bin.filed, (char *)head_buf, sizeof( head_buf )); if ( cc < sizeof( head_buf )) { @@ -502,7 +535,7 @@ test_header() #if DEBUG fprintf( stderr, "was able to read HEADBUFSIZ bytes\n" ); -#endif +#endif /* DEBUG */ /* check for macbinary III header */ if (memcmp(head_buf + 102, "mBIN", 4) == 0) @@ -512,7 +545,7 @@ test_header() if (( head_buf[ 0 ] == 0 ) || ( head_buf[ 74 ] == 0 )) { #if DEBUG fprintf( stderr, "byte 0 and 74 are both zero\n" ); -#endif +#endif /* DEBUG */ bin.headercrc = updcrc( (u_short) 0, head_buf, 124 ); memcpy(&header_crc, head_buf + 124, sizeof( header_crc )); header_crc = ntohs( header_crc ); @@ -522,7 +555,7 @@ test_header() #if DEBUG fprintf( stderr, "header crc didn't pan out\n" ); -#endif +#endif /* DEBUG */ } /* now see if we have a macbinary file. */ @@ -532,7 +565,7 @@ test_header() memcpy( &namelen, head_buf + 1, sizeof( namelen )); #if DEBUG fprintf( stderr, "name length is %d\n", namelen ); -#endif +#endif /* DEBUG */ if (( namelen < 1 ) || ( namelen > 63 )) { return( -1 ); } @@ -542,19 +575,20 @@ test_header() return -1; /* macbinary forks aren't larger than 0x7FFFFF */ + /* we allow forks to be larger, breaking the specs */ memcpy(&cc, head_buf + 83, sizeof(cc)); cc = ntohl(cc); - if (cc > 0x7FFFFF) + if (cc > 0x7FFFFFFF) return -1; memcpy(&cc, head_buf + 87, sizeof(cc)); cc = ntohl(cc); - if (cc > 0x7FFFFF) + if (cc > 0x7FFFFFFF) return -1; #if DEBUG fprintf( stderr, "byte 82 is zero and name length is cool\n" ); -#endif +#endif /* DEBUG */ return( 1 ); }