From a48f57e1c902b2e6ef2d946cfebf2da0637f9a88 Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Sat, 28 Feb 2015 18:07:06 +0000 Subject: Haiku patch diff --git a/tailor.h b/tailor.h index 272f979..b79221c 100644 --- a/tailor.h +++ b/tailor.h @@ -68,6 +68,12 @@ #include "macos/osdep.h" #endif +#ifdef __HAIKU__ +#undef local +#include +#define local static +#endif + #ifdef NLM #include "novell/osdep.h" #endif diff --git a/unix/Makefile b/unix/Makefile index abd0c44..09b5a4f 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -38,8 +38,8 @@ BINFLAGS = 755 MANFLAGS = 644 # target directories - where to install executables and man pages to -prefix = /usr/local -BINDIR = $(prefix)/bin +prefix = $PREFIX +BINDIR ?= $(prefix)/bin MANEXT=1 MANDIR = $(prefix)/man/man$(MANEXT) ZIPMANUAL = zip.txt diff --git a/unix/osdep.h b/unix/osdep.h index 10f8ee9..b766e52 100644 --- a/unix/osdep.h +++ b/unix/osdep.h @@ -78,3 +78,9 @@ #if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME) # define USE_EF_UT_TIME #endif + +#ifdef __HAIKU__ + #ifndef ZP_NEED_MEMCOMPR + # define ZP_NEED_MEMCOMPR + #endif +#endif diff --git a/unix/unix.c b/unix/unix.c index f4d655d..970af5c 100644 --- a/unix/unix.c +++ b/unix/unix.c @@ -42,6 +42,13 @@ # endif #endif /* HAVE_DIRENT_H || _POSIX_VERSION */ +#ifdef __HAIKU__ +#include +#include +#include +#include +#endif + #define PAD 0 #define PATH_END '/' @@ -434,6 +441,355 @@ ulg filetime(f, a, n, t) #ifndef QLZIP /* QLZIP Unix2QDOS cross-Zip supplies an extended variant */ +#ifdef __HAIKU__ + +/* Set a file's MIME type. */ +#define BE_FILE_TYPE_NAME "BEOS:TYPE" + +/* ---------------------------------------------------------------------- */ +/* Set a file's MIME type. */ +void setfiletype( const char *file, const char *type ) +{ + int fd; + attr_info fa; + ssize_t wrote_bytes; + + fd = open( file, O_RDWR ); + if( fd < 0 ) { + zipwarn( "can't open zipfile to write file type", "" ); + return; + } + + fa.type = B_MIME_STRING_TYPE; + fa.size = (off_t)(strlen( type ) + 1); + + wrote_bytes = fs_write_attr( fd, BE_FILE_TYPE_NAME, fa.type, 0, + type, fa.size ); + if( wrote_bytes != (ssize_t)fa.size ) { + zipwarn( "couldn't write complete file type", "" ); + } + + close( fd ); +} + +/* ---------------------------------------------------------------------- + +Return a malloc()'d buffer containing all of the attributes and their names +for the file specified in name. You have to free() this yourself. The length +of the buffer is also returned. + +If get_attr_dir() fails, the buffer will be NULL, total_size will be 0, +and an error will be returned: + + ZE_OK - no errors occurred + ZE_LOGIC - attr_buff was pointing at a buffer + ZE_MEM - insufficient memory for attribute buffer + +Other errors are possible (whatever is returned by the fs_attr.h functions). + +PROBLEMS: + +- pointers are 32-bits; attributes are limited to off_t in size so it's + possible to overflow... in practice, this isn't too likely... your + machine will thrash like hell before that happens + +*/ + +#define INITIAL_BUFF_SIZE 65536 + +int get_attr_dir( const char *name, char **attr_buff, off_t *total_size ) +{ + int retval = ZE_OK; + int fd; + DIR *fa_dir; + struct dirent *fa_ent; + off_t attrs_size; + off_t this_size; + char *ptr; + struct attr_info fa_info; + struct attr_info big_fa_info; + + retval = ZE_OK; + attrs_size = 0; /* gcc still says this is used uninitialized... */ + *total_size = 0; + + /* ----------------------------------------------------------------- */ + /* Sanity-check. */ + if( *attr_buff != NULL ) { + return ZE_LOGIC; + } + + /* ----------------------------------------------------------------- */ + /* Can we open the file/directory? */ + /* */ + /* linkput is a zip global; it's set to 1 if we're storing symbolic */ + /* links as symbolic links (instead of storing the thing the link */ + /* points to)... if we're storing the symbolic link as a link, we'll */ + /* want the link's file attributes, otherwise we want the target's. */ + if( linkput ) { + fd = open( name, O_RDONLY | O_NOTRAVERSE ); + } else { + fd = open( name, O_RDONLY ); + } + if( fd < 0 ) { + return errno; + } + + /* ----------------------------------------------------------------- */ + /* Allocate an initial buffer; 64k should usually be enough. */ + *attr_buff = (char *)malloc( INITIAL_BUFF_SIZE ); + ptr = *attr_buff; + if( ptr == NULL ) { + close( fd ); + + return ZE_MEM; + } + + /* ----------------------------------------------------------------- */ + /* Open the attributes directory for this file. */ + fa_dir = fs_fopen_attr_dir( fd ); + if( fa_dir == NULL ) { + close( fd ); + + free( ptr ); + *attr_buff = NULL; + + return retval; + } + + /* ----------------------------------------------------------------- */ + /* Read all the attributes; the buffer could grow > 64K if there are */ + /* many and/or they are large. */ + fa_ent = fs_read_attr_dir( fa_dir ); + while( fa_ent != NULL ) { + retval = fs_stat_attr( fd, fa_ent->d_name, &fa_info ); + /* TODO: check retval != ZE_OK */ + + this_size = strlen( fa_ent->d_name ) + 1; + this_size += sizeof( struct attr_info ); + this_size += fa_info.size; + + attrs_size += this_size; + + if( attrs_size > INITIAL_BUFF_SIZE ) { + unsigned long offset = ptr - *attr_buff; + + *attr_buff = (char *)realloc( *attr_buff, attrs_size ); + if( *attr_buff == NULL ) { + retval = fs_close_attr_dir( fa_dir ); + /* TODO: check retval != ZE_OK */ + close( fd ); + + return ZE_MEM; + } + + ptr = *attr_buff + offset; + } + + /* Now copy the data for this attribute into the buffer. */ + strcpy( ptr, fa_ent->d_name ); + ptr += strlen( fa_ent->d_name ); + *ptr++ = '\0'; + + /* We need to put a big-endian version of the fa_info data into */ + /* the archive. */ + big_fa_info.type = B_HOST_TO_BENDIAN_INT32( fa_info.type ); + big_fa_info.size = B_HOST_TO_BENDIAN_INT64( fa_info.size ); + memcpy( ptr, &big_fa_info, sizeof( struct attr_info ) ); + ptr += sizeof( struct attr_info ); + + if( fa_info.size > 0 ) { + ssize_t read_bytes; + + read_bytes = fs_read_attr( fd, fa_ent->d_name, fa_info.type, 0, + ptr, fa_info.size ); + if( read_bytes != fa_info.size ) { + /* print a warning about mismatched sizes */ + char buff[80]; + + sprintf( buff, "read %ld, expected %ld", + (ssize_t)read_bytes, (ssize_t)fa_info.size ); + zipwarn( "attribute size mismatch: ", buff ); + } + + /* Wave my magic wand... this swaps all the Be types to big- */ + /* endian automagically. */ + (void)swap_data( fa_info.type, ptr, fa_info.size, + B_SWAP_HOST_TO_BENDIAN ); + + ptr += fa_info.size; + } + + fa_ent = fs_read_attr_dir( fa_dir ); + } + + /* ----------------------------------------------------------------- */ + /* Close the attribute directory. */ + retval = fs_close_attr_dir( fa_dir ); + /* TODO: check retval != ZE_OK */ + + /* ----------------------------------------------------------------- */ + /* If the buffer is too big, shrink it. */ + if( attrs_size < INITIAL_BUFF_SIZE ) { + *attr_buff = (char *)realloc( *attr_buff, attrs_size ); + if( *attr_buff == NULL ) { + /* This really shouldn't happen... */ + close( fd ); + + return ZE_MEM; + } + } + + *total_size = attrs_size; + + close( fd ); + + return ZE_OK; +} + +/* ---------------------------------------------------------------------- */ +/* Add a 'Be' extra field to the zlist data pointed to by z. */ + +#define EB_L_BE_LEN 5 /* min size is an unsigned long and flag */ +#define EB_C_BE_LEN 5 /* Length of data in local EF and flag. */ + +#define EB_BE_FL_NATURAL 0x01 /* data is 'natural' (not compressed) */ + +#define EB_L_BE_SIZE (EB_HEADSIZE + EB_L_BE_LEN) /* + attr size */ +#define EB_C_BE_SIZE (EB_HEADSIZE + EB_C_BE_LEN) + +/* maximum memcompress overhead is the sum of the compression header length */ +/* (6 = ush compression type, ulg CRC) and the worstcase deflate overhead */ +/* when uncompressible data are kept in 2 "stored" blocks (5 per block = */ +/* byte blocktype + 2 * ush blocklength) */ +#define MEMCOMPRESS_OVERHEAD (EB_MEMCMPR_HSIZ + EB_DEFLAT_EXTRA) + +local int add_Be_ef( struct zlist far *z ) +{ + char *l_ef = NULL; + char *c_ef = NULL; + char *attrbuff = NULL; + off_t attrsize = 0; + char *compbuff = NULL; + ush compsize = 0; + uch flags = 0; + + /* Check to make sure we've got enough room in the extra fields. */ + if( z->ext + EB_L_BE_SIZE > USHRT_MAX || + z->cext + EB_C_BE_SIZE > USHRT_MAX ) { + return ZE_MEM; + } + + /* Attempt to load up a buffer full of the file's attributes. */ + { + int retval; + + retval = get_attr_dir( z->name, &attrbuff, &attrsize ); + if( retval != ZE_OK ) { + return ZE_OPEN; + } + if( attrsize == 0 ) { + return ZE_OK; + } + if( attrbuff == NULL ) { + return ZE_LOGIC; + } + + /* Check for way too much data. */ + if( attrsize > (off_t)ULONG_MAX ) { + zipwarn( "uncompressed attributes truncated", "" ); + attrsize = (off_t)(ULONG_MAX - MEMCOMPRESS_OVERHEAD); + } + } + + if( verbose ) { + printf( "\t[in=%lu]", (unsigned long)attrsize ); + } + + /* Try compressing the data */ + compbuff = (char *)malloc( (size_t)attrsize + MEMCOMPRESS_OVERHEAD ); + if( compbuff == NULL ) { + return ZE_MEM; + } + compsize = memcompress( compbuff, + (size_t)attrsize + MEMCOMPRESS_OVERHEAD, + attrbuff, + (size_t)attrsize ); + if( verbose ) { + printf( " [out=%u]", compsize ); + } + + /* Attempt to optimise very small attributes. */ + if( compsize > attrsize ) { + free( compbuff ); + compsize = (ush)attrsize; + compbuff = attrbuff; + + flags = EB_BE_FL_NATURAL; + } + + /* Check to see if we really have enough room in the EF for the data. */ + if( ( z->ext + compsize + EB_L_BE_LEN ) > USHRT_MAX ) { + compsize = USHRT_MAX - EB_L_BE_LEN - z->ext; + } + + /* Allocate memory for the local and central extra fields. */ + if( z->extra && z->ext != 0 ) { + l_ef = (char *)realloc( z->extra, z->ext + EB_L_BE_SIZE + compsize ); + } else { + l_ef = (char *)malloc( EB_L_BE_SIZE + compsize ); + z->ext = 0; + } + if( l_ef == NULL ) { + return ZE_MEM; + } + z->extra = l_ef; + l_ef += z->ext; + + if( z->cextra && z->cext != 0 ) { + c_ef = (char *)realloc( z->cextra, z->cext + EB_C_BE_SIZE ); + } else { + c_ef = (char *)malloc( EB_C_BE_SIZE ); + z->cext = 0; + } + if( c_ef == NULL ) { + return ZE_MEM; + } + z->cextra = c_ef; + c_ef += z->cext; + + /* Now add the local version of the field. */ + *l_ef++ = 'B'; + *l_ef++ = 'e'; + *l_ef++ = (char)(compsize + EB_L_BE_LEN); + *l_ef++ = (char)((compsize + EB_L_BE_LEN) >> 8); + *l_ef++ = (char)((unsigned long)attrsize); + *l_ef++ = (char)((unsigned long)attrsize >> 8); + *l_ef++ = (char)((unsigned long)attrsize >> 16); + *l_ef++ = (char)((unsigned long)attrsize >> 24); + *l_ef++ = flags; + memcpy( l_ef, compbuff, (size_t)compsize ); + + z->ext += EB_L_BE_SIZE + compsize; + + /* And the central version. */ + *c_ef++ = 'B'; + *c_ef++ = 'e'; + *c_ef++ = (char)(EB_C_BE_LEN); + *c_ef++ = (char)(EB_C_BE_LEN >> 8); + *c_ef++ = (char)compsize; + *c_ef++ = (char)(compsize >> 8); + *c_ef++ = (char)(compsize >> 16); + *c_ef++ = (char)(compsize >> 24); + *c_ef++ = flags; + + z->cext += EB_C_BE_SIZE; + + return ZE_OK; +} + +#endif + int set_new_unix_extra_field(z, s) struct zlist far *z; @@ -568,6 +924,7 @@ int set_extra_field(z, z_utim) /* store full data in local header but just modification time stamp info in central header */ { + int retval; z_stat s; char *name; int len = strlen(z->name); @@ -678,8 +1035,14 @@ int set_extra_field(z, z_utim) #endif /* never */ /* new unix extra field */ - set_new_unix_extra_field(z, &s); - + retval = set_new_unix_extra_field(z, &s); + if (retval != ZE_OK) + return retval; + + retval = add_Be_ef(z); + if (retval != ZE_OK) + return retval; + return ZE_OK; } diff --git a/zip.c b/zip.c index 439821f..6682e41 100644 --- a/zip.c +++ b/zip.c @@ -1845,7 +1845,7 @@ int rename_split(temp_name, out_path) int set_filetype(out_path) char *out_path; { -#ifdef __BEOS__ +#if defined(__BEOS__) || defined(__HAIKU__) /* Set the filetype of the zipfile to "application/zip" */ setfiletype( out_path, "application/zip" ); #endif -- 1.8.3.4 From d3e651b9d30d440eb46d63b8ddc4a3d1fc4ca3ad Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Mon, 2 Mar 2015 19:27:01 +0000 Subject: Haiku x86_64 fixes diff --git a/unix/unix.c b/unix/unix.c index 970af5c..6a0cbe3 100644 --- a/unix/unix.c +++ b/unix/unix.c @@ -562,11 +562,14 @@ int get_attr_dir( const char *name, char **attr_buff, off_t *total_size ) /* many and/or they are large. */ fa_ent = fs_read_attr_dir( fa_dir ); while( fa_ent != NULL ) { + uint32 attr_type; + uint64 attr_size; + retval = fs_stat_attr( fd, fa_ent->d_name, &fa_info ); /* TODO: check retval != ZE_OK */ this_size = strlen( fa_ent->d_name ) + 1; - this_size += sizeof( struct attr_info ); + this_size += sizeof(uint32) + sizeof(uint64); this_size += fa_info.size; attrs_size += this_size; @@ -591,13 +594,13 @@ int get_attr_dir( const char *name, char **attr_buff, off_t *total_size ) ptr += strlen( fa_ent->d_name ); *ptr++ = '\0'; - /* We need to put a big-endian version of the fa_info data into */ - /* the archive. */ - big_fa_info.type = B_HOST_TO_BENDIAN_INT32( fa_info.type ); - big_fa_info.size = B_HOST_TO_BENDIAN_INT64( fa_info.size ); - memcpy( ptr, &big_fa_info, sizeof( struct attr_info ) ); - ptr += sizeof( struct attr_info ); - + /* the attr_info is stored in BigEndian because of PowerPC */ + attr_type = B_HOST_TO_BENDIAN_INT32( fa_info.type ); + attr_size = B_HOST_TO_BENDIAN_INT64( fa_info.size ); + + memcpy( ptr, &attr_type, sizeof(uint32)); ptr += sizeof(uint32); + memcpy( ptr, &attr_size, sizeof(uint64)); ptr += sizeof(uint64); + if( fa_info.size > 0 ) { ssize_t read_bytes; @@ -696,9 +699,9 @@ local int add_Be_ef( struct zlist far *z ) } /* Check for way too much data. */ - if( attrsize > (off_t)ULONG_MAX ) { + if( attrsize > OFF_MAX ) { zipwarn( "uncompressed attributes truncated", "" ); - attrsize = (off_t)(ULONG_MAX - MEMCOMPRESS_OVERHEAD); + attrsize = OFF_MAX - MEMCOMPRESS_OVERHEAD; } } -- 1.8.3.4 From 6b6c66f091b513c313e68f35c16ad79891206521 Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Sun, 22 Mar 2015 14:08:10 +0000 Subject: Haiku: warn if attrs total length exceeds extra field size diff --git a/unix/unix.c b/unix/unix.c index 6a0cbe3..b6d06d0 100644 --- a/unix/unix.c +++ b/unix/unix.c @@ -674,7 +674,7 @@ local int add_Be_ef( struct zlist far *z ) char *attrbuff = NULL; off_t attrsize = 0; char *compbuff = NULL; - ush compsize = 0; + ulg compsize = 0; uch flags = 0; /* Check to make sure we've got enough room in the extra fields. */ @@ -732,8 +732,10 @@ local int add_Be_ef( struct zlist far *z ) } /* Check to see if we really have enough room in the EF for the data. */ - if( ( z->ext + compsize + EB_L_BE_LEN ) > USHRT_MAX ) { - compsize = USHRT_MAX - EB_L_BE_LEN - z->ext; + if( ( z->ext + compsize + EB_L_BE_SIZE ) > USHRT_MAX ) { + zipwarn("not enough space in extra field for attributes\n", ""); + free( compbuff ); + return ZE_MEM; } /* Allocate memory for the local and central extra fields. */ -- 1.8.3.4