]> arthur.barton.de Git - netatalk.git/blobdiff - bin/megatron/macbin.c
Writing metadata xattr on directories with sticky bit set, FR#94
[netatalk.git] / bin / megatron / macbin.c
index 2b367055cad3ac274ba07c33121ce77a93e7060e..986aac9247c91f6e7cb210030facfa4d566ef01d 100644 (file)
@@ -1,6 +1,9 @@
+/*
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
+#endif /* HAVE_CONFIG_H */
 
 #include <sys/types.h>
 #include <sys/uio.h>
@@ -8,8 +11,8 @@
 #include <sys/param.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <string.h>
 #include <strings.h>
-#include <syslog.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <time.h>
 #include <atalk/adouble.h>
 #include <netatalk/endian.h>
 #include "megatron.h"
+#include "macbin.h"
+#include "updcrc.h"
+
+/* 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
  */
  */
 #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;
@@ -49,7 +57,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
@@ -57,10 +65,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;
@@ -69,15 +74,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 ) {
@@ -88,7 +94,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 );
@@ -103,7 +109,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 ));
@@ -114,7 +120,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 ) {
@@ -132,12 +138,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 ) {
@@ -157,24 +162,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 ) {
@@ -182,13 +184,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 );
     }
@@ -201,14 +204,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;
        }
@@ -220,7 +223,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 );
 }
 
@@ -228,21 +231,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" );
@@ -259,7 +261,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 );
@@ -270,12 +272,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
@@ -285,8 +283,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:" );
@@ -295,12 +294,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 );
 }
@@ -311,9 +310,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;
 
@@ -352,8 +349,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 );
@@ -370,6 +373,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 ] );
@@ -383,11 +387,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 );
 }
@@ -399,8 +410,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;
@@ -411,7 +421,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 );
@@ -440,16 +456,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 );
@@ -485,16 +515,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 )) {
@@ -504,7 +534,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)
@@ -514,7 +544,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 );
@@ -524,7 +554,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. */
@@ -534,7 +564,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 );
     }
@@ -544,19 +574,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 );
 }