zip unzip - restore xattr patches

Debora Velarde dvelarde at us.ibm.com
Mon Oct 24 22:14:18 UTC 2005


Below are patches to zip and unzip that will allow administrators to 
restore extended attributes.
I understand star already does this, but this gives administrators another 
option.


Usage:

zip
Will store extended attributes in the archive file by default unless the 
existing option:
   "-X eXclude eXtra file attributes" is used.

unzip
Will NOT restore extended attributes by default.
Will only restore extended attributes if used with the new option:
   "-E restore extended attributes".
The new -E option can only be used in conjunction with the existing:
   "-X restore UID/GID info" option.
Users can still choose to restore only the UID/GID info with the existing 
'-X' option.


Please send me any feedback.

Thanks,
debora



diff -urpN zip-2.3.orig/unix/Makefile zip-2.3/unix/Makefile
--- zip-2.3.orig/unix/Makefile  2005-10-10 13:55:45.000000000 -0500
+++ zip-2.3/unix/Makefile       2005-10-24 15:38:44.000000000 -0500
@@ -59,7 +59,7 @@ OBJN = zipnote.o  $(OBJU)
 OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
 OBJS = zipsplit.o $(OBJU)
 
-ZIP_H = zip.h ziperr.h tailor.h unix/osdep.h
+ZIP_H = zip.h ziperr.h tailor.h unix/osdep.h unix/xattr.h
 
 # suffix rules
 .SUFFIXES:
diff -urpN zip-2.3.orig/unix/unix.c zip-2.3/unix/unix.c
--- zip-2.3.orig/unix/unix.c    2005-10-10 13:55:45.000000000 -0500
+++ zip-2.3/unix/unix.c 2005-10-24 15:38:44.000000000 -0500
@@ -11,6 +11,7 @@
 #ifndef UTIL    /* the companion #endif is a bit of ways down ... */
 
 #include <time.h>
+#include "xattr.h"
 
 #if defined(MINIX) || defined(__mpexl)
 #  ifdef S_IWRITE
@@ -40,6 +41,8 @@
 #  endif
 #endif /* HAVE_DIRENT_H || _POSIX_VERSION */
 
+#include <attr/xattr.h>
+
 #define PAD 0
 #define PATH_END '/'
 
@@ -436,19 +439,80 @@ int set_extra_field(z, z_utim)
   struct stat s;
 #endif
 
+char * xa_list;
+char * xa_name;
+char * xa_value;
+ssize_t xa_list_len=0;
+ssize_t xa_name_len=0;
+ssize_t xa_value_len=0;
+int value_len=0;
+int largest_value_len=0;
+int ext_index=0;
+int xa_pairs_found=0;
+int value_index=1;
+int i=0, j=0;
+
   /* For the full sized UT local field including the UID/GID fields, we
    * have to stat the file again. */
   if (LSSTAT(z->name, &s))
     return ZE_OPEN;
 
+
 #define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))
 #define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
 #define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)
 #define EB_C_UX2_SIZE   EB_HEADSIZE
-#define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)
-#define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)
+#define EB_L_XA_SIZE   (EB_HEADSIZE + EB_XA_MINLEN)
+#define EB_C_XA_SIZE   EB_HEADSIZE
 
-  if ((z->extra = (char *)malloc(EF_L_UNIX_SIZE)) == NULL)
+  /* Get size of xattr name list */
+  /* Calling listxattr with NULL and zero returns the size */
+  xa_list_len = listxattr(z->name, NULL, 0);
+
+  if (xa_list_len > 0) {
+
+    /* now that we know the size, alloc space for list */
+    if ((xa_list = malloc(xa_list_len+1)) == NULL)
+       return ZE_MEM;
+
+    /* Get the list of xattr names */
+    xa_list_len = listxattr(z->name, xa_list, xa_list_len);
+    if (xa_list_len < 0) 
+        return ZE_XATTR;
+    xa_name = xa_list;
+    xa_name_len = xa_list_len;
+
+    /* figure out how many xattr names there are in the list */
+    xa_pairs_found=get_xattr_count(xa_list, xa_list_len);
+    if (xa_pairs_found < 1)
+        return ZE_XATTR;
+
+    /* Need to figure out the largest value_len before calling malloc */
+    /* also need the sum of all value_lens; store it in xa_value_len */
+    for (value_index=1; value_index <= xa_pairs_found; value_index++) {
+      xa_name=get_xattr_name(xa_list, xa_list_len, value_index);
+      if (xa_name == (char *)NULL)
+          return ZE_XATTR;
+      value_len=getxattr(z->name, xa_name, xa_value, 0);
+      if (value_len < 0)
+          return ZE_XATTR;
+      if (value_len > largest_value_len)
+          largest_value_len = value_len;
+      xa_value_len=xa_value_len + value_len + 1; 
+    } 
+    if ((xa_value = malloc(largest_value_len+1)) == NULL)
+       return ZE_MEM;
+  }
+
+#define EB_L_XN_SIZE   (EB_HEADSIZE + EB_XA_MINLEN + xa_name_len)
+#define EB_C_XN_SIZE   EB_HEADSIZE
+#define EB_L_XV_SIZE   (EB_HEADSIZE + EB_XA_MINLEN + xa_value_len)
+#define EB_C_XV_SIZE   EB_HEADSIZE
+#define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE + EB_L_XA_SIZE + 
EB_L_XN_SIZE + EB_L_XV_SIZE)
+#define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE + EB_C_XA_SIZE + 
EB_C_XN_SIZE + EB_C_XV_SIZE)
+
+  z->ext = EF_L_UNIX_SIZE; 
+  if ((z->extra = (char *)malloc(z->ext)) == NULL)
     return ZE_MEM;
   if ((z->cextra = (char *)malloc(EF_C_UNIX_SIZE)) == NULL)
     return ZE_MEM;
@@ -474,7 +538,71 @@ int set_extra_field(z, z_utim)
   z->extra[18] = (char)(s.st_uid >> 8);
   z->extra[19] = (char)(s.st_gid);
   z->extra[20] = (char)(s.st_gid >> 8);
