From b8754a12212c2e37053e7a74a27a7d7f1f79913c Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Wed, 25 Feb 2015 18:16:33 +0000
Subject: Haiku patch


diff --git a/unix/Makefile b/unix/Makefile
index ab32270..a8e4b85 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -63,9 +63,8 @@ FL = -o funzip$E $(LFLAGS1)
 FL2 = $(LF2)
 
 # general-purpose stuff
-#CP = cp
-CP = ln
-LN = ln
+CP = cp
+LN = ln -s 
 RM = rm -f
 CHMOD = chmod
 BINPERMS = 755
@@ -121,7 +120,7 @@ INSTALL_PROGRAM = $(INSTALL)
 INSTALL_D = mkdir -p
 # on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate
 manext = 1
-prefix = /usr/local
+prefix = $(PREFIX)
 BINDIR = $(prefix)/bin#			where to install executables
 MANDIR = $(prefix)/man/man$(manext)#	where to install man pages
 INSTALLEDBIN = $(BINDIR)/funzip$E $(BINDIR)/unzip$E $(BINDIR)/unzipsfx$E \
@@ -144,7 +143,7 @@ SYSTEMG1 = generic generic_gcc  generic_pkg generic_gccpkg
 SYSTEMG2 = generic1 generic2 generic3 generic_bz2 generic_zlib generic_shlib
 SYSTEMS1 = 386i 3Bx 7300 7300_gcc aix aix_rt amdahl amdahl_eft apollo aviion
 SYSTEMS2 = bsd bsdi bsdi_noasm bull coherent convex cray cray_opt cyber_sgi
-SYSTEMS3 = cygwin dec dnix encore eta freebsd gcc gould hk68 hp hpux
+SYSTEMS3 = cygwin dec dnix encore eta freebsd gcc gould haiku hk68 hp hpux
 SYSTEMS4 = isc isc_gcc isi linux linux_dos linux_noasm linux_shlib linux_shlibz
 SYSTEMS5 = lynx macosx macosx_gcc minix mips mpeix next next10 next2x next3x
 SYSTEMS6 = nextfat osf1 pixel ptx pyramid qnxnto realix regulus rs6000 sco
