From c5e1d2451e5718b9068c08af28c27b43760f16c0 Mon Sep 17 00:00:00 2001
From: Adrien Destugues <pulkomandy@pulkomandy.tk>
Date: Sun, 21 Jan 2018 13:41:08 +0100
Subject: Import revised patch from upstream.


diff --git a/unix/Makefile b/unix/Makefile
index aa889d0..1dd4989 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -1,8 +1,8 @@
 #==============================================================================
 # unix/Makefile
-# - For UnZip, fUnZip, UnZipSFX, and ZipInfo            Revised: 2017-04-28
+# - For UnZip, fUnZip, UnZipSFX, and ZipInfo            Revised: 2018-01-16
 #
-# Copyright (c) 2004-2017 Info-ZIP.  All rights reserved.
+# Copyright (c) 2004-2018 Info-ZIP.  All rights reserved.
 #
 # See the accompanying file LICENSE, version 2009-Jan-2 or later (the
 # contents of which are also included in zip.h) for terms of use.  If,
@@ -129,13 +129,14 @@ MISC_TARGETS = clean  clean_bzip2  clean_docs  clean_exe  dashv
 SYS_TARGETS01 = 386i 3Bx 7300 7300_gcc amdahl amdahl_eft apollo aviion
 SYS_TARGETS02 = bsd bsdi bsdi_noasm bull coherent convex cray cray_opt
 SYS_TARGETS03 = cyber_sgi cygwin dec dnix encore eta freebsd gcc gould
-SYS_TARGETS04 = hk68 hp hpux isc isc_gcc isi linux linux_dos linux_noasm
-SYS_TARGETS05 = lynx macosx macosx_gcc minix mips
-SYS_TARGETS06 = mpeix next next10 next2x next3x nextfat osf1 pixel ptx
-SYS_TARGETS07 = pyramid qnxnto realix regulus sco sco_dos sco_sl sco_x286
-SYS_TARGETS08 = sequent sgi solaris stardent stellar sunos3 sunos4
-SYS_TARGETS09 = sysv sysv_gcc sysv6300 tahoe ti_sysv ultrix vax v7
-SYS_TARGETS10 = xenix xos
+SYS_TARGETS04 = haiku hk68 hp hpux isc isc_gcc isi
+SYS_TARGETS05 = linux linux_dos linux_noasm lynx
+SYS_TARGETS06 = macosx macosx_gcc minix mips mpeix
+SYS_TARGETS07 = next next10 next2x next3x nextfat osf1
+SYS_TARGETS08 = pixel ptx pyramid qnxnto realix regulus
+SYS_TARGETS09 = sco sco_dos sco_sl sco_x286 sequent sgi solaris
+SYS_TARGETS10 = stardent stellar sunos3 sunos4 sysv sysv_gcc sysv6300
+SYS_TARGETS11 = tahoe ti_sysv ultrix vax v7 xenix xos
 
 # By default, print help on which "make" targets to try.
 
@@ -258,6 +259,7 @@ list:
 	@echo "  $(SYS_TARGETS08)"
 	@echo "  $(SYS_TARGETS09)"
 	@echo "  $(SYS_TARGETS10)"
+	@echo "  $(SYS_TARGETS11)"
 	@echo ''
 	@echo 'Miscellaneous targets:'
 	@echo "  $(MISC_TARGETS)"
@@ -1650,6 +1652,17 @@ gcc: unix_make
 	$(MAKE) $(BINS) CC=gcc LD=gcc CFLAGS="-O3" LF2=""
 	$(STRIP) $(UNZIP_PPGMS)
 
+# Haiku
+haiku: unix_make
+	$(MAKE) $(BINS) \
+         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="-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
 hk68: unix_make
 	$(MAKE) $(BINS) CC="gcc" LD="gcc" \
diff --git a/unix/unix.c b/unix/unix.c
index d839c18..ffb997b 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -54,6 +54,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 /* def __HAIKU__ */
+
 #ifdef _POSIX_VERSION
 # ifndef DIRENT
 #  define DIRENT
@@ -690,6 +705,17 @@ int mapname(__G__ renamed)
                 G.action_msg_str = "creat";
 #endif /* def ENABLE_USER_PROGRESS */
             }
+
+#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 /* def __HAIKU__ */
+
 #ifndef NO_CHMOD
 # ifdef KFLAG
             if (uO.kflag >= 0)