-  z->ext = EF_L_UNIX_SIZE;
+  z->extra[21] = 'X';
+  z->extra[22] = 'A';
+  z->extra[23] = (char) xa_pairs_found; /* Number of xattr attributes*/
+  z->extra[24] = 0;
+  z->extra[25] = 'X';
+  z->extra[26] = 'N';
+  z->extra[27] = (char) xa_name_len;    /* length of xattr name list*/
+  z->extra[28] = 0;
+
+  ext_index=29; 
+
+  if (xa_list_len > 0) {
+
+/* Put all the xattr names in extra field */
+    for (i=1; i<=xa_pairs_found; i++) {
+      xa_name=get_xattr_name(xa_list, xa_list_len, i);
+      if (xa_name == (char *)NULL)
+          return ZE_XATTR;
+      xa_name_len=strlen(xa_name);
+      if (xa_name_len < 1)
+          return ZE_XATTR;
+      for (j=0; j<xa_name_len; j++) {
+        z->extra[ext_index+j]=(char) xa_name[j];
+      }
+      ext_index = ext_index+j;
+      z->extra[ext_index] = '\0';
+      ext_index++;
+    }
+
+    z->extra[ext_index] = 'X';
+    ext_index++;
+    z->extra[ext_index] = 'V';
+    ext_index++;
+    z->extra[ext_index]  = (char) xa_value_len;    /* length of xattr 
value list*/
+    ext_index++;
+    z->extra[ext_index] = 0;
+    ext_index++;
+
+/* Put all the xattr values in extra field */
+    for (value_index=1; value_index <= xa_pairs_found; value_index++) {
+      xa_name=get_xattr_name(xa_list, xa_list_len, value_index);
+      if (xa_name == (char *)NULL)
+          return ZE_XATTR;
+      value_len=getxattr(z->name, xa_name, xa_value, 0);
+      if (value_len < 1)
+          return ZE_XATTR;
+      xa_value=memset(xa_value, 0, largest_value_len+1);
+      if (xa_value == (char *) NULL)
+          return ZE_MEM;
+      value_len=getxattr(z->name, xa_name, xa_value, value_len);
+      if (value_len < 1)
+          return ZE_XATTR;
+
+      for (j=0; j<value_len; j++) {
+        z->extra[ext_index+j]=(char) xa_value[j];
+      }
+      ext_index = ext_index+j;
+      z->extra[ext_index] = '\0';
+      ext_index++;
+    } 
+
+  }  /* if xa_list_len > 0 */
+
+  free(xa_list);
+  free(xa_value);
 
   memcpy(z->cextra, z->extra, EB_C_UT_SIZE);
   z->cextra[EB_LEN] = (char)EB_UT_LEN(1);
diff -urpN zip-2.3.orig/unix/xattr.h zip-2.3/unix/xattr.h
--- zip-2.3.orig/unix/xattr.h   1969-12-31 18:00:00.000000000 -0600
+++ zip-2.3/unix/xattr.h        2005-10-24 15:42:43.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2005 IBM Corporation
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP 
license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+
+
+int get_xattr_count(char * xa_list, int xa_list_size)
+{
+/* xattr names have the form name1.name2 */
+/* A file can have any number of xattr name pairs */
+/* This function returns the number of name pairs found */
+/* If list passed in is NULL or list size is less than 1 
+   function returns 0 */
+
+  int i=0;
+  int p=0;
+
+  if ( (xa_list == (char *) NULL) || (xa_list_size < 1))
+    return 0;
+
+  while (i < xa_list_size) {
+    if ( xa_list[i] != '\0') {
+      i++;
+    } else {
+        i++; 
+        p++;
+    }
+  }
+  return p;
+}
+
+char * get_xattr_name(char * xa_list, int xa_list_size, int pair)
+{
+/* xattr names have the form name1.name2 */
+/* A file can have any number of xattr name pairs */
+/* This function returns a pointer to the specified name pair */
+/* If list is NULL or size or pair are less than 1, then
+   function returns NULL */
+
+  int i=0;
+  int p=1;
+  char * tmp;
+
+  tmp=NULL;
+
+  if ( (xa_list == (char *) NULL) || (xa_list_size < 1) || (pair < 1) )
+    return NULL;
+
+  while ( (i < xa_list_size) && ( p != pair) ) {
+    if ( xa_list[i] != '\0') {
+      i++;
+    } else {
+        i++; 
+        p++;
+    }
+  }
+
+  if ( (p==pair) && (i < xa_list_size) )
+   tmp=&xa_list[i];
+
+  return tmp;
+}
diff -urpN zip-2.3.orig/zip.c zip-2.3/zip.c
--- zip-2.3.orig/zip.c  2005-10-10 14:11:49.000000000 -0500
+++ zip-2.3/zip.c       2005-10-24 15:38:44.000000000 -0500
@@ -980,7 +980,7 @@ char **argv;            /* command line 
   zp_tz_is_valid = VALID_TIMEZONE(p);
 #if (defined(AMIGA) || defined(DOS))
   if (!zp_tz_is_valid)
-    extra_fields = 0;     /* disable storing "UT" time stamps and xatter 
info*/
+    extra_fields = 0;     /* disable storing "UT" time stamps */
 #endif /* AMIGA || DOS */
 #endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
 
diff -urpN zip-2.3.orig/ziperr.h zip-2.3/ziperr.h
--- zip-2.3.orig/ziperr.h       2005-10-10 13:55:45.000000000 -0500
+++ zip-2.3/ziperr.h    2005-10-24 15:38:44.000000000 -0500
@@ -31,8 +31,9 @@
 #define ZE_CREAT        15      /* couldn't open to write */
 #define ZE_PARMS        16      /* bad command line */
 #define ZE_OPEN         18      /* could not open a specified file to 
read */
+#define ZE_XATTR        19      /* xattr error occurred */
 
-#define ZE_MAXERR       18      /* the highest error number */
+#define ZE_MAXERR       19      /* the highest error number */
 
 /* Macro to determine whether to call perror() or not */
 #define PERR(e) 