@@ -778,6 +777,13 @@ gcc:		unix_make
 	$(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O3" LF2=""
 	$(STRIP) $(UNZIPS)
 
+# Haiku:
+haiku:		unix_make
+	$(MAKE) unzips \
+	CC="cc" CFLAGS=" -O3 -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUNICODE_SUPPORT -DUTF8_MAYBE_NATIVE -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS -DNO_SYSDIR" \
+	CRCA_O="" AS="cc -c" LFLAGS1="" LF2="-s" CC_BZ="cc" CFLAGS_BZ=" -O3" \
+	IZ_BZIP2="." D_USE_BZ2="" L_BZ2="" LIBBZ2=""
+
 # Heurikon HK68 (68010), UniPlus+ System V 5.0, Green Hills C-68000
 hk68:		unix_make
 	$(MAKE) unzips CC="gcc" LD="gcc"\
diff --git a/unzpriv.h b/unzpriv.h
index dc9eff5..2cb9af6 100644
--- a/unzpriv.h
+++ b/unzpriv.h
@@ -306,6 +306,14 @@
 #endif
 
 /*---------------------------------------------------------------------------
+    Haiku section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef __HAIKU__
+#  include <sys/stat.h>
+#endif
+
+/*---------------------------------------------------------------------------
     Human68k/X680x0 section:
   ---------------------------------------------------------------------------*/
 
@@ -741,7 +749,7 @@
 #  define DOS_T20_VMS
 #endif
 
-#if (defined(__ATHEOS__) || defined(__BEOS__))
+#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(__HAIKU__)) 
 #  define ATH_BEO
 #endif
 
-- 
1.8.3.4


From 6f4d07e984224be0b5edf1b7dd18d7a603ceec70 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Wed, 25 Feb 2015 21:47:12 +0000
Subject: merge beos.c into unix.c with __HAIKU__


diff --git a/unix/Makefile b/unix/Makefile
index a8e4b85..e27058e 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -781,7 +781,7 @@ gcc:		unix_make
 haiku:		unix_make
 	$(MAKE) unzips \
 	CC="cc" CFLAGS=" -O3 -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT -DUNICODE_WCHAR -DUNICODE_SUPPORT -DUTF8_MAYBE_NATIVE -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS -DNO_SYSDIR" \
-	CRCA_O="" AS="cc -c" LFLAGS1="" LF2="-s" CC_BZ="cc" CFLAGS_BZ=" -O3" \
+	CRCA_O="" AS="cc -c" LFLAGS1="-lbe" LF2="-s" CC_BZ="cc" CFLAGS_BZ=" -O3" \
 	IZ_BZIP2="." D_USE_BZ2="" L_BZ2="" LIBBZ2=""
 
 # Heurikon HK68 (68010), UniPlus+ System V 5.0, Green Hills C-68000
diff --git a/unix/unix.c b/unix/unix.c
index efa97fc..df76ffc 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -46,6 +46,21 @@
 #  endif
 #endif
 
+#ifdef __HAIKU__
+#include <fs_attr.h>
+#include <ByteOrder.h>
+#include <Mime.h>
+#define EB_BE_FL_BADBITS    0xfe    /* bits currently undefined */
+static uch *scanBeOSexfield  OF((const uch *ef_ptr, unsigned ef_len));
+static void setBeOSexfield   OF((const char *path, uch *extra_field));
+#ifdef BEOS_USE_PRINTEXFIELD
+static void printBeOSexfield OF((int isdir, uch *extra_field));
+#endif
+#ifdef BEOS_ASSIGN_FILETYPE
+static void assign_MIME( const char * );
+#endif
+#endif
+
 #ifdef _POSIX_VERSION
 #  ifndef DIRENT
 #    define DIRENT
@@ -638,6 +653,15 @@ int mapname(__G__ renamed)
                 Info(slide, 0, ((char *)slide, "   creating: %s\n",
                   FnFilter1(G.filename)));
             }
+#ifdef __HAIKU__
+            if (!uO.J_flag) {   /* Handle the BeOS extra field if present. */
+                void *ptr = scanBeOSexfield(G.extra_field,
+                                            G.lrec.extra_field_length);
+                if (ptr) {
+                    setBeOSexfield(G.filename, ptr);
+                }
+            }
+#endif
 #ifndef NO_CHMOD
             /* Filter out security-relevant attributes bits. */
             G.pInfo->file_attr = filtattr(__G__ G.pInfo->file_attr);
@@ -663,6 +687,17 @@ int mapname(__G__ renamed)
             /* set dir time (note trailing '/') */
             return (error & ~MPN_MASK) | MPN_CREATED_DIR;
         }
+#ifdef __HAIKU__
+        /* TODO: should we re-write the BeOS extra field data in case it's */
+        /* changed?  The answer is yes. [Sept 1999 - cjh]                  */
+        if (!uO.J_flag) {   /* Handle the BeOS extra field if present. */
+            void *ptr = scanBeOSexfield(G.extra_field,
+                                        G.lrec.extra_field_length);
+            if (ptr) {
+                setBeOSexfield(G.filename, ptr);
+            }
+        }
+#endif
         /* dir existed already; don't look for data to extract */
         return (error & ~MPN_MASK) | MPN_INF_SKIP;
     }
@@ -1128,15 +1163,27 @@ void close_outfile(__G)    /* GRR: change to return PK-style warning level */
 # else
         extent attribsize = 0;
 # endif
+        extent slnk_entrysize;
+        slinkentry *slnk_entry;
+#ifdef __HAIKU__
+		uch *BeOS_exfld;
+        if (!uO.J_flag) {
+            /* Symlinks can have attributes, too. */
+            BeOS_exfld = scanBeOSexfield(G.extra_field,
+                                         G.lrec.extra_field_length);
+            if (BeOS_exfld) {
+                attribsize = makeword(EB_LEN + BeOS_exfld) + EB_HEADSIZE;
+            }
+        }
+#endif
         /* size of the symlink entry is the sum of
          *  (struct size (includes 1st '\0') + 1 additional trailing '\0'),
          *  system specific attribute data size (might be 0),
          *  and the lengths of name and link target.
          */
-        extent slnk_entrysize = (sizeof(slinkentry) + 1) + attribsize +
+        slnk_entrysize = (sizeof(slinkentry) + 1) + attribsize +
                                 ucsize + strlen(G.filename);
-        slinkentry *slnk_entry;
-
+        
         if (slnk_entrysize < ucsize) {
             Info(slide, 0x201, ((char *)slide,
               "warning:  symbolic link (%s) failed: mem alloc overflow\n",
@@ -1156,15 +1203,19 @@ void close_outfile(__G)    /* GRR: change to return PK-style warning level */
         slnk_entry->targetlen = ucsize;
         slnk_entry->attriblen = attribsize;
 # ifdef SET_SYMLINK_ATTRIBS
-        memcpy(slnk_entry->buf, &(G.pInfo->file_attr),
+#ifdef __HAIKU__
+        if (attribsize > 0)
+            memcpy(slnk_entry->buf, BeOS_exfld, attribsize);
+#else        
+            memcpy(slnk_entry->buf, &(G.pInfo->file_attr),
                sizeof(unsigned));
         if (have_uidgid_flg)
             memcpy(slnk_entry->buf + 4, z_uidgid, sizeof(z_uidgid));
+#endif
 # endif
         slnk_entry->target = slnk_entry->buf + slnk_entry->attriblen;
         slnk_entry->fname = slnk_entry->target + ucsize + 1;
         strcpy(slnk_entry->fname, G.filename);
-
         /* move back to the start of the file to re-read the "link data" */
         rewind(G.outfile);
 
@@ -1204,6 +1255,23 @@ void close_outfile(__G)    /* GRR: change to return PK-style warning level */
     fclose(G.outfile);
 #endif
 
+#ifdef __HAIKU__
+    /* handle the BeOS extra field if present */
+    if (!uO.J_flag) {
+        void *ptr = scanBeOSexfield(G.extra_field,
+                                    G.lrec.extra_field_length);
+
+        if (ptr) {
+            setBeOSexfield(G.filename, ptr);
+#ifdef BEOS_ASSIGN_FILETYPE
+        } else {
+            /* Otherwise, ask the system to try assigning a MIME type. */
+            assign_MIME( G.filename );
+#endif
+        }
+    }
+#endif
+
     /* if -X option was specified and we have UID/GID info, restore it */
     if (have_uidgid_flg
         /* check that both uid and gid values fit into their data sizes */
@@ -1278,6 +1346,9 @@ int set_symlnk_attribs(__G__ slnk_entry)
     slinkentry *slnk_entry;
 {
     if (slnk_entry->attriblen > 0) {
+#ifdef __HAIKU__
+      setBeOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf);
+#endif
 # if (!defined(NO_LCHOWN))
       if (slnk_entry->attriblen > sizeof(unsigned)) {
         ulg *z_uidgid_p = (zvoid *)(slnk_entry->buf + sizeof(unsigned));
@@ -1874,3 +1945,281 @@ static void qlfix(__G__ ef_ptr, ef_len)
     }
 }
 #endif /* QLZIP */
+
+#ifdef __HAIKU__
+
+/******************************/
+/* Extra field functions      */
+/******************************/
+
+/*
+** Scan the extra fields in extra_field, and look for a BeOS EF; return a
+** pointer to that EF, or NULL if it's not there.
+*/
+static uch *scanBeOSexfield(const uch *ef_ptr, unsigned ef_len)
+{
+    while( ef_ptr != NULL && ef_len >= EB_HEADSIZE ) {
+        unsigned eb_id  = makeword(EB_ID + ef_ptr);
+        unsigned eb_len = makeword(EB_LEN + ef_ptr);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            Trace((stderr,
+              "scanBeOSexfield: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        if (eb_id == EF_BEOS && eb_len >= EB_BEOS_HLEN) {
+            return (uch *)ef_ptr;
+        }
+
+        ef_ptr += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+    }
+
+    return NULL;
+}
+
+/* Used by setBeOSexfield():
+
+Set a file/directory's attributes to the attributes passed in.
+
+If set_file_attrs() fails, an error will be returned:
+
+     EOK - no errors occurred
+
+(other values will be whatever the failed function returned; no docs
+yet, or I'd list a few)
+*/
+static int set_file_attrs( const char *name,
+                           const unsigned char *attr_buff,
+                           const off_t attr_size )
+{
+    int                  retval = EOK;
+    unsigned char       *ptr;
+    const unsigned char *guard;
+    int                  fd;
+
+    ptr   = (unsigned char *)attr_buff;
+    guard = ptr + attr_size;
+
+    fd = open(name, O_RDWR | O_NOTRAVERSE);
+    if (fd < 0) {
+        return errno; /* should it be -fd ? */
+    }
+
+    while (ptr < guard) {
+        ssize_t              wrote_bytes;
+        struct attr_info     fa_info;
+        const char          *attr_name;
+        unsigned char       *attr_data;
+
+        attr_name  = (char *)&(ptr[0]);
+        ptr       += strlen(attr_name) + 1;
+
+        /* The attr_info data is stored in big-endian format because the */
+        /* PowerPC port was here first.                                  */
+        memcpy(&fa_info, ptr, sizeof(struct attr_info));
+        fa_info.type = (uint32)B_BENDIAN_TO_HOST_INT32( fa_info.type );
+        fa_info.size = (off_t)B_BENDIAN_TO_HOST_INT64( fa_info.size );
+        ptr     += sizeof(struct attr_info);
+
+        if (fa_info.size < 0LL) {
+            Info(slide, 0x201, ((char *)slide,
+                 "warning: skipping attribute with invalid length (%Ld)\n",
+                 fa_info.size));
+            break;
+        }
+
+        attr_data  = ptr;
+        ptr       += fa_info.size;
+
+        if (ptr > guard) {
+            /* We've got a truncated attribute. */
+            Info(slide, 0x201, ((char *)slide,
+                 "warning: truncated attribute\n"));
+            break;
+        }
+
+        /* Wave the magic wand... this will swap Be-known types properly. */
+        (void)swap_data( fa_info.type, attr_data, fa_info.size,
+                         B_SWAP_BENDIAN_TO_HOST );
+
+        wrote_bytes = fs_write_attr(fd, attr_name, fa_info.type, 0,
+                                    attr_data, fa_info.size);
+        if (wrote_bytes != fa_info.size) {
+            Info(slide, 0x201, ((char *)slide,
+                 "warning: wrote %ld attribute bytes of %ld\n",
+                 (unsigned long)wrote_bytes,(unsigned long)fa_info.size));
+        }
+    }
+
+    close(fd);
+
+    return retval;
+}
+
+static void setBeOSexfield(const char *path, uch *extra_field)
+{
+    uch *ptr       = extra_field;
+    ush  id        = 0;
+    ush  size      = 0;
+    ulg  full_size = 0;
+    uch  flags     = 0;
+    uch *attrbuff  = NULL;
+    int retval;
+
+    if( extra_field == NULL ) {
+        return;
+    }
+
+    /* Collect the data from the extra field buffer. */
+    id        = makeword(ptr);    ptr += 2;   /* we don't use this... */
+    size      = makeword(ptr);    ptr += 2;
+    full_size = makelong(ptr);    ptr += 4;
+    flags     = *ptr;             ptr++;
+
+    /* Do a little sanity checking. */
+    if (flags & EB_BE_FL_BADBITS) {
+        /* corrupted or unsupported */
+        Info(slide, 0x201, ((char *)slide,
+          "Unsupported flags set for this BeOS extra field, skipping.\n"));
+        return;
+    }
+    if (size <= EB_BEOS_HLEN) {
+        /* corrupted, unsupported, or truncated */
+        Info(slide, 0x201, ((char *)slide,
+             "BeOS extra field is %d bytes, should be at least %d.\n", size,
+             EB_BEOS_HLEN));
+        return;
+    }
+    if (full_size < (size - EB_BEOS_HLEN)) {
+        /* possible old archive? will this screw up on valid archives? */
+        Info(slide, 0x201, ((char *)slide,
+             "Skipping attributes: BeOS extra field is %d bytes, "
+             "data size is %ld.\n", size - EB_BEOS_HLEN, full_size));
+        return;
+    }
+
+    /* Find the BeOS file attribute data. */
+    if (flags & EB_BE_FL_UNCMPR) {
+        /* Uncompressed data */
+        attrbuff = ptr;
+    } else {
+        /* Compressed data */
+        attrbuff = (uch *)malloc( full_size );
+        if (attrbuff == NULL) {
+            /* No memory to uncompress attributes */
+            Info(slide, 0x201, ((char *)slide,
+                 "Can't allocate memory to uncompress file attributes.\n"));
+            return;
+        }
+
+        retval = memextract(__G__ attrbuff, full_size,
+                            ptr, size - EB_BEOS_HLEN);
+        if( retval != PK_OK ) {
+            /* error uncompressing attributes */
+            Info(slide, 0x201, ((char *)slide,
+                 "Error uncompressing file attributes.\n"));
+
+            /* Some errors here might not be so bad; we should expect */
+            /* some truncated data, for example.  If the data was     */
+            /* corrupt, we should _not_ attempt to restore the attrs  */
+            /* for this file... there's no way to detect what attrs   */
+            /* are good and which are bad.                            */
+            free (attrbuff);
+            return;
+        }
+    }
+
+    /* Now attempt to set the file attributes on the extracted file. */
+    retval = set_file_attrs(path, attrbuff, (off_t)full_size);
+    if (retval != EOK) {
+        Info(slide, 0x201, ((char *)slide,
+             "Error writing file attributes.\n"));
+    }
+
+    /* Clean up, if necessary */
+    if (attrbuff != ptr) {
+        free(attrbuff);
+    }
+
+    return;
+}
+
+#ifdef BEOS_USE_PRINTEXFIELD
+static void printBeOSexfield( int isdir, uch *extra_field )
+{
+    uch *ptr       = extra_field;
+    ush  id        = 0;
+    ush  size      = 0;
+    ulg  full_size = 0;
+    uch  flags     = 0;
+
+    /* Tell picky compilers to be quiet. */
+    isdir = isdir;
+
+    if( extra_field == NULL ) {
+        return;
+    }
+
+    /* Collect the data from the buffer. */
+    id        = makeword( ptr );    ptr += 2;
+    size      = makeword( ptr );    ptr += 2;
+    full_size = makelong( ptr );    ptr += 4;
+    flags     = *ptr;               ptr++;
+
+    if( id != EF_BEOS ) {
+        /* not a 'Be' field */
+        printf("\t*** Unknown field type (0x%04x, '%c%c')\n", id,
+               (char)(id >> 8), (char)id);
+    }
+
+    if( flags & EB_BE_FL_BADBITS ) {
+        /* corrupted or unsupported */
+        printf("\t*** Corrupted BeOS extra field:\n");
+        printf("\t*** unknown bits set in the flags\n");
+        printf("\t*** (Possibly created by an old version of zip for BeOS.\n");
+    }
+
+    if( size <= EB_BEOS_HLEN ) {
+        /* corrupted, unsupported, or truncated */
+        printf("\t*** Corrupted BeOS extra field:\n");
+        printf("\t*** size is %d, should be larger than %d\n", size,
+               EB_BEOS_HLEN );
+    }
+
+    if( flags & EB_BE_FL_UNCMPR ) {
+        /* Uncompressed data */
+        printf("\tBeOS extra field data (uncompressed):\n");
+        printf("\t\t%ld data bytes\n", full_size);
+    } else {
+        /* Compressed data */
+        printf("\tBeOS extra field data (compressed):\n");
+        printf("\t\t%d compressed bytes\n", size - EB_BEOS_HLEN);
+        printf("\t\t%ld uncompressed bytes\n", full_size);
+    }
+}
+#endif
+
+#ifdef BEOS_ASSIGN_FILETYPE
+/* Note: This will no longer be necessary in BeOS PR4; update_mime_info()    */
+/* will be updated to build its own absolute pathname if it's not given one. */
+static void assign_MIME( const char *file )
+{
+    char *fullname;
+    char buff[PATH_MAX], cwd_buff[PATH_MAX];
+    int retval;
+
+    if( file[0] == '/' ) {
+        fullname = (char *)file;
+    } else {
+        sprintf( buff, "%s/%s", getcwd( cwd_buff, PATH_MAX ), file );
+        fullname = buff;
+    }
+
+    retval = update_mime_info( fullname, FALSE, TRUE, TRUE );
+}
+#endif
+
+#endif
diff --git a/unzip.c b/unzip.c
index 8dbfc95..e44c2e4 100644
--- a/unzip.c
+++ b/unzip.c
@@ -2164,7 +2164,7 @@ static void help_extended(__G)
   "  -i   [MacOS] Ignore filenames in MacOS extra field.  Instead, use name in",
   "         standard header.",
   "  -j   Junk paths and deposit all files in extraction directory.",
-  "  -J   [BeOS] Junk file attributes.  [MacOS] Ignore MacOS specific info.",
+  "  -J   [BeOS, Haiku] Junk file attributes.  [MacOS] Ignore MacOS specific info.",
   "  -K   [AtheOS, BeOS, Unix] Restore SUID/SGID/Tacky file attributes.",
   "  -L   Convert to lowercase any names from uppercase only file system.",
   "  -LL  Convert all files to lowercase.",
diff --git a/unzip.h b/unzip.h
index 5b2a326..a002d95 100644
--- a/unzip.h
+++ b/unzip.h
@@ -495,7 +495,7 @@ typedef struct _UzpOpts {
     int scanimage;      /* -I: scan image files */
 #endif
     int jflag;          /* -j: junk pathnames (unzip) */
-#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(MACOS))
+#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(MACOS) || defined(__HAIKU__))
     int J_flag;         /* -J: ignore AtheOS/BeOS/MacOS e. f. info (unzip) */
 #endif
 #if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX))
-- 
1.8.3.4


From ecc3dc54154357bb5a484deda277eac429e1b186 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Wed, 25 Feb 2015 22:24:29 +0000
Subject: apply patch from Ingo Weinhold


diff --git a/unix/unix.c b/unix/unix.c
index df76ffc..ff7605a 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -1993,7 +1993,7 @@ yet, or I'd list a few)
 */
 static int set_file_attrs( const char *name,
                            const unsigned char *attr_buff,
-                           const off_t attr_size )
+                           const off_t total_attr_size )
 {
     int                  retval = EOK;
     unsigned char       *ptr;
@@ -2001,38 +2001,39 @@ static int set_file_attrs( const char *name,
     int                  fd;
 
     ptr   = (unsigned char *)attr_buff;
-    guard = ptr + attr_size;
+    guard = ptr + total_attr_size;
 
-    fd = open(name, O_RDWR | O_NOTRAVERSE);
+    fd = open(name, O_RDONLY | O_NOTRAVERSE);
     if (fd < 0) {
         return errno; /* should it be -fd ? */
     }
 
     while (ptr < guard) {
         ssize_t              wrote_bytes;
-        struct attr_info     fa_info;
         const char          *attr_name;
         unsigned char       *attr_data;
+        uint32              attr_type;
+        int64              attr_size;
 
         attr_name  = (char *)&(ptr[0]);
         ptr       += strlen(attr_name) + 1;
 
         /* The attr_info data is stored in big-endian format because the */
         /* PowerPC port was here first.                                  */
-        memcpy(&fa_info, ptr, sizeof(struct attr_info));
-        fa_info.type = (uint32)B_BENDIAN_TO_HOST_INT32( fa_info.type );
-        fa_info.size = (off_t)B_BENDIAN_TO_HOST_INT64( fa_info.size );
-        ptr     += sizeof(struct attr_info);
+        memcpy(&attr_type, ptr, 4); ptr += 4;
+        memcpy(&attr_size, ptr, 8); ptr += 8;
+        attr_type = (uint32)B_BENDIAN_TO_HOST_INT32( attr_type );
+        attr_size = (off_t)B_BENDIAN_TO_HOST_INT64( attr_size );
 
-        if (fa_info.size < 0LL) {
+        if (attr_size < 0LL) {
             Info(slide, 0x201, ((char *)slide,
                  "warning: skipping attribute with invalid length (%Ld)\n",
-                 fa_info.size));
+                 attr_size));
             break;
         }
 
         attr_data  = ptr;
-        ptr       += fa_info.size;
+        ptr       += attr_size;
 
         if (ptr > guard) {
             /* We've got a truncated attribute. */
@@ -2042,15 +2043,15 @@ static int set_file_attrs( const char *name,
         }
 
         /* Wave the magic wand... this will swap Be-known types properly. */
-        (void)swap_data( fa_info.type, attr_data, fa_info.size,
+        (void)swap_data( attr_type, attr_data, attr_size,
                          B_SWAP_BENDIAN_TO_HOST );
 
-        wrote_bytes = fs_write_attr(fd, attr_name, fa_info.type, 0,
-                                    attr_data, fa_info.size);
-        if (wrote_bytes != fa_info.size) {
+        wrote_bytes = fs_write_attr(fd, attr_name, attr_type, 0,
+                                    attr_data, attr_size);
+        if (wrote_bytes != attr_size) {
             Info(slide, 0x201, ((char *)slide,
                  "warning: wrote %ld attribute bytes of %ld\n",
-                 (unsigned long)wrote_bytes,(unsigned long)fa_info.size));
+                 (unsigned long)wrote_bytes,(unsigned long)attr_size));
         }
     }
 
-- 
1.8.3.4


From f6d3d7ea8574aeb43884158ea4c6fd51a9b68880 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Tue, 5 May 2015 21:04:17 +0000
Subject: Haiku: attribsize should be a minimum of 4


diff --git a/unix/unix.c b/unix/unix.c
index ff7605a..d3098e8 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -1204,7 +1204,7 @@ void close_outfile(__G)    /* GRR: change to return PK-style warning level */
         slnk_entry->attriblen = attribsize;
 # ifdef SET_SYMLINK_ATTRIBS
 #ifdef __HAIKU__
-        if (attribsize > 0)
+        if (attribsize > sizeof(unsigned))
             memcpy(slnk_entry->buf, BeOS_exfld, attribsize);
 #else        
             memcpy(slnk_entry->buf, &(G.pInfo->file_attr),
@@ -1347,7 +1347,9 @@ int set_symlnk_attribs(__G__ slnk_entry)
 {
     if (slnk_entry->attriblen > 0) {
 #ifdef __HAIKU__
-      setBeOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf);
+      if (slnk_entry->attriblen > sizeof(unsigned)) {
+        setBeOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf);
+      }
 #endif
 # if (!defined(NO_LCHOWN))
       if (slnk_entry->attriblen > sizeof(unsigned)) {
-- 
1.8.3.4