@@ -721,6 +747,20 @@ 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 /* def __HAIKU__ */
+
         /* dir existed already; don't look for data to extract */
         return (error & ~MPN_MASK) | MPN_INF_SKIP;
     }
@@ -1233,14 +1273,29 @@ 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 /* def __HAIKU__ */
+
         /* 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,
@@ -1261,11 +1316,18 @@ 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),
-               sizeof(unsigned));
+
+#   ifdef __HAIKU__
+        if (attribsize > sizeof(unsigned))
+            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 /* def __HAIKU__ */
+
+#  endif /* def SET_SYMLINK_ATTRIBS */
+
         slnk_entry->target = slnk_entry->buf + slnk_entry->attriblen;
         slnk_entry->fname = slnk_entry->target + ucsize + 1;
         strcpy(slnk_entry->fname, G.filename);
@@ -1452,6 +1514,13 @@ int set_symlnk_attribs(__G__ slnk_entry)
     slinkentry *slnk_entry;
 {
     if (slnk_entry->attriblen > 0) {
+
+# ifdef __HAIKU__
+      if (slnk_entry->attriblen > sizeof(unsigned)) {
+        setBeOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf);
+      }
+# endif
+
 # ifndef NO_LCHOWN
       if (slnk_entry->attriblen > sizeof(unsigned)) {
         ulg *z_uidgid_p = (zvoid *)(slnk_entry->buf + sizeof(unsigned));
@@ -2286,6 +2355,287 @@ static void qlfix(__G__ ef_ptr, ef_len)
 #endif /* def 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 total_attr_size )
+{
+    int                  retval = EOK;
+    unsigned char       *ptr;
+    const unsigned char *guard;
+    int                  fd;
+
+    ptr   = (unsigned char *)attr_buff;
+    guard = ptr + total_attr_size;
+
+    fd = open(name, O_RDONLY | O_NOTRAVERSE);
+    if (fd < 0) {
+        return errno; /* should it be -fd ? */
+    }
+
+    while (ptr < guard) {
+        ssize_t              wrote_bytes;
+        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(&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 (attr_size < 0LL) {
+            Info(slide, 0x201, ((char *)slide,
+                 "warning: skipping attribute with invalid length (%Ld)\n",
+                 attr_size));
+            break;
+        }
+
+        attr_data  = ptr;
+        ptr       += attr_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, 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)attr_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 were
+             * 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 /* def BEOS_USE_PRINTEXFIELD */
+
+# 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 /* def BEOS_ASSIGN_FILETYPE */
+
+#endif /* def __HAIKU__ */
+
+
 /* ISO/OEM (iconv) character conversion. */
 
 #ifdef ICONV_MAPPING
@@ -2452,7 +2802,7 @@ void charset_to_intern(char *string, char *from_charset)
     {
         /* 2017-11-29 Rene Freingruber, SMS.
          * Was using buflen, ignoring last byte.  Next strcpy() was
-         * strncpy() with a bad maxchar parameter (buflen). 
+         * strncpy() with a bad maxchar parameter (buflen).
          */
         memset( buf, 0, (buflen+ 1));
 
diff --git a/unzip.c b/unzip.c
index 094c72c..61e8e65 100644
--- a/unzip.c
+++ b/unzip.c
@@ -3467,7 +3467,7 @@ static void help_extended(__G)
   "  -I   [Unix, with ICONV_MAPPING] ISO code page to use.",
   "  -i   [MacOS] Ignore filenames in MacOS extra field.  Instead, use name in",
   "         standard header.",
-  "  -J   [BeOS] Junk file attributes.",
+  "  -J   [BeOS, Haiku] Junk file attributes.",
   "       [MacOS] Ignore MacOS specific info.",
   "       [MacOSX] No special AppleDouble file handling.",
   "  -Je  [MacOSX] Ignore AppleDouble extended attributes.",
diff --git a/unzpriv.h b/unzpriv.h
index 1361f34..89f3e00 100644
--- a/unzpriv.h
+++ b/unzpriv.h
@@ -395,13 +395,21 @@
 #endif
 
 /*---------------------------------------------------------------------------
-    BeOS/Haiku section:
+    BeOS section:
   ---------------------------------------------------------------------------*/
 
-#if defined( __BEOS__) || defined( __HAIKU__)
+#ifdef __BEOS__
 #  include "beos/beocfg.h"
 #endif
 
+/*---------------------------------------------------------------------------
+    Haiku section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef __HAIKU__
+#  include <sys/stat.h>
+#endif
+
 /*---------------------------------------------------------------------------
     Human68k/X680x0 section:
   ---------------------------------------------------------------------------*/
@@ -877,7 +885,7 @@ extern void izu_md_check( void);
 #  define DOS_T20_VMS
 #endif
 
-#if (defined(__ATHEOS__) || defined(__BEOS__))
+#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(__HAIKU__))
 #  define ATH_BEO
 #endif
 
-- 
2.21.0


From ad8faa63b707080301ea344f227192a404063915 Mon Sep 17 00:00:00 2001
From: Adrien Destugues <pulkomandy@pulkomandy.tk>
Date: Sun, 21 Jan 2018 14:07:25 +0100
Subject: Fix build and re-enable -DICONV_MAPPING for Haiku


diff --git a/unix/Makefile b/unix/Makefile
index 1dd4989..9e2605e 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -1656,12 +1656,12 @@ gcc: unix_make
 haiku: unix_make
 	$(MAKE) $(BINS) \
          CC="cc" CFLAGS=" -O3 -DLARGE_FILE_SUPPORT -DUNICODE_SUPPORT \
-         -DUNICODE_WCHAR -DUNICODE_SUPPORT -DUTF8_MAYBE_NATIVE \
+         -DUNICODE_WCHAR -DICONV_MAPPING -DUTF8_MAYBE_NATIVE \
          -DNO_LCHMOD -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -D_MBCS \
          -DNO_SYSDIR" \
-          CRCA_O="" AS="cc -c" LFLAGS1="-lbe" LF2="-s" \
+          CRCA_O="" AS="cc -c" LF2="-lbe -liconv -s" \
           CC_BZ="cc" CFLAGS_BZ="-O3" \
-          IZ_BZIP2="." D_USE_BZ2="" L_BZ2="" LIBBZ2=""
+          IZ_BZIP2="." D_USE_BZ2="" L_BZ2="" LIBBZ2="" LN="ln -s"
 
 # Heurikon HK68 (68010), UniPlus+ System V 5.0, Green Hills C-68000
 hk68: unix_make
diff --git a/unix/unix.c b/unix/unix.c
index ffb997b..b6e14fa 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -56,7 +56,7 @@
 
 #ifdef __HAIKU__
 # include <fs_attr.h>
-# include <ByteOrder.h>
+# include <support/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));
@@ -2451,7 +2451,7 @@ 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, attr_type, 0,
-- 
2.21.0


From fd60f91e80bcfdbe87ffa0df10f2e75c90f3389c Mon Sep 17 00:00:00 2001
From: Adrien Destugues <pulkomandy@pulkomandy.tk>
Date: Tue, 14 May 2019 23:15:32 +0200
Subject: Fix extraction of file attributes

Part of the code was missed when migrating from beos.c.

diff --git a/unix/unix.c b/unix/unix.c
index b6e14fa..12dbf44 100644
--- a/unix/unix.c
+++ b/unix/unix.c
@@ -1483,6 +1483,24 @@ void close_outfile(__G)    /* GRR: change to return PK-style warning level */
 # endif /* defined( UNIX) && defined( __APPLE__) */
     }
 
+#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 defined( NO_FCHOWN) || defined( NO_FCHMOD)
   /* We lack fchown() or fchmod(), so the file has been closed.  We may
    * have done chown() above, but not chmod().
@@ -2406,11 +2424,17 @@ static int set_file_attrs( const char *name,
     unsigned char       *ptr;
     const unsigned char *guard;
     int                  fd;
+	bool isDir;
+
+	if (name[strlen(name) - 1] == '/')
+		isDir = true;
+	else
+		isDir = false;
 
     ptr   = (unsigned char *)attr_buff;
     guard = ptr + total_attr_size;
 
-    fd = open(name, O_RDONLY | O_NOTRAVERSE);
+    fd = open(name, (isDir ? O_RDONLY : O_RDWR) | O_NOTRAVERSE);
     if (fd < 0) {
         return errno; /* should it be -fd ? */
     }
-- 
2.21.0