(e==ZE_READ||e==ZE_WRITE||e==ZE_CREAT||e==ZE_TEMP||e==ZE_OPEN)
@@ -58,6 +59,7 @@ char *errors[ZE_MAXERR] = {
 /* 16 */  "Invalid command arguments",
 /* 17 */  "",
 /* 18 */  "File not found or no read permission"
+/* 19 */  "Extended attributes failure"
 #  ifdef AZTEC_C
           ,     /* extremely lame compiler bug workaround */
 #  endif
diff -urpN zip-2.3.orig/zip.h zip-2.3/zip.h
--- zip-2.3.orig/zip.h  2005-10-10 13:55:45.000000000 -0500
+++ zip-2.3/zip.h       2005-10-24 15:38:44.000000000 -0500
@@ -171,6 +171,9 @@ struct plist {
 #define EF_SPARK     0x4341   /* David Pilling's Acorn/SparkFS ("AC") */
 #define EF_THEOS     0x6854   /* THEOS ("Th") */
 #define EF_TANDEM    0x4154   /* Tandem NSK ("TA") */
+#define EF_XATTR     0x4158   /* XATTR ("XA") */
+#define EF_XA_NAME   0x4e58   /* XATTR NAME ("XN") */
+#define EF_XA_VALUE  0x5658   /* XATTR VALUE ("XV") */
 
 /* Definitions for extra field handling: */
 #define EF_SIZE_MAX  ((unsigned)0xFFFF) /* hard limit of total e.f. 
length */
@@ -199,6 +202,8 @@ struct plist {
 #define EB_UX2_GID        2     /* byte offset of GID in "Ux" field data 
*/
 #define EB_UX2_VALID      (1 << 8)      /* UID/GID present */
 
+#define EB_XA_MINLEN      4    /* minimal XA field contains count */
+
 /* ASCII definitions for line terminators in text files: */
 #define LF     10        /* '\n' on ASCII machines; must be 10 due to 
EBCDIC */
 #define CR     13        /* '\r' on ASCII machines; must be 13 due to 
EBCDIC */
diff -urpN zip-2.3.orig/zip.h.4gb zip-2.3/zip.h.4gb
--- zip-2.3.orig/zip.h.4gb      2005-10-10 13:55:45.000000000 -0500
+++ zip-2.3/zip.h.4gb   2005-10-24 15:38:44.000000000 -0500
@@ -171,6 +171,9 @@ struct plist {
 #define EF_SPARK     0x4341   /* David Pilling's Acorn/SparkFS ("AC") */
 #define EF_THEOS     0x6854   /* THEOS ("Th") */
 #define EF_TANDEM    0x4154   /* Tandem NSK ("TA") */
+#define EF_XATTR     0x4158   /* XATTR ("XA") */
+#define EF_XA_NAME   0x4e58   /* XATTR NAME ("XN") */
+#define EF_XA_VALUE  0x5658   /* XATTR VALUE ("XV") */
 
 /* Definitions for extra field handling: */
 #define EF_SIZE_MAX  ((unsigned)0xFFFF) /* hard limit of total e.f. 
length */
@@ -199,6 +202,8 @@ struct plist {
 #define EB_UX2_GID        2     /* byte offset of GID in "Ux" field data 
*/
 #define EB_UX2_VALID      (1 << 8)      /* UID/GID present */
 
+#define EB_XA_MINLEN      4    /* minimal XA field contains count */
+
 /* ASCII definitions for line terminators in text files: */
 #define LF     10        /* '\n' on ASCII machines; must be 10 due to 
EBCDIC */
 #define CR     13        /* '\r' on ASCII machines; must be 13 due to 
EBCDIC */
diff -urpN zip-2.3.orig/zip.h.zip zip-2.3/zip.h.zip
--- zip-2.3.orig/zip.h.zip      2005-10-10 13:55:45.000000000 -0500
+++ zip-2.3/zip.h.zip   2005-10-24 15:38:44.000000000 -0500
@@ -170,6 +170,10 @@ struct plist {
 #define EF_SPARK     0x4341   /* David Pilling's Acorn/SparkFS ("AC") */
 #define EF_THEOS     0x6854   /* THEOS ("Th") */
 #define EF_TANDEM    0x4154   /* Tandem NSK ("TA") */
+#define EF_XATTR     0x4158   /* XATTR ("XA") */
+#define EF_XA_NAME   0x4e58   /* XATTR NAME ("XN") */
+#define EF_XA_VALUE  0x5658   /* XATTR VALUE ("XV") */
+
 
 /* Definitions for extra field handling: */
 #define EF_SIZE_MAX  ((unsigned)0xFFFF) /* hard limit of total e.f. 
length */
@@ -198,6 +202,8 @@ struct plist {
 #define EB_UX2_GID        2     /* byte offset of GID in "Ux" field data 
*/
 #define EB_UX2_VALID      (1 << 8)      /* UID/GID present */
 
+#define EB_XA_MINLEN      4    /* minimal XA field contains count */
+
 /* ASCII definitions for line terminators in text files: */
 #define LF     10        /* '\n' on ASCII machines; must be 10 due to 
EBCDIC */
 #define CR     13        /* '\r' on ASCII machines; must be 13 due to 
EBCDIC */



diff -urpN unzip-5.51.orig/extract.c unzip-5.51/extract.c
--- unzip-5.51.orig/extract.c   2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/extract.c        2005-10-24 16:09:09.000000000 -0500
@@ -1908,6 +1908,9 @@ static int TestExtraField(__G__ ef, ef_l
             case EF_ASIUNIX:
             case EF_IZVMS:
             case EF_IZUNIX:
+            case EF_XATTR:
+            case EF_XA_NAME:
+            case EF_XA_VALUE:
             case EF_VMCMS:
             case EF_MVS:
             case EF_SPARK:
diff -urpN unzip-5.51.orig/fileio.c unzip-5.51/fileio.c
--- unzip-5.51.orig/fileio.c    2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/fileio.c 2005-10-24 16:09:09.000000000 -0500
@@ -1833,6 +1833,9 @@ int check_for_newer(__G__ filename)  /* 
 #ifdef USE_EF_UT_TIME
     iztimes z_utime;
 #endif
+#ifdef USE_EF_XATTR
+    izxattr z_xattr;
+#endif
 #ifdef AOS_VS
     long    dyy, dmm, ddd, dhh, dmin, dss;
 
@@ -1902,7 +1905,11 @@ int check_for_newer(__G__ filename)  /* 
         G.tz_is_valid &&
 #endif
         (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
+#ifdef USE_EF_XATTR
+                          G.lrec.last_mod_dos_datetime, &z_utime, NULL, 
&z_xattr)
+#else
                           G.lrec.last_mod_dos_datetime, &z_utime, NULL)
+#endif
          & EB_UT_FL_MTIME))
     {
         TTrace((stderr, "check_for_newer:  using Unix extra field 
mtime\n"));
diff -urpN unzip-5.51.orig/list.c unzip-5.51/list.c
--- unzip-5.51.orig/list.c      2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/list.c   2005-10-24 16:09:09.000000000 -0500
@@ -104,6 +104,9 @@ int list_files(__G)    /* return PK-type
     iztimes z_utime;
     struct tm *t;
 #endif
+#ifdef USE_EF_XATTR
+    izxattr z_xattr;
+#endif
     unsigned yr, mo, dy, hh, mm;
     ulg csiz;
     unsigned long long tot_csize=0, tot_ucsize=0;
@@ -268,7 +271,12 @@ int list_files(__G)    /* return PK-type
                 G.tz_is_valid &&
 #endif
                 (ef_scan_for_izux(G.extra_field, 
G.crec.extra_field_length, 1,
-                                  G.crec.last_mod_dos_datetime, &z_utime, 
NULL)
+                                  G.crec.last_mod_dos_datetime, &z_utime,
+#ifdef USE_EF_XATTR
+                                  NULL, &z_xattr)
+#else
+                                  NULL)
+#endif
                  & EB_UT_FL_MTIME))
             {
                 TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0, 
Mac */
@@ -509,6 +517,9 @@ int get_time_stamp(__G__ last_modtime, n
 #ifdef USE_EF_UT_TIME
     iztimes z_utime;
 #endif
+#ifdef USE_EF_XATTR
+    iztimes z_xattr;
+#endif
     min_info info;
 
 
@@ -594,7 +605,12 @@ int get_time_stamp(__G__ last_modtime, n
                 G.tz_is_valid &&
 #endif
                 (ef_scan_for_izux(G.extra_field, 
G.crec.extra_field_length, 1,
-                                  G.crec.last_mod_dos_datetime, &z_utime, 
NULL)
+                                  G.crec.last_mod_dos_datetime, &z_utime,
+#ifdef USE_EF_XATTR
+                                  NULL, &z_xattr)
+#else
+                                  NULL)
+#endif
                  & EB_UT_FL_MTIME))
             {
                 if (*last_modtime < z_utime.mtime)
diff -urpN unzip-5.51.orig/Makefile unzip-5.51/Makefile
--- unzip-5.51.orig/Makefile    2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/Makefile 2005-10-24 16:09:09.000000000 -0500
@@ -81,14 +81,14 @@ CRC32 = crc32
 OSDEP_H =
 
 # object files
-OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O
+OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O xattr$O
 OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O
 OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O
 OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O
 LOBJS = $(OBJS)
 OBJSDLL = $(OBJS:.o=.pic.o) api.pic.o
 OBJX = unzipsfx$O $(CRC32)$O crctab_$O crypt_$O extract_$O fileio_$O \
-       globals_$O inflate_$O match_$O process_$O ttyio_$O $M_$O
+       globals_$O inflate_$O match_$O process_$O ttyio_$O xattr_$O $M_$O 
 LOBJX = $(OBJX)
 OBJF = funzip$O $(CRC32)$O cryptf$O globalsf$O inflatef$O ttyiof$O
 #OBJS_OS2 = $(OBJS1:.o=.obj) $(OBJS2:.o=.obj) os2.obj
@@ -300,6 +300,7 @@ ttyio$O:    ttyio.c $(UNZIP_H) zip.h crypt.
 unreduce$O:    unreduce.c $(UNZIP_H)
 unshrink$O:    unshrink.c $(UNZIP_H)
 unzip$O:       unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h
+xattr$O:       xattr.c $(UNZIP_H)
 zipinfo$O:     zipinfo.c $(UNZIP_H)
 
 unzipsfx$O:    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h   # unzipsfx 
only
@@ -342,6 +343,11 @@ match_$O:  match.c $(UNZIP_H) # unzips
        $(CC) -c $(CF) -DSFX match_.c
        $(RM) match_.c
 
+xattr_$O:      xattr.c $(UNZIP_H)                              # unzipsfx 
only
+       -$(CP) xattr.c xattr_.c
+       $(CC) -c $(CF) -DSFX xattr_.c
+       $(RM) xattr_.c
+
 process_$O:    process.c $(UNZIP_H)                            # unzipsfx 
only
        -$(CP) process.c process_.c
        $(CC) -c $(CF) -DSFX process_.c
diff -urpN unzip-5.51.orig/process.c unzip-5.51/process.c
--- unzip-5.51.orig/process.c   2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/process.c        2005-10-24 16:09:09.000000000 -0500
@@ -1300,15 +1300,22 @@ int process_local_file_hdr(__G)    /* re
 /*******************************/
 /* Function ef_scan_for_izux() */
 /*******************************/
-
+#ifdef USE_EF_XATTR
+unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
+                          z_utim, z_uidgid, z_xattr)
+#else
 unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
                           z_utim, z_uidgid)
+#endif
     ZCONST uch *ef_buf; /* buffer containing extra field */
     unsigned ef_len;    /* total length of extra field */
     int ef_is_c;        /* flag indicating "is central extra field" */
     ulg dos_mdatetime;  /* last_mod_file_date_time in DOS format */
     iztimes *z_utim;    /* return storage: atime, mtime, ctime */
     ush *z_uidgid;      /* return storage: uid and gid */
+#ifdef USE_EF_XATTR
+    izxattr *z_xattr;   /* return storage: xattr names, values, lens, 
count */
+#endif
 {
     unsigned flags = 0;
     unsigned eb_id;
@@ -1342,6 +1349,12 @@ unsigned ef_scan_for_izux(ef_buf, ef_len
     if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == 
NULL))
         return 0;
 
+#ifdef USE_EF_XATTR
+    if (z_xattr == NULL)
+        return 0;
+    z_xattr->count=0;
+#endif
+
     TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length 
%u\n",
       ef_len));
 
@@ -1358,6 +1371,56 @@ unsigned ef_scan_for_izux(ef_buf, ef_len
         }
 
         switch (eb_id) {
+#ifdef USE_EF_XATTR
+          case EF_XATTR:
+               z_xattr->count=eb_len;
+               if (z_xattr->count > 0) {
+                   ef_buf += EB_HEADSIZE;
+                   ef_len -= EB_HEADSIZE;
+                   eb_id = makeword(EB_ID + ef_buf);
+               } else {
+                   break;
+               }
+          case EF_XA_NAME:
+               if (z_xattr->count > 0) {
+                   ef_buf += EB_HEADSIZE;
+                   ef_len -= EB_HEADSIZE;
+                   if ((z_xattr->xa_name=malloc(ef_len)) == (char *)NULL) 
{
+                       Info(slide, 0x401, ((char *)slide,
+                         LoadFarString(CannotAllocateBuffers)));
+                         return 0;
+                   }
+                   z_xattr->xa_name_len=copy_xattr(ef_buf, 
z_xattr->xa_name, z_xattr->count);
+                   if (z_xattr->xa_name_len < 0) {
+                              TTrace((stderr,
+                                "  XATTR name error; ignore e.f.!\n"));
+                              break;            /* stop scanning this 
field */
+                   }
+                   ef_buf += z_xattr->xa_name_len;
+                   ef_len -= z_xattr->xa_name_len;
+              } else {
+                  break;
+              }
+          case EF_XA_VALUE:
+               if (z_xattr->count > 0) {
+                   ef_buf += EB_HEADSIZE;
+                   ef_len -= EB_HEADSIZE;
+                   if ((z_xattr->xa_value=malloc(ef_len)) == (char 
*)NULL) {
+                       Info(slide, 0x401, ((char *)slide,
+                         LoadFarString(CannotAllocateBuffers)));
+                         return 0;
+                   }
+                   z_xattr->xa_value_len=copy_xattr(ef_buf, 
z_xattr->xa_value, z_xattr->count);
+                   if (z_xattr->xa_value_len <= 0) {
+                              TTrace((stderr,
+                                "  XATTR value error; ignore e.f.!\n"));
+                              break;            /* stop scanning this 
field */
+                   }
+                   ef_buf += z_xattr->xa_value_len;
+                   ef_len -= z_xattr->xa_value_len;
+               }
+               break;
+#endif
           case EF_TIME:
             flags &= ~0x0ff;    /* ignore previous IZUNIX or EF_TIME 
fields */
             have_new_type_eb = TRUE;
diff -urpN unzip-5.51.orig/unix/Makefile unzip-5.51/unix/Makefile
--- unzip-5.51.orig/unix/Makefile       2005-09-08 14:25:57.000000000 
-0500
+++ unzip-5.51/unix/Makefile    2005-10-24 16:09:09.000000000 -0500
@@ -81,14 +81,14 @@ CRC32 = crc32
 OSDEP_H =
 
 # object files
-OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O
+OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O xattr$O
 OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O
 OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O
 OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O
 LOBJS = $(OBJS)
 OBJSDLL = $(OBJS:.o=.pic.o) api.pic.o
 OBJX = unzipsfx$O $(CRC32)$O crctab_$O crypt_$O extract_$O fileio_$O \
-       globals_$O inflate_$O match_$O process_$O ttyio_$O $M_$O
+       globals_$O inflate_$O match_$O process_$O ttyio_$O xattr_$O $M_$O 
 LOBJX = $(OBJX)
 OBJF = funzip$O $(CRC32)$O cryptf$O globalsf$O inflatef$O ttyiof$O
 #OBJS_OS2 = $(OBJS1:.o=.obj) $(OBJS2:.o=.obj) os2.obj
@@ -300,6 +300,7 @@ ttyio$O:    ttyio.c $(UNZIP_H) zip.h crypt.
 unreduce$O:    unreduce.c $(UNZIP_H)
 unshrink$O:    unshrink.c $(UNZIP_H)
 unzip$O:       unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h
+xattr$O:       xattr.c $(UNZIP_H)
 zipinfo$O:     zipinfo.c $(UNZIP_H)
 
 unzipsfx$O:    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h   # unzipsfx 
only
@@ -342,6 +343,11 @@ match_$O:  match.c $(UNZIP_H) # unzips
        $(CC) -c $(CF) -DSFX match_.c
        $(RM) match_.c
 
+xattr_$O:      xattr.c $(UNZIP_H)                              # unzipsfx 
only
+       -$(CP) xattr.c xattr_.c
+       $(CC) -c $(CF) -DSFX xattr_.c
+       $(RM) xattr_.c
+
 process_$O:    process.c $(UNZIP_H)                            # unzipsfx 
only
        -$(CP) process.c process_.c
        $(CC) -c $(CF) -DSFX process_.c
diff -urpN unzip-5.51.orig/unix/unix.c unzip-5.51/unix/unix.c
--- unzip-5.51.orig/unix/unix.c 2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/unix/unix.c      2005-10-24 16:09:09.000000000 -0500
@@ -83,6 +83,7 @@ typedef struct uxdirattr {      /* struc
     int have_uidgid;            /* flag */
     ush uidgid[2];
     char fnbuf[1];              /* buffer stub for directory name */
+    izxattr z_xattr;            /* struct for xattr names and values */
 } uxdirattr;
 #define UxAtt(d)  ((uxdirattr *)d)    /* typecast shortcut */
 #endif /* SET_DIR_ATTRIB */
@@ -932,12 +933,13 @@ int mkdir(path, mode)
 
 
 #if (!defined(MTS) || defined(SET_DIR_ATTRIB))
-static int get_extattribs OF((__GPRO__ iztimes *pzt, ush z_uidgid[2]));
+static int get_extattribs OF((__GPRO__ iztimes *pzt, ush z_uidgid[2], 
izxattr *pzxattr));
 
-static int get_extattribs(__G__ pzt, z_uidgid)
+static int get_extattribs(__G__ pzt, z_uidgid, pzxattr)
     __GDEF
     iztimes *pzt;
     ush z_uidgid[2];
+    izxattr *pzxattr;
 {
 
/*---------------------------------------------------------------------------
     Convert from MSDOS-format local time and date to Unix-format 32-bit 
GMT
@@ -957,7 +959,13 @@ static int get_extattribs(__G__ pzt, z_u
 #else
                    pzt,
 #endif
-                   z_uidgid) : 0);
+                   z_uidgid, 
+#ifdef USE_EF_XATTR
+                   pzxattr) : 0);
+#else
+                   NULL) : 0);
+#endif
+
     if (eb_izux_flg & EB_UT_FL_MTIME) {
         TTrace((stderr, "\nget_extattribs:  Unix e.f. modif. time = 
%ld\n",
           pzt->mtime));
@@ -1000,7 +1008,14 @@ void close_outfile(__G)    /* GRR: chang
         ztimbuf t2;             /* modtime, actime */
     } zt;
     ush z_uidgid[2];
+    izxattr z_xattr; 
     int have_uidgid_flg;
+    int rc=0;
+    char *name;
+    char *value;
+    int i;
+    int value_len;
+    int largest_value_len=0;
 
     fchmod(fileno(G.outfile), 0400);
 
@@ -1090,7 +1105,7 @@ void close_outfile(__G)    /* GRR: chang
     }
 #endif
 
-    have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);
+    have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid, &z_xattr);
 
     /* if -X option was specified and we have UID/GID info, restore it */
     if (have_uidgid_flg) {
@@ -1108,6 +1123,54 @@ void close_outfile(__G)    /* GRR: chang
         }
     }
 
+#ifdef USE_EF_XATTR
+/* if -E option was specified attempt to restore extended attribute info 
*/
+    if (uO.E_flag && (!have_uidgid_flg)) { 
+        Info(slide, 0x201, ((char *)slide,
+          " (warning) unable to restore extended attributes for %s\n", 
FnFilter1(G.filename)));
+    }
+    if (uO.E_flag && have_uidgid_flg) { 
+    /* Restore extended attributes info */
+        if (z_xattr.count > 0) {
+            /* Need to figure out the largest value_len before calling 
malloc */
+            for (i=1; i<=z_xattr.count; i++) {
+                name = get_xattr_name(z_xattr.xa_name, 
z_xattr.xa_name_len, i);
+                value_len=getxattr(z_xattr.xa_name, name, value, 0); 
+                if (value_len > largest_value_len)
+                    largest_value_len = value_len;
+            }
+            if ((value = malloc(largest_value_len+1)) == (char *)NULL) {
+                Info(slide, 0x201, ((char *)slide,
+                  "warning: xattr (%s) failed: no mem\n",
+                  FnFilter1(G.filename)));
+                return; 
+            } else {
+                /* Set all xattr name and value pairs */
+                for (i=1; i<=z_xattr.count; i++) {
+                    name = get_xattr_name(z_xattr.xa_name, 
z_xattr.xa_name_len, i);
+                    if (name == (char *) NULL) {
+                        Info(slide, 0x201, ((char *)slide,
+                          " (warning) cannot restore extended attributes 
for %s\n", FnFilter1(G.filename)));
+                    }
+                    value = get_xattr_value(z_xattr.xa_value, 
z_xattr.xa_value_len, i);
+                    if (value == (char *) NULL) {
+                        Info(slide, 0x201, ((char *)slide,
+                          " (warning) cannot restore extended attributes 
for %s\n", FnFilter1(G.filename)));
+                    }
+                    rc = setxattr(G.filename, name, value, strlen(value), 
0); 
+                    if (rc != 0) {
+                        Info(slide, 0x201, ((char *)slide,
+                          " (warning) cannot restore extended attributes 
for %s\n", FnFilter1(G.filename)));
+                    }
+                }
+            }
+        } else {
+              Info(slide, 0x201, ((char *)slide,
+                " (warning) cannot restore extended attributes for %s\n", 
FnFilter1(G.filename)));
+        }
+    }
+#endif
+
     /* set the file's access and modification times */
     if (utime(G.filename, &(zt.t2))) {
 #ifdef AOS_VS
@@ -1160,7 +1223,7 @@ int defer_dir_attribs(__G__ pd)
     d_entry->perms = G.pInfo->file_attr;
 
     d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3),
-                                          d_entry->uidgid);
+                                          d_entry->uidgid, 
&(d_entry->z_xattr));
     return PK_OK;
 } /* end function defer_dir_attribs() */
 
diff -urpN unzip-5.51.orig/unix/unxcfg.h unzip-5.51/unix/unxcfg.h
--- unzip-5.51.orig/unix/unxcfg.h       2005-09-08 14:25:57.000000000 
-0500
+++ unzip-5.51/unix/unxcfg.h    2005-10-24 16:09:09.000000000 -0500
@@ -122,6 +122,8 @@
 #endif
 #define RESTORE_UIDGID
 
+#define USE_EF_XATTR
+
 /* Static variables that we have to add to Uz_Globs: */
 #define SYSTEM_SPECIFIC_GLOBALS \
     int created_dir, renamed_fullpath;\
diff -urpN unzip-5.51.orig/unzip.c unzip-5.51/unzip.c
--- unzip-5.51.orig/unzip.c     2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/unzip.c  2005-10-24 16:09:09.000000000 -0500
@@ -143,6 +143,8 @@ static ZCONST char Far InvalidOptionsMsg
   -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
 static ZCONST char Far IgnoreOOptionMsg[] =
   "caution:  both -n and -o specified; ignoring -o\n";
+static ZCONST char Far InvalidEModifierMsg[] = "error:\
+  -E modifier cannot be used without -X modifier\n";
 
 /* usage() strings */
 #ifndef SFX
@@ -238,12 +240,30 @@ M  pipe through \"more\" pager 
 #else /* !VMS */
 #ifdef BEO_UNX
    static ZCONST char Far local2[] = " -X  restore UID/GID info";
+#ifdef USE_EF_XATTR
+#ifdef MORE
+   static ZCONST char Far local3[] = "  \
+-E  restore extended attributes            -M  pipe through \"more\" 
pager\n";
+#else /* !MORE */
+   static ZCONST char Far local3[] = " \
+-E  restore extended attributes\n";
+#endif
+#else /* !USE_EF_XATTR */
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+                                             -M  pipe through \"more\" 
pager\n";
+#else /* !MORE */
+   static ZCONST char Far local3[] = "\n";
+#endif
+#endif
+/* 
 #ifdef MORE
    static ZCONST char Far local3[] = "\
                                              -M  pipe through \"more\" 
pager\n";
 #else
    static ZCONST char Far local3[] = "\n";
 #endif
+*/
 #else /* !BEO_UNX */
 #ifdef TANDEM
    static ZCONST char Far local2[] = "\
@@ -1222,6 +1242,15 @@ int uz_opts(__G__ pargc, pargv)
                     }
                     break;
 #endif /* MACOS */
+#ifdef UNIX
+                case ('E'): /* -E [UNIX] restore extended attributes */
+                    if( negative ) {
+                        uO.E_flag = FALSE, negative = 0;
+                    } else {
+                        uO.E_flag = TRUE;
+                    }
+                    break;
+#endif /* MACOS */
                 case ('f'):    /* "freshen" (extract only newer files) */
                     if (negative)
                         uO.fflag = uO.uflag = FALSE, negative = 0;
@@ -1521,6 +1550,13 @@ opts_done:  /* yes, very ugly...but only
         Info(slide, 0x401, ((char *)slide, 
LoadFarString(InvalidOptionsMsg)));
         error = TRUE;
     }
+#ifdef UNIX
+    if (uO.E_flag && (!uO.X_flag))
+    {
+        Info(slide, 0x401, ((char *)slide, 
LoadFarString(InvalidEModifierMsg)));
+        error = TRUE;
+    }
+#endif
     if (uO.aflag > 2)
         uO.aflag = 2;
 #ifdef VMS
diff -urpN unzip-5.51.orig/unzip.h unzip-5.51/unzip.h
--- unzip-5.51.orig/unzip.h     2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/unzip.h  2005-10-24 16:09:09.000000000 -0500
@@ -438,6 +438,9 @@ typedef struct _UzpOpts {
 #ifdef MACOS
     int E_flag;         /* -E: [MacOS] show Mac extra field during 
restoring */
 #endif
+#ifdef UNIX
+    int E_flag;         /* -E: [Unix] restore extended attributes */
+#endif
     int fflag;          /* -f: "freshen" (extract only newer files) */
 #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
     int acorn_nfs_ext;  /* -F: RISC OS types & NFS filetype extensions */
@@ -571,6 +574,7 @@ typedef struct central_directory_file_he
 #define PK_FIND           11   /* no files found */
 #define PK_DISK           50   /* disk full */
 #define PK_EOF            51   /* unexpected EOF */
+#define PK_XATTR          52   /* extended attributes error */
 
 #define IZ_CTRLC          80   /* user hit ^C to terminate */
 #define IZ_UNSUP          81   /* no files found: all unsup. 
compr/encrypt. */
diff -urpN unzip-5.51.orig/unzpriv.h unzip-5.51/unzpriv.h
--- unzip-5.51.orig/unzpriv.h   2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/unzpriv.h        2005-10-24 16:09:09.000000000 -0500
@@ -1433,6 +1433,9 @@
 #define EF_THEOSO    0x4854    /* old Theos port */
 #define EF_MD5       0x4b46    /* Fred Kantor's MD5 ("FK") */
 #define EF_ASIUNIX   0x756e    /* ASi's Unix ("nu") */
+#define EF_XATTR     0x4158    /* XATTR ("XA") */
+#define EF_XA_NAME   0x4e58    /* XATTR NAME ("XN") */
+#define EF_XA_VALUE  0x5658    /* XATTR VALUE ("XV") */
 
 #define EB_HEADSIZE       4    /* length of extra field block header */
 #define EB_ID             0    /* offset of block ID in header */
@@ -1459,6 +1462,8 @@
 #define EB_UT_FL_ATIME    (1 << 1)      /* atime present */
 #define EB_UT_FL_CTIME    (1 << 2)      /* ctime present */
 
+#define EB_XA_MINLEN      4    /* minimal XA size */
+
 #define EB_FLGS_OFFS      4    /* offset of flags area in generic 
compressed
                                   extra field blocks (BEOS, MAC, and 
others) */
 #define EB_OS2_HLEN       4    /* size of OS2/ACL compressed data header 
*/
@@ -1576,6 +1581,14 @@ typedef struct iztimes {
    time_t ctime;             /* used for creation time; NOT same as 
st_ctime */
 } iztimes;
 
+typedef struct izxattr {
+   char *xa_name;            /* xattr names list */
+   char *xa_value;           /* xattr values list */ 
+   ssize_t xa_name_len;      /* size of xa_names list */
+   ssize_t xa_value_len;     /* size of xa_value list */
+   int count;                /* number of xattr name and value pairs */ 
+} izxattr;
+
 #ifdef SET_DIR_ATTRIB
    typedef struct direntry {    /* head of system-specific struct holding 
*/
        struct direntry *next;   /*  defered directory attributes info */
@@ -1812,7 +1825,12 @@ int      get_cdir_ent            OF((__G
 int      process_local_file_hdr  OF((__GPRO));
 unsigned ef_scan_for_izux        OF((ZCONST uch *ef_buf, unsigned ef_len,
                                      int ef_is_c, ulg dos_mdatetime,
+#ifdef USE_EF_XATTR
+                                     iztimes *z_utim, ush *z_uidgid,
+                                     izxattr *z_xattr));
+#else
                                      iztimes *z_utim, ush *z_uidgid));
+#endif
 #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
    zvoid *getRISCOSexfield       OF((ZCONST uch *ef_buf, unsigned 
ef_len));
 #endif
@@ -1850,6 +1868,15 @@ void     fnprint                 OF((__G
 #endif /* !SFX */
 
 
/*---------------------------------------------------------------------------
+    Functions in xattr.c:
+ 
---------------------------------------------------------------------------*/
+
+int      get_xattr_count(char *xa_list, int xa_list_size);
+char *   get_xattr_name(char *xa_list, int xa_list_size, int pair);
+char *   get_xattr_value(char *xa_list, int xa_list_size, int pair);
+int      copy_xattr(char *xa_list, char *new_list, int pair);
+
+/*---------------------------------------------------------------------------
     Functions in fileio.c:
 
---------------------------------------------------------------------------*/
 
diff -urpN unzip-5.51.orig/xattr.c unzip-5.51/xattr.c
--- unzip-5.51.orig/xattr.c     1969-12-31 18:00:00.000000000 -0600
+++ unzip-5.51/xattr.c  2005-10-24 16:12:01.000000000 -0500
@@ -0,0 +1,127 @@
+/*
+*/
+/* xattr.c
+ *
+ * Author:  Debora Velarde <dvelarde at us.ibm.com>
+ * Created: Sept 14, 2005
+ */
+
+
+#define __XATTR_C   /* identifies this source module */
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+int get_xattr_count(char *xa_list, int xa_list_size)
+{
+/* xattr names have the form name1.name2 */
+/* A file can have any number of xattr name pairs */
+/* This function returns the number of name pairs found */
+/* If list passed in is NULL or list size is less than 1
+   function retunrs 0 */
+
+    int i=0;
+    int p=0;
+
+    if ( (xa_list == (char *) NULL) || (xa_list_size < 1))
+        return 0;
+
+
+    while (i < xa_list_size) {
+        if ( xa_list[i] != '\0') {
+            i++;
+        } else {
+              i++; //move index to one past \0
+              p++;
+        }
+    }
+
+  return p;
+}
+
+char * get_xattr_name(char *xa_list, int xa_list_size, int pair)
+{
+/* xattr names have the form name1.name2 */
+/* A file can have any number of xattr name pairs */
+/* This function returns a pointer to the specified name pair */
+/* If list is NULL or size or pair are less than 1, then
+   function returns NULL */
+
+    int i=0;
+    int p=1;
+    char *tmp;
+
+    tmp=NULL;
+
+    if ( (xa_list == (char *) NULL) || (xa_list_size < 1) || (pair < 1) )
+        return NULL;
+
+    while ( (i < xa_list_size) && ( p != pair) ) {
+        if ( xa_list[i] != '\0') {
+            i++;
+        } else {
+              i++; //move index to one past \0
+              p++;
+        }
+    }
+
+    if ( (p==pair) && (i < xa_list_size) )
+        tmp=&xa_list[i];
+
+    return tmp;
+}
+
+char * get_xattr_value(char *xa_list, int xa_list_size, int pair)
+{
+/* A file can have any number of xattr name and value pairs */
+/* This function returns a pointer to the specified value pair */
+/* If list is NULL or size or pair are less than 1, then 
+   function returns NULL */
+
+    int i=0;
+    int p=1;
+    char *tmp;
+
+    tmp=NULL;
+
+    if ( (xa_list == (char *) NULL) || (xa_list_size < 1) || (pair < 1) )
+        return NULL;
+
+    while ( (i < xa_list_size) && ( p != pair) ) {
+        if ( xa_list[i] != '\0') {
+            i++;
+        } else {
+              i++; //move index to one past \0
+              p++;
+        }
+    }
+
+  if ( (p==pair) && (i < xa_list_size) )
+     tmp=&xa_list[i];
+
+  return tmp;
+}
+
+int copy_xattr(char *xa_list, char *new_list, int pair)
+{
+/* A file can have any number of xattr name and value pairs */
+/* This function copies all the names or value from xa_list to new_list 
*/
+/* This function returns the size of new_list */
+/* If either list being copied or new list is NULL, then retunrs -1 */
+/* If pair is less than 1 returns -1 */
+
+    int i=0;
+    int p=0;
+
+    if ( (xa_list == (char *) NULL) || (new_list == (char *) NULL) || 
(pair < 1) )
+        return -1;
+
+    while ( p < pair ) {
+        new_list[i] = xa_list[i];
+        if ( xa_list[i] == '\0') {
+            p++;
+        } 
+        i++;
+    }
+
+  return i;
+}
diff -urpN unzip-5.51.orig/zipinfo.c unzip-5.51/zipinfo.c
--- unzip-5.51.orig/zipinfo.c   2005-09-08 14:25:57.000000000 -0500
+++ unzip-5.51/zipinfo.c        2005-10-24 16:09:09.000000000 -0500
@@ -330,6 +330,8 @@ static ZCONST char Far efMD5[] = "Fred K
 static ZCONST char Far efASiUnix[] = "ASi Unix";
 static ZCONST char Far efTandem[] = "Tandem NSK";
 static ZCONST char Far efTheos[] = "Theos";
+static ZCONST char Far efXAname[] = "xattr name";
+static ZCONST char Far efXAvalue[] = "xattr value";
 static ZCONST char Far efUnknown[] = "unknown";
 
 static ZCONST char Far OS2EAs[] = ".\n\
@@ -935,6 +937,9 @@ static int zi_long(__G__ pEndprev)   /* 
 #ifdef USE_EF_UT_TIME
     iztimes z_utime;
 #endif
+#ifdef USE_EF_XATTR 
+    izxattr z_xattr;
+#endif
     int  error, error_in_archive=PK_COOL;
     unsigned  hostnum, hostver, extnum, extver, methnum, xattr;
     char workspace[12], attribs[22];
@@ -1076,7 +1081,12 @@ static int zi_long(__G__ pEndprev)   /* 
         G.tz_is_valid &&
 #endif
         (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
-                          G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                          G.crec.last_mod_dos_datetime, &z_utime,
+#ifdef USE_EF_XATTR
+                          NULL, &z_xattr)
+#else
+                          NULL)
+#endif
          & EB_UT_FL_MTIME))
     {
         TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0 or 
Macintosh */
@@ -1422,6 +1432,12 @@ static int zi_long(__G__ pEndprev)   /* 
 #endif
                     ef_fieldname = efTheos;
                     break;
+                case EF_XA_NAME:
+                    ef_fieldname = efXAname;
+                    break;
+                case EF_XA_VALUE:
+                    ef_fieldname = efXAvalue;
+                    break;
                 default:
                     ef_fieldname = efUnknown;
                     break;
@@ -1755,6 +1771,9 @@ static int zi_short(__G)   /* return PK-
     iztimes     z_utime;
     time_t      *z_modtim;
 #endif
+#ifdef USE_EF_XATTR
+    izxattr     z_xattr;
+#endif
     int         k, error, error_in_archive=PK_COOL;
     unsigned    hostnum, hostver, methnum, xattr;
     char        *p, workspace[12], attribs[16];
@@ -2053,7 +2072,12 @@ static int zi_short(__G)   /* return PK-
                G.tz_is_valid &&
 #endif
                (ef_scan_for_izux(G.extra_field, 
G.crec.extra_field_length, 1,
-                                 G.crec.last_mod_dos_datetime, &z_utime, 
NULL)
+                                 G.crec.last_mod_dos_datetime, &z_utime,
+#ifdef USE_EF_XATTR
+                                 NULL, &z_xattr)
+#else
+                                 NULL)
+#endif
                 & EB_UT_FL_MTIME)
               ? &z_utime.mtime : NULL;
     TIMET_TO_NATIVE(z_utime.mtime)     /* NOP unless MSC 7.0 or Macintosh 
*/




More information about the selinux mailing list