Move Source From Main Repo

Based on xar-420
This commit is contained in:
Thomas A 2023-02-26 15:50:37 -08:00
commit 2e9eaedf80
107 changed files with 34227 additions and 0 deletions

55
CMakeLists.txt Normal file
View File

@ -0,0 +1,55 @@
project(libxar)
cmake_minimum_required(VERSION 3.10)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -D__DARWIN_UNIX03 -fPIC -w")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostdlib")
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/xar/include
${CMAKE_CURRENT_SOURCE_DIR}/xar/lib
)
set(xar_SRCS
xar/lib/archive.c
xar/lib/arcmod.c
xar/lib/b64.c
xar/lib/bzxar.c
xar/lib/darwinattr.c
xar/lib/data.c
xar/lib/ea.c
xar/lib/err.c
xar/lib/ext2.c
xar/lib/fbsdattr.c
xar/lib/filetree.c
xar/lib/hash.c
xar/lib/io.c
xar/lib/linuxattr.c
xar/lib/lzmaxar.c
xar/lib/script.c
xar/lib/signature.c
xar/lib/stat.c
xar/lib/subdoc.c
xar/lib/util.c
xar/lib/zxar.c
)
set(DYLIB_INSTALL_NAME "/usr/lib/libxar.1.dylib")
set(DYLIB_COMPAT_VERSION "1.0.0")
set(DYLIB_CURRENT_VERSION "1.0.0")
add_darling_library(xar SHARED ${xar_SRCS})
set_target_properties(xar PROPERTIES OUTPUT_NAME "xar.1")
target_link_libraries(xar system z bz2 xml2)
make_fat(xar)
add_darling_executable(xarexe xar/src/xar.c)
set_target_properties(xarexe PROPERTIES OUTPUT_NAME "xar")
target_link_libraries(xarexe system xar)
install(TARGETS xar DESTINATION libexec/darling/usr/lib)
install(TARGETS xarexe DESTINATION libexec/darling/usr/bin)
install(FILES xar/src/xar.1 DESTINATION libexec/darling/usr/share/man/man1)
InstallSymlink("libxar.1.dylib" "${CMAKE_INSTALL_PREFIX}/libexec/darling/usr/lib/libxar.dylib")

11
README Normal file
View File

@ -0,0 +1,11 @@
#########################################################################################
# Project Created by Christopher Ryan (ryanc@apple.com) #
# Sources based on tot as of 7/12/06 #
# cvs -d :pserver:anonymous@anoncvs.opendarwin.org:/Volumes/src/cvs/od co -P xar #
# #
# Patched folder, included in the project contain some #
# patches on the original project xar-1.4.tar.gz. This #
# project was created because creating changes ontop of #
# the original open source project has become a serious #
# hassle. #
#########################################################################################

BIN
Revision.plist Normal file

Binary file not shown.

1170
patches/appleadditions.diff Normal file

File diff suppressed because it is too large Load Diff

2056
patches/context.diff Normal file

File diff suppressed because it is too large Load Diff

551
patches/hash.diff Normal file
View File

@ -0,0 +1,551 @@
diff -urN xar/include/xar.h.in xar.hash/include/xar.h.in
--- xar/include/xar.h.in 2006-03-19 20:57:56.000000000 -0800
+++ xar.hash/include/xar.h.in 2006-03-19 20:58:35.000000000 -0800
@@ -38,6 +38,7 @@
#include <sys/types.h>
#include <stdint.h>
+#include <sys/stat.h>
struct xar_header {
uint32_t magic;
@@ -71,7 +72,8 @@
#define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */
#define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */
-#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */
+#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */
+#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */
#define XAR_OPT_VAL_NONE "none"
#define XAR_OPT_VAL_SHA1 "sha1"
#define XAR_OPT_VAL_MD5 "md5"
diff -urN xar/lib/Makefile.inc.in xar.hash/lib/Makefile.inc.in
--- xar/lib/Makefile.inc.in 2006-03-19 20:57:56.000000000 -0800
+++ xar.hash/lib/Makefile.inc.in 2006-03-19 20:58:35.000000000 -0800
@@ -16,7 +16,7 @@
# Sources.
LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c err.c
-LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c linuxattr.c md5.c stat.c
+LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c linuxattr.c hash.c stat.c
LIBXAR_SRCS += subdoc.c util.c zxar.c script.c macho.c
LIBXAR_SRCS := $(patsubst %, @srcroot@lib/%, $(LIBXAR_SRCS))
diff -urN xar/lib/hash.c xar.hash/lib/hash.c
--- xar/lib/hash.c 1969-12-31 16:00:00.000000000 -0800
+++ xar.hash/lib/hash.c 2006-03-19 20:58:51.000000000 -0800
@@ -0,0 +1,210 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <zlib.h>
+#include <openssl/evp.h>
+
+#include "config.h"
+#ifndef HAVE_ASPRINTF
+#include "asprintf.h"
+#endif
+#include "xar.h"
+
+
+struct _hash_context{
+ EVP_MD_CTX src_ctx;
+ EVP_MD_CTX dst_ctx;
+ uint8_t src;
+ uint8_t dst;
+};
+
+#define CONTEXT(x) ((struct _hash_context *)(*x))
+
+static char* xar_format_hash(const unsigned char* m,unsigned int len);
+
+int32_t xar_hash_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) {
+ const char *opt;
+ char *tmpstr;
+ const EVP_MD *md;
+
+ if(!context)
+ return 0;
+
+ asprintf(&tmpstr, "%s/extracted-checksum", attr);
+ opt = xar_attr_get(f, tmpstr, "style");
+ free(tmpstr);
+
+ if( !opt )
+ opt = xar_opt_get(x, XAR_OPT_FILECKSUM);
+
+ if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) )
+ return 0;
+
+ if(!CONTEXT(context)){
+ *context = calloc(1,sizeof(struct _hash_context));
+ OpenSSL_add_all_digests();
+ }
+
+ if( !CONTEXT(context)->src ){
+ md = EVP_get_digestbyname(opt);
+ if( md == NULL ) return -1;
+ EVP_DigestInit(&(CONTEXT(context)->src_ctx), md);
+ CONTEXT(context)->src = 1;
+ }
+
+ if( *inlen == 0 )
+ return 0;
+
+ EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen);
+ return 0;
+}
+
+int32_t xar_hash_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) {
+ const char *opt;
+ const EVP_MD *md;
+ char *tmpstr;
+
+ if(!context)
+ return 0;
+
+ asprintf(&tmpstr, "%s/archived-checksum", attr);
+ opt = xar_attr_get(f, tmpstr, "style");
+ free(tmpstr);
+
+ if( !opt )
+ opt = xar_opt_get(x, XAR_OPT_FILECKSUM);
+
+ if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) )
+ return 0;
+
+ if(!CONTEXT(context)){
+ *context = calloc(1,sizeof(struct _hash_context));
+ OpenSSL_add_all_digests();
+ }
+
+ if ( !CONTEXT(context)->dst ){
+ md = EVP_get_digestbyname(opt);
+ if( md == NULL ) return -1;
+ EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md);
+ CONTEXT(context)->dst = 1;
+ }
+
+ if( inlen == 0 )
+ return 0;
+
+ EVP_DigestUpdate(&(CONTEXT(context)->dst_ctx), in, inlen);
+ return 0;
+}
+
+int32_t xar_hash_done(xar_t x, xar_file_t f, const char *attr, void **context) {
+ unsigned char hashstr[EVP_MAX_MD_SIZE];
+ char *str, *tmpstr;
+ unsigned int len;
+
+ if(!CONTEXT(context))
+ return 0;
+
+ if( CONTEXT(context)->src ){
+ EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx;
+ const EVP_MD *md = EVP_MD_CTX_md(ctx);
+ const char *type = EVP_MD_name(md);
+
+ memset(hashstr, 0, sizeof(hashstr));
+ EVP_DigestFinal(&(CONTEXT(context)->src_ctx), hashstr, &len);
+ str = xar_format_hash(hashstr,len);
+ asprintf(&tmpstr, "%s/extracted-checksum", attr);
+ if( f ) {
+ xar_prop_set(f, tmpstr, str);
+ xar_attr_set(f, tmpstr, "style", type);
+ }
+ free(tmpstr);
+ free(str);
+ }
+
+ if( CONTEXT(context)->dst ){
+ EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx;
+ const EVP_MD *md = EVP_MD_CTX_md(ctx);
+ const char *type = EVP_MD_name(md);
+
+ memset(hashstr, 0, sizeof(hashstr));
+ EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), hashstr, &len);
+ str = xar_format_hash(hashstr,len);
+ asprintf(&tmpstr, "%s/archived-checksum", attr);
+ if( f ) {
+ xar_prop_set(f, tmpstr, str);
+ xar_attr_set(f, tmpstr, "style", type);
+ }
+ free(tmpstr);
+ free(str);
+ }
+
+ if(*context){
+ free(*context);
+ *context = NULL;
+ }
+
+ return 0;
+}
+
+static char* xar_format_hash(const unsigned char* m,unsigned int len) {
+ char* result = malloc((2*len)+1);
+ char hexValue[3];
+ unsigned int itr = 0;
+
+ result[0] = '\0';
+
+ for(itr = 0;itr < len;itr++){
+ sprintf(hexValue,"%02x",m[itr]);
+ strncat(result,hexValue,2);
+ }
+
+ return result;
+}
+
+int32_t xar_hash_out_done(xar_t x, xar_file_t f, const char *attr, void **context) {
+ const char *uncomp, *uncompstyle;
+ unsigned char hashstr[EVP_MAX_MD_SIZE];
+ unsigned int len;
+ char *tmpstr;
+ const EVP_MD *md;
+
+ if(!CONTEXT(context))
+ return 0;
+
+ if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){
+ return 0;
+ }
+
+ asprintf(&tmpstr, "%s/extracted-checksum", attr);
+ xar_prop_get(f, tmpstr, &uncomp);
+ uncompstyle = xar_attr_get(f, tmpstr, "style");
+ free(tmpstr);
+
+ md = EVP_get_digestbyname(uncompstyle);
+
+ if( uncomp && uncompstyle && md && CONTEXT(context)->dst ) {
+ char *str;
+ memset(hashstr, 0, sizeof(hashstr));
+ EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), hashstr, &len);
+ str = xar_format_hash(hashstr,len);
+ if(strcmp(uncomp, str) != 0) {
+ xar_err_new(x);
+ xar_err_set_file(x, f);
+ asprintf(&tmpstr, "extracted-checksum %s's do not match",uncompstyle);
+ xar_err_set_string(x, tmpstr);
+ xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
+ }
+ free(str);
+ }
+
+ if( CONTEXT(context)->src )
+ EVP_DigestFinal(&(CONTEXT(context)->src_ctx), hashstr, &len);
+
+ if(*context){
+ free(*context);
+ *context = NULL;
+ }
+
+ return 0;
+}
diff -urN xar/lib/hash.h xar.hash/lib/hash.h
--- xar/lib/hash.h 1969-12-31 16:00:00.000000000 -0800
+++ xar.hash/lib/hash.h 2006-03-19 20:58:35.000000000 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005 Rob Braun
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Rob Braun nor the names of his contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * 03-Apr-2005
+ * DRI: Rob Braun <bbraun@opendarwin.org>
+ */
+
+#ifndef _XAR_HASH_H_
+#define _XAR_HASH_H_
+
+int32_t xar_hash_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context);
+int32_t xar_hash_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context);
+int32_t xar_hash_done(xar_t x, xar_file_t f, const char *, void **context);
+int32_t xar_hash_out_done(xar_t x, xar_file_t f, const char *, void **context);
+
+#endif /* _XAR_HASH_H_ */
diff -urN xar/lib/io.c xar.hash/lib/io.c
--- xar/lib/io.c 2006-03-19 20:58:13.000000000 -0800
+++ xar.hash/lib/io.c 2006-03-19 20:58:35.000000000 -0800
@@ -54,7 +54,7 @@
#include "io.h"
#include "zxar.h"
#include "bzxar.h"
-#include "md5.h"
+#include "hash.h"
#include "script.h"
#include "macho.h"
@@ -68,11 +68,11 @@
struct datamod xar_datamods[] = {
{ (fromheap_in)NULL,
- xar_md5_compressed,
- xar_md5out_done,
- xar_md5_uncompressed,
- xar_md5_compressed,
- xar_md5_done
+ xar_hash_compressed,
+ xar_hash_out_done,
+ xar_hash_uncompressed,
+ xar_hash_compressed,
+ xar_hash_done
},
{ (fromheap_in)NULL,
(fromheap_out)NULL,
diff -urN xar/lib/md5.c xar.hash/lib/md5.c
--- xar/lib/md5.c 2006-03-19 20:58:13.000000000 -0800
+++ xar.hash/lib/md5.c 1969-12-31 16:00:00.000000000 -0800
@@ -1,179 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <zlib.h>
-#include <openssl/evp.h>
-
-#include "config.h"
-#ifndef HAVE_ASPRINTF
-#include "asprintf.h"
-#endif
-#include "xar.h"
-
-struct _md5_context{
- EVP_MD_CTX src_ctx;
- EVP_MD_CTX dst_ctx;
- uint8_t src;
- uint8_t dst;
-};
-
-#define CONTEXT(x) ((struct _md5_context *)(*x))
-
-static char* xar_format_md5(const unsigned char* m);
-
-int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) {
- const EVP_MD *md;
-
- if(!context)
- return 0;
-
- if(!CONTEXT(context)){
- *context = calloc(1,sizeof(struct _md5_context));
- OpenSSL_add_all_digests();
- }
-
- if( !CONTEXT(context)->src ){
- md = EVP_get_digestbyname("md5");
- if( md == NULL ) return -1;
- EVP_DigestInit(&(CONTEXT(context)->src_ctx), md);
- CONTEXT(context)->src = 1;
- }
-
- if( *inlen == 0 )
- return 0;
-
- EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen);
- return 0;
-}
-
-int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) {
- const EVP_MD *md;
-
- if(!context)
- return 0;
-
- if(!CONTEXT(context)){
- *context = calloc(1,sizeof(struct _md5_context));
- OpenSSL_add_all_digests();
- }
-
- if( !CONTEXT(context)->dst ){
- md = EVP_get_digestbyname("md5");
- if( md == NULL ) return -1;
- EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md);
- CONTEXT(context)->dst = 1;
- }
-
- if( inlen == 0 )
- return 0;
-
- EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), in, inlen);
- return 0;
-}
-
-int32_t xar_md5_done(xar_t x, xar_file_t f, const char *attr, void **context) {
- unsigned char md5str[EVP_MAX_MD_SIZE];
- char *str, *tmpstr;
- unsigned int len;
-
- if(!CONTEXT(context))
- return 0;
-
- if( CONTEXT(context)->src ){
- EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx;
- const EVP_MD *md = EVP_MD_CTX_md(ctx);
-
- memset(md5str, 0, sizeof(md5str));
- EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len);
- str = xar_format_md5(md5str);
- asprintf(&tmpstr, "%s/extracted-checksum", attr);
- if( f ) {
- xar_prop_set(f, tmpstr, str);
- xar_attr_set(f, tmpstr, "style", "md5");
- }
- free(tmpstr);
- free(str);
- }
-
- if( CONTEXT(context)->dst ){
- EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx;
- const EVP_MD *md = EVP_MD_CTX_md(ctx);
-
- memset(md5str, 0, sizeof(md5str));
- EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len);
- str = xar_format_md5(md5str);
- asprintf(&tmpstr, "%s/archived-checksum", attr);
- if( f ) {
- xar_prop_set(f, tmpstr, str);
- xar_attr_set(f, tmpstr, "style", "md5");
- }
- free(tmpstr);
- free(str);
- }
-
- if(*context){
- free(*context);
- *context = NULL;
- }
-
- return 0;
-}
-
-static char* xar_format_md5(const unsigned char* m) {
- char* result = NULL;
- asprintf(&result,
- "%02x%02x%02x%02x"
- "%02x%02x%02x%02x"
- "%02x%02x%02x%02x"
- "%02x%02x%02x%02x",
- m[0], m[1], m[2], m[3],
- m[4], m[5], m[6], m[7],
- m[8], m[9], m[10], m[11],
- m[12], m[13], m[14], m[15]);
- return result;
-}
-
-int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *attr, void **context) {
- const char *uncomp, *uncompstyle;
- unsigned char md5str[EVP_MAX_MD_SIZE];
- unsigned int len;
- char *tmpstr;
-
- if(!CONTEXT(context))
- return 0;
-
- if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){
- return 0;
- }
-
- asprintf(&tmpstr, "%s/extracted-checksum", attr);
- xar_prop_get(f, tmpstr, &uncomp);
- uncompstyle = xar_attr_get(f, tmpstr, "style");
- free(tmpstr);
-
- if( uncomp && uncompstyle && CONTEXT(context)->dst ) {
- char *str;
- memset(md5str, 0, sizeof(md5str));
- EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len);
- str = xar_format_md5(md5str);
- if(strcmp(uncomp, str) != 0) {
- xar_err_new(x);
- xar_err_set_file(x, f);
- asprintf(&tmpstr, "extracted-checksum MD5's do not match");
- xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
- }
- free(str);
- }
-
- if( CONTEXT(context)->src )
- EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len);
-
- if(*context){
- free(*context);
- *context = NULL;
- }
-
- return 0;
-
-}
diff -urN xar/lib/md5.h xar.hash/lib/md5.h
--- xar/lib/md5.h 2006-03-19 20:58:13.000000000 -0800
+++ xar.hash/lib/md5.h 1969-12-31 16:00:00.000000000 -0800
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005 Rob Braun
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Rob Braun nor the names of his contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * 03-Apr-2005
- * DRI: Rob Braun <bbraun@opendarwin.org>
- */
-
-#ifndef _XAR_MD5_H_
-#define _XAR_MD5_H_
-
-int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context);
-int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context);
-int32_t xar_md5_done(xar_t x, xar_file_t f, const char *, void **context);
-int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *, void **context);
-
-#endif /* _XAR_MD5_H_ */

26
patches/noea.diff Normal file
View File

@ -0,0 +1,26 @@
diff -urN xar/lib/darwinattr.c xar.patch/lib/darwinattr.c
--- xar/lib/darwinattr.c 2006-03-16 11:45:21.000000000 -0800
+++ xar.patch/lib/darwinattr.c 2006-03-16 11:48:27.000000000 -0800
@@ -569,10 +569,6 @@
#if defined(__APPLE__)
if( len )
return 0;
-#if defined(HAVE_GETXATTR)
- if( ea_archive(x, f, file, (void *)&context) == 0 )
- return 0;
-#endif
if( nonea_archive(x, f, file, (void *)&context) == 0 )
return 0;
return underbar_archive(x, f, file, (void *)&context);
@@ -589,11 +585,6 @@
#if defined(__APPLE__)
if( len )
return 0;
-#if defined(HAVE_GETXATTR)
- if( ea_extract(x, f, file, (void *)&context) == 0 )
- return 0;
-#endif
-
if( nonea_extract(x, f, file, (void *)&context) == 0 )
return 0;
#endif /* __APPLE__ */

39
patches/static-lib.diff Normal file
View File

@ -0,0 +1,39 @@
diff -urN xar/lib/Makefile.inc.in xar.change/lib/Makefile.inc.in
--- xar/lib/Makefile.inc.in 2006-03-20 21:29:23.000000000 -0800
+++ xar.change/lib/Makefile.inc.in 2006-03-20 21:29:08.000000000 -0800
@@ -39,6 +39,12 @@
LIBXAR_SNAME := libxar.@LIB_REV@.dylib
LIBXAR_LNAME := libxar.dylib
LIBXAR_L := @objroot@lib/$(LIBXAR_LNAME)
+
+LIBXARSTATIC := libxar.a
+LIBXARSTATIC_L := @objroot@lib/$(LIBXARSTATIC)
+
+
+
endif
ifeq (aout, @abi@)
LIBRXAR_SNAME := librxar.so.@LIB_REV@.0
@@ -64,11 +70,13 @@
lib_all : $(LIBRXAR_S) $(LIBXAR_S)
-lib_install : $(LIBXAR_S)
+lib_install : $(LIBXAR_S) $(LIBXARSTATIC)
@INSTALL@ -d $(DESTDIR)$(INCLUDEDIR)/xar
@INSTALL@ -m 0644 $(LIBXAR_INCS) $(DESTDIR)$(INCLUDEDIR)/xar
@INSTALL@ -d $(DESTDIR)$(LIBDIR)
@INSTALL@ -m 0444 $(LIBXAR_S) $(DESTDIR)$(LIBDIR)
+ @INSTALL@ -d $(DESTDIR)/usr/local/lib/
+ @INSTALL@ -m 0444 $(LIBXARSTATIC) $(DESTDIR)/usr/local/lib/
ifneq ($(words "" $(LIBXAR_LNAME)), 1)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
ln -s $(LIBXAR_SNAME) $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
@@ -125,6 +133,7 @@
endif
ifeq (macho, @abi@)
$(CC) -dynamiclib -compatibility_version @LIB_REV@ -current_version @LIB_REV@ -install_name $(LIBDIR)/$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@
+ $(AR) cq $(LIBXARSTATIC) $+
endif
ifeq (aout, @abi@)
$(CC) -shared -o $@ $+

69
test_tools/xar.tcl Normal file
View File

@ -0,0 +1,69 @@
big_endian
requires 0 "78617221" ;# xar!
ascii 4 "Signature"
set headersize [uint16 "Header Size"]
uint16 "Version"
set compressed_length [uint64 "TOC Compressed Length"]
uint64 "TOC Uncompressed Length"
uint32 "Checksum"
set compressed_data [bytes $compressed_length "TOC Data"]
set xml [zlib_uncompress $compressed_data]
#puts "${xml}"
package require tdom
set doc [dom parse $xml]
set root [$doc documentElement]
set hashes [$root selectNodes "//checksum"]
set signatures [$root selectNodes "//signature"]
section "Hashes"
foreach hash $hashes {
section [$hash getAttribute "style"] {
set lengthString [[lindex [$hash getElementsByTagName "size"] 0] text]
set offsetString [[lindex [$hash getElementsByTagName "offset"] 0] text]
scan $lengthString "%d" length
scan $offsetString "%d" heapoffset
set offset [expr { $heapoffset + $headersize + $compressed_length}]
entry "Checksum" "<DATA>" $length $offset
}
}
endsection
section "Signatures"
foreach signature $signatures {
section [$signature getAttribute "style"] {
set lengthString [[lindex [$signature getElementsByTagName "size"] 0] text]
set offsetString [[lindex [$signature getElementsByTagName "offset"] 0] text]
scan $lengthString "%d" length
scan $offsetString "%d" heapoffset
set offset [expr { $heapoffset + $headersize + $compressed_length}]
entry "Signature Blob" "<DATA>" $length $offset
}
}
endsection
set nodes [$root selectNodes "//file"]
section "Files" {
foreach node $nodes {
section [[lindex [$node getElementsByTagName "name"] 0] text] {
entry "ID" [$node getAttribute "id"]
entry "Type" [[lindex [$node getElementsByTagName "type"] 0] text]
set dataNode [lindex [$node getElementsByTagName "data"] 0]
set compressedSizeString [[lindex [$dataNode getElementsByTagName "length"] 0] text]
set offsetString [[lindex [$dataNode getElementsByTagName "offset"] 0] text]
scan $compressedSizeString "%d" compressedSize
scan $offsetString "%d" heapoffset
set offset [expr { $heapoffset + $headersize + $compressed_length}]
entry "Size" [[lindex [$dataNode getElementsByTagName "size"] 0] text]
entry "Compressed Size" $compressedSizeString
entry "Compressed Blob" "<DATA>" $compressedSize $offset
}
}
}

26
xar.plist Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>OpenSourceLicense</key>
<string>BSD</string>
<key>OpenSourceLicenseFile</key>
<string>xar.txt</string>
<key>OpenSourceMD5</key>
<string>7f3976664a426911eab93cdf367894bc</string>
<key>OpenSourceModifications</key>
<array>
<string>3397142</string>
</array>
<key>OpenSourceProject</key>
<string>xar</string>
<key>OpenSourceURL</key>
<string>http://www.opendarwin.org/projects/xar/xar-1.4.tar.gz</string>
<key>OpenSourceVersion</key>
<string>1.4</string>
<key>OpenSourceWebsiteURL</key>
<string>http://www.opendarwin.org/projects/xar/</string>
</dict>
</array>
</plist>

35
xar.txt Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2005 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@opendarwin.org>
*/
/*
* Portions Copyright (c) 2006 Apple Computer, Inc.
*/

11
xar.xcconfig Normal file
View File

@ -0,0 +1,11 @@
//
// xar.xcconfig
// xar
//
// Created by Lucy Zhang on 1/30/19.
//
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974
IS_ZIPPERED = YES

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:xar.xcodeproj">
</FileRef>
</Workspace>

7
xar/.cvsignore Normal file
View File

@ -0,0 +1,7 @@
Makefile
autom4te.cache
cfghdrs.stamp
cfgoutputs.stamp
configure
config.log
config.status

68
xar/ChangeLog Normal file
View File

@ -0,0 +1,68 @@
devel
2008-08-19 Rob Braun bbraun@synack.net
* lib/lzmaxar.c: if lzma compression is specified but not compiled in, throw an error.
* src/xar.c: When extracting, save directories until the end. This lets timestamps get set correctly on directories and addresses issue #58.
2008-08-17 Rob Braun bbraun@synack.net
* lib/archive.c: Make sure the binary header and toc checksum types match. Contributed by Apple.
2008-08-15 Rob Braun bbraun@synack.net
* lib/Makefile.inc.in: Add the $(LDFLAGS) variable when creating libxar
* src/xar.c: Fix a typo in the usage statement.
* lib/io.c: Fix seeking on a pipe
2008-08-14 Rob Braun bbraun@synack.net
* lib/bzxar.c: if bzip2 compression is specified but not compiled in, throw an error.
* src/xar.c src/xar.1: Add -C to chdir before extraction.
* lib/script.c: Perform some input checking.
* lib/b64.c lib/b64.h: xar_to_base64() was never used, so it is removed.
* lib/lzmaxar.c: Update the use of the lzma API to match 4.42 alpha 6 of the lzma library from Anders F Björklund.
2007-12-14 Rob Braun bbraun@synack.net
* configure.ac: Fix a broken configure check for sys/acl.h and acl_t
2007-12-09 Rob Braun bbraun@synack.net
* include/xar.h.in lib/filetree.c lib/stat.c test/validate.c: Make sure xar_iter_new() takes no parameters. From rpm5.
* lib/libxar.la.in.in: set the libxir to @LIBDIR@ from autoconf. From rpm5.
* configure.ac: Allow specifying the path to lzma with --with-lzma=PATH
* lib/lzmaxar.c: Use the global macro for compression level.
2007-11-11 Rob Braun bbraun@synack.net
* lib/archive.c: Add a #define for a mising function in Mac OS X's old version of libxml2 from Anders F Björklund.
* lib/Makefile.inc.in: Be a little more gnu libtool friendly from Anders F Björklund.
2007-11-11 Rob Braun bbraun@synack.net
* lib/archive.c: Some memory leak cleanups from Anders F Björklund.
2007-11-1 Dave Leimbach leimy2k@gmail.com
* lib/data.c: fixed a file descriptor leak by adding a close before return
* src/xar.1: Added man page text for --extract-subdoc
2007-10-22 Rob Braun bbraun@synack.net
* src/xar.c src/xar.1: Add -a as a synonym for --compression=lzma
* lib/darwinattr.c lib/fbsdattr.c: Add --prop-exclude support for darwin and fbsd EAs.
2007-10-16 Rob Braun bbraun@synack.net
* include/xar.h.in src/xar.c lib/io.c lib/lzmaxar.c lib/bzxar.c lib/archive.c lib/zxar.c: Added an option to pass arguments to the compression code. This to allow specifying compression levels to gzip, bzip2, and lzma.
* lib/io.c: Issue 41, fixed a bug where rsize was being used uninitialized.
* lib/io.c: Issue 42, log a warning and continue if archived-checksum doesn't appear when archiving a file.
* lib/archive.c: Issue 43, free the buffer in xar_extract_tobuffersz() if there is an error extracting the file.
2007-10-02 Rob Braun bbraun@synack.net
* test/compression test/data include/config.h.in include/xar.h.in src/xar.1 src/xar.c configure.ac lib/lzmaxar.c lib/lzmaxar.h lib/io.c lib/bzxar.c lib/Makefile.inc.in lib/zxar.c INSTALL: Incorporate a patch from anders.f.bjorklund for adding lzma compression support.
2007-10-02 Rob Braun bbraun@synack.net
* include/xar.h.in lib/io.c lib/io.h lib/archive.c: Add a "streaming" API that allows for file data to be extracted incrementally, like the zlib decompression API, instead of requiring the entire file to fit in memory like xar_extract_tobuffer(). This is the inital commit of the API and may still change. This change is based on a patch from Charles Srstka.
2007-09-26 Rob Braun bbraun@synack.net
* lib/io.c: Consolidate the lseek handling code into one function.
Contributed by Charles Srstka as part of Issue 2.
2007-09-21 Rob Braun bbraun@synack.net
* include/xar.h.in src/xar.c src/xar.1 lib/stat.c: Only extract setuid/setgid bits if the user/group are the same as the archived file (if -p/-P are specified on the command line) OR if the newly added --keep-setuid flag is specified.
* configure.ac lib/stat.c: Fix the autoconf test for ino_t size, and switch the inode and device number printf's to use the autogenerated INO_STRING and DEV_STRING to get the correct formatting parameter.
2007-09-20 Rob Braun bbraun@synack.net
* src/xar.c src/xar.1: Add -k as a synonym for --keep-existing for tar compatibility.
2007-09-20 Rob Braun bbraun@synack.net
* src/xar.c src/xar.1: Add --keep-existing flag which prevents existing files from being extracted.
2007-09-20 Rob Braun bbraun@synack.net
* lib/archive.c: Fix a bug in toc parsing where invalid tocs, particularly with mismatched closing tags, would still be processed.
2007-09-20 Rob Braun bbraun@synack.net
* lib/filetree.c: Fix a minor memory leak with xar_iter_free() not freeing all memory associated with a xar_iter_t.
2007-09-20 Rob Braun bbraun@synack.net
* ChangeLog: renamed from CHANGELOG.
2007-09-19 Dave Leimbach leimy2k@gmail.com
* xar/xar.c xar/xar.1: Added support for -j and -z as shortcuts for --compression=bzip2 or --compression=zlib respectively.
2007-09-19 Rob Braun bbraun@synack.net
* lib/zxar.c lib/bzxar.c: cleanup for more consistency between the two compression modules. Patch contributed by Anders Björklund from the rpm5 project.
2007-09-19 Rob Braun bbraun@synack.net
* CHANGELOG: Added changelog
* include/xar.h.in src/xar.c lib/util.c: moved helper functions for retrieving and formating file properties such as size, mode, mtime, etc. from src/xar.c to lib/util.c and exported them in xar.h.
* lib/err.c lib/archive.h: Added the xar_t archive context to the error handler context to be able to retrieve archive level context within an error, such as archive level options, or being able to examine other files than the one the error occurred on.
* lib/strmode.h lib/util.c config.h.in configure.ac: Import strmode(3) from freebsd to handle the formatting of file mode in xar_get_mode(), used for displaying file mode from xar -tvf. configure will automatically detect whether to use the OS strmode(3) or the included copy.

160
xar/INSTALL Normal file
View File

@ -0,0 +1,160 @@
################################################################################
#
# Building and installation instructions for the Xar source distribution.
#
################################################################################
Required: Xar's build system uses GNU make.
Required: Xar depends on libxml2's XML functionality. For more information
about libxml2, see:
http://www.xmlsoft.org/
Required: Xar depends on OpenSSL (libcrypto in particular) for MD5 and SHA1
functionality. For more information about OpenSSL, see:
http://www.openssl.org/
Required: Xar depends on zlib (libz) for data compression. For more information
about zlib, see:
http://www.zlib.net/
Optional: Xar can optionally use libbzip2 for data compression. For more
information about libbzip2, see:
http://www.bzip.org/
Optional: Xar can optionally use liblzma for data compression. For more
information about liblzma, see:
http://tukaani.org/lzma/
Optional: Regenerating the configure script requires GNU autoconf. Doing so is
only necessary when making changes to the configuration system.
################################################################################
Building Xar is in many cases as simple as typing the following commands while
in the root directory of the source tree:
./configure
make
To install, do the above, then type:
make install
Additional build targets of finer granularity include:
src_all
lib_all
Additional install targets of finer granularity include:
src_install
lib_install
Uninstall targets include:
uninstall
src_uninstall
lib_uninstall
Cleanup targets include:
clean
distclean
relclean
Note that if you are using a development version of xar, configure is
not checked into the repository. You may replace the ./configure step
above with ./autogen.sh.
################################################################################
The build system is capable of building in a different directory than the
source, so that no files are written to the source tree. In order to use this
feature, run 'configure' and 'make' while in the directory that you want to
build the software in.
Optionally, pass any of the following arguments to 'configure' (run 'configure'
with the --help option for a full list):
--prefix=<install-root-dir>
Set the base directory in which to install. For example:
./configure --prefix=/usr/local
will cause files to be installed into /usr/local/bin, /usr/local/man,
/usr/local/include, /usr/local/lib, and /usr/local/share.
--enable-autogen
Include dependency rules in the build system to automatically regenerate
files created by configure when their sources are newer. This is
only of interest when making modifications to the source code.
--with-xml2-config=<path>
If specified, use <path> as the full path (including filename) to the
xml2-config program. This is useful when there is more than one copy of
xml2-config in your shell's path, or when you want to use a copy of
xml2-config that is not in your shell's path at all.
Optionally, define environment variables when invoking configure, including (not
exclusively):
CFLAGS="?"
Pass these flags to the compiler.
CPPFLAGS="?"
Pass these flags to the C preprocessor. Note that CFLAGS is not passed
to 'cpp' when 'configure' is looking for include files, so you must use
CPPFLAGS instead if you need to help 'configure' find header files.
LD_LIBRARY_PATH="?"
'ld' uses this colon-separated list to find libraries.
LDFLAGS="?"
Pass these flags when linking.
PATH="?"
'configure' uses this to find programs.
################################################################################
Optionally, define make variables when invoking make, including (not
exclusively):
PREFIX="?"
Use this as the installation prefix.
BINDIR="?"
Use this as the installation prefix for programs.
DATADIR="?"
Use this as the installation prefix for modules and documentation.
LIBDIR="?"
Use this as the installation prefix for libraries.
INCLUDEDIR="?"
Use this as the installation prefix for header files.
MANDIR="?"
Use this as the installation prefix for man pages.
CC="?"
Use this to specify the C compiler.
CFLAGS="?"
Pass these flags to the compiler.
CPPFLAGS="?"
Pass these flags to the C preprocessor.
LDFLAGS="?"
Pass these flags when linking.
PATH="?"
Use this to search for programs used during configuration and building.

33
xar/LICENSE Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/

108
xar/Makefile.in Normal file
View File

@ -0,0 +1,108 @@
# Clear out all vpaths, then set just one (default vpath) for the main build
# directory.
vpath
vpath % .
# Clear the default suffixes, so that built-in rules are not used.
.SUFFIXES :
#
# Standard definitions.
#
SHELL := /bin/sh
CC := @CC@
LD := @LD@
AR := @AR@
RANLIB := @RANLIB@
INSTALL := @INSTALL@
AUTOCONF := @AUTOCONF@
#
# Build parameters.
#
CPPFLAGS := @CPPFLAGS@
CFLAGS := @CFLAGS@
A_CFLAGS := $(CFLAGS)
S_CFLAGS := $(CFLAGS) -fPIC -DPIC
ifeq (macho, @abi@)
S_CFLAGS += -dynamic
endif
LDFLAGS := @LDFLAGS@
prefix := @PREFIX@
bindir := @BINDIR@
datadir := @DATADIR@
libdir := @LIBDIR@
includedir := @INCLUDEDIR@
mandir := @MANDIR@
PREFIX := $(prefix)
BINDIR := $(bindir)
DATADIR := $(datadir)
LIBDIR := $(libdir)
INCLUDEDIR := $(includedir)
MANDIR := $(mandir)
dir_names := lib src
all : $(dir_names:%=%_all)
install : $(dir_names:%=%_install)
uninstall : $(dir_names:%=%_uninstall)
clean : $(dir_names:%=%_clean)
distclean : clean $(dir_names:%=%_distclean)
rm -f @objroot@config.log
rm -f @objroot@config.status
rm -f @objroot@cfghdrs.stamp
rm -f @objroot@cfgoutputs.stamp
rm -f @objroot@configure.lineno
rm -f @cfghdrs@
rm -f @cfgoutputs@
rm -rf @objroot@autom4te.cache
relclean : distclean
rm -f @objroot@configure
# Include Makefile.inc files in subdirectories.
include $(dir_names:%=%/Makefile.inc)
#
# Re-configuration rules.
#
ifeq (@enable_autogen@, 1)
@srcroot@configure : @srcroot@configure.ac
cd ./@srcroot@ && $(AUTOCONF)
@objroot@config.status : @srcroot@configure
./@objroot@config.status --recheck
# cfghdrs rules.
@srcroot@cfghdrs.stamp.in : @srcroot@configure.ac
echo stamp > @srcroot@cfghdrs.stamp.in
$(patsubst %, @srcroot@%.in, @cfghdrs@) : @objroot@config.status
@objroot@cfghdrs.stamp : $(patsubst %, @srcroot@%.in, @cfghdrs@)
./@objroot@config.status
echo stamp > $@
$(filter-out @objroot@cfghdrs.stamp, @cfghdrs@) : @objroot@cfghdrs.stamp
# cfgoutputs rules.
@srcroot@cfgoutputs.stamp.in : @srcroot@configure.ac
echo stamp > @srcroot@cfgoutputs.stamp.in
$(patsubst %, @srcroot@%.in, @cfgoutputs@) : @objroot@config.status
@objroot@cfgoutputs.stamp : $(patsubst %, @srcroot@%.in, @cfgoutputs@)
./@objroot@config.status
$(filter-out \
@objroot@cfgoutputs.stamp, \
$(patsubst %, @objroot@%, @cfgoutputs@)) : @objroot@cfgoutputs.stamp
endif

2
xar/TODO Normal file
View File

@ -0,0 +1,2 @@
The xar TODO exists primarily on the wiki site at:
http://wiki.opendarwin.org/index.php/Xar:Todo

21
xar/autogen.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/sh
for i in autoconf; do
echo "$i"
$i
if [ $? -ne 0 ]; then
echo "Error $? in $i"
exit 1
fi
done
if [ "$1" = "--noconfigure" ]; then
exit 0;
fi
echo "./configure --enable-autogen $@"
./configure --enable-autogen $@
if [ $? -ne 0 ]; then
echo "Error $? in ./configure"
exit 1
fi

2
xar/cfghdrs.stamp Normal file
View File

@ -0,0 +1,2 @@
/* cfghdrs.stamp. Generated from cfghdrs.stamp.in by configure. */
stamp

1
xar/cfghdrs.stamp.in Normal file
View File

@ -0,0 +1 @@
stamp

1
xar/cfgoutputs.stamp Normal file
View File

@ -0,0 +1 @@
stamp

1
xar/cfgoutputs.stamp.in Normal file
View File

@ -0,0 +1 @@
stamp

1466
xar/config.guess vendored Normal file

File diff suppressed because it is too large Load Diff

1068
xar/config.status Executable file

File diff suppressed because it is too large Load Diff

1579
xar/config.sub vendored Normal file

File diff suppressed because it is too large Load Diff

6350
xar/configure vendored Executable file

File diff suppressed because it is too large Load Diff

361
xar/configure.ac Normal file
View File

@ -0,0 +1,361 @@
AC_PREREQ(2.59)
AC_INIT([Xar], [1.8dev], [xar-devel@googlegroups.com], [xar])
AC_CONFIG_SRCDIR([LICENSE])
dnl Revision number for libxar.
LIB_REV=1
AC_SUBST([LIB_REV])
dnl xar version variables.
XAR_MAJOR_VERSION="1"
XAR_MINOR_VERSION="8dev"
XAR_VERSION="${XAR_MAJOR_VERSION}.${XAR_MINOR_VERSION}"
AC_SUBST([XAR_MAJOR_VERSION])
AC_SUBST([XAR_MINOR_VERSION])
AC_SUBST([XAR_VERSION])
dnl
dnl Various paths.
dnl
srcroot=$srcdir
if test "x${srcroot}" = "x." ; then
srcroot=""
else
srcroot="${srcroot}/"
fi
AC_SUBST([srcroot])
abs_srcroot="`cd "$srcdir"; pwd`/"
AC_SUBST([abs_srcroot])
objroot=""
AC_SUBST([objroot])
abs_objroot="`pwd`/"
AC_SUBST([abs_objroot])
dnl Set install paths.
if test "x$prefix" = "xNONE" ; then
prefix="/usr/local"
fi
if test "x$exec_prefix" = "xNONE" ; then
exec_prefix=$prefix
fi
PREFIX=$prefix
AC_SUBST([PREFIX])
BINDIR=`eval echo $bindir`
BINDIR=`eval echo $BINDIR`
AC_SUBST([BINDIR])
DATADIR=`eval echo $datadir`
DATADIR=`eval echo $DATADIR`
AC_SUBST([DATADIR])
LIBDIR=`eval echo $libdir`
LIBDIR=`eval echo $LIBDIR`
AC_SUBST([LIBDIR])
INCLUDEDIR=`eval echo $includedir`
INCLUDEDIR=`eval echo $INCLUDEDIR`
AC_SUBST([INCLUDEDIR])
MANDIR=`eval echo $mandir`
MANDIR=`eval echo $MANDIR`
AC_SUBST([MANDIR])
cfgoutputs="cfgoutputs.stamp"
cfgoutputs="${cfgoutputs} Makefile"
cfgoutputs="${cfgoutputs} include/xar.h"
cfgoutputs="${cfgoutputs} lib/Makefile.inc"
cfgoutputs="${cfgoutputs} lib/libxar.la.in"
cfgoutputs="${cfgoutputs} src/Makefile.inc"
cfgoutputs="${cfgoutputs} xar.spec"
cfghdrs="${objroot}cfghdrs.stamp"
cfghdrs="${cfghdrs} ${objroot}include/config.h"
dnl If CFLAGS isn't defined and using gcc, set CFLAGS to something reasonable.
dnl Otherwise, just prevent autoconf from molesting CFLAGS.
CFLAGS=$CFLAGS
AC_PROG_CC
AC_SYS_LARGEFILE
if test "x$CFLAGS" = "x" ; then
no_CFLAGS="yes"
fi
if test "x$no_CFLAGS" = "xyes" -a "x$GCC" = "xyes" ; then
CFLAGS="-Wall -g"
fi
dnl Append EXTRA_CFLAGS to CFLAGS, if defined.
if test "x$EXTRA_CFLAGS" != "x" ; then
CFLAGS="$CFLAGS $EXTRA_CFLAGS"
fi
AC_PROG_CPP
AC_PROG_INSTALL
AC_PATH_PROG([LD], [ld], , [$PATH])
AC_PATH_PROG([AR], [ar], , [$PATH])
AC_PATH_PROG([RANLIB], [ranlib], , [$PATH])
AC_PATH_PROG([AUTOCONF], [autoconf], , [$PATH])
dnl Some libtool envy
#AC_ENABLE_SHARED
AC_MSG_CHECKING([whether to build shared libraries])
AC_ARG_ENABLE([shared],
[AC_HELP_STRING([--enable-shared],
[build shared libraries @<:@default=yes@:>@])],
[shared=$enableval],[shared=yes])
AC_MSG_RESULT($shared)
AC_SUBST([shared])
#AC_ENABLE_STATIC
AC_MSG_CHECKING([whether to build static libraries])
AC_ARG_ENABLE([static],
[AC_HELP_STRING([--enable-static],
[build static libraries @<:@default=yes@:>@])],
[static=$enableval],[static=yes])
AC_MSG_RESULT($static)
AC_SUBST([static])
# Make sure either enable_shared or enable_static is yes.
test "$shared" = "yes" || test "$static" = "yes"
dnl Platform-specific settings. abi and RPATH can probably be determined
dnl programmatically, but doing so is error-prone, which makes it generally
dnl not worth the trouble.
dnl
dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the
dnl definitions need to be seen before and headers are included, which is a pain
dnl to make happen otherwise.
AC_CANONICAL_HOST
case "${host}" in
*-*-darwin*)
abi="macho"
RPATH=""
;;
*-*-freebsd*)
CFLAGS="$CFLAGS"
abi="elf"
RPATH="-Wl,-rpath,"
;;
*-*-linux*)
CFLAGS="$CFLAGS"
abi="elf"
dnl Linux needs this for things like asprintf() and poll() flags.
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
RPATH="-Wl,-rpath,"
;;
*-*-netbsd*)
AC_MSG_CHECKING([ABI])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[#ifdef __ELF__
/* ELF */
#else
#error aout
#endif
]])],
[CFLAGS="$CFLAGS"; abi="elf"],
[abi="aout"])
AC_MSG_RESULT([$abi])
RPATH="-Wl,-rpath,"
;;
*-*-solaris2*)
CFLAGS="$CFLAGS"
abi="elf"
RPATH="-Wl,-R,"
dnl XXX Remove the following if it ends up not being useful.
dnl Solaris needs this for sigwait().
dnl CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
dnl LIBS="$LIBS -lposix4 -lsocket -lnsl"
;;
*)
AC_MSG_RESULT([Unsupported operating system: ${host}])
abi="elf"
RPATH="-Wl,-rpath,"
;;
esac
AC_SUBST([abi])
AC_SUBST([RPATH])
dnl Disable rules that do automatic regeneration of configure output by default.
AC_ARG_ENABLE([autogen],
[ --enable-autogen Automatically regenerate configure output],
[if test "x$enable_autogen" = "xno" ; then
enable_autogen="0"
else
enable_autogen="1"
fi
],
[enable_autogen="0"]
)
AC_SUBST([enable_autogen])
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/acl.h>], [acl_t a], [AC_DEFINE([HAVE_SYS_ACL_H],[1], [define if you have sys/acl.h and it has a working acl_t type])])
AC_CHECK_HEADERS(ext2fs/ext2_fs.h sys/statfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h)
AC_CHECK_FUNCS(lgetxattr)
AC_CHECK_FUNCS(lsetxattr)
AC_CHECK_FUNCS(getxattr)
AC_CHECK_FUNCS(setxattr)
AC_CHECK_FUNCS(getattrlist)
AC_CHECK_FUNCS(setattrlist)
AC_CHECK_FUNCS(lchmod)
AC_CHECK_FUNCS(lchown)
AC_CHECK_FUNCS(chflags)
AC_CHECK_FUNCS(statvfs)
AC_CHECK_FUNCS(statfs)
AC_CHECK_FUNCS(strmode)
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[#include <sys/types.h>
#include <sys/param.h>
#include <sys/mount.h>])
AC_CHECK_MEMBERS([struct statvfs.f_fstypename],,,[#include <sys/statvfs.h>])
AC_CHECK_MEMBERS([struct stat.st_flags])
AC_CHECK_SIZEOF(uid_t)
if test $ac_cv_sizeof_uid_t = "4"; then
AC_DEFINE(UID_STRING, RId32)
AC_DEFINE(UID_CAST, (uint32_t))
elif test $ac_cv_sizeof_uid_t = "8"; then
AC_DEFINE(UID_STRING, PRId64)
AC_DEFINE(UID_CAST, (uint64_t))
else
AC_ERROR(can not detect the size of your system's uid_t type)
fi
AC_CHECK_SIZEOF(gid_t)
if test $ac_cv_sizeof_gid_t = "4"; then
AC_DEFINE(GID_STRING, PRId32)
AC_DEFINE(GID_CAST, (uint32_t))
elif test $ac_cv_sizeof_gid_t = "8"; then
AC_DEFINE(GID_STRING, PRId64)
AC_DEFINE(GID_CAST, (uint64_t))
else
AC_ERROR(can not detect the size of your system's gid_t type)
fi
AC_CHECK_SIZEOF(ino_t)
if test $ac_cv_sizeof_ino_t = "4"; then
AC_DEFINE(INO_STRING, PRId32)
AC_DEFINE(INO_HEXSTRING, PRIx32)
AC_DEFINE(INO_CAST, (uint32_t))
elif test $ac_cv_sizeof_ino_t = "8"; then
AC_DEFINE(INO_STRING, PRId64)
AC_DEFINE(INO_HEXSTRING, PRIx64)
AC_DEFINE(INO_CAST, (uint64_t))
else
AC_ERROR(can not detect the size of your system's ino_t type)
fi
AC_CHECK_SIZEOF(dev_t)
if test $ac_cv_sizeof_dev_t = "4"; then
AC_DEFINE(DEV_STRING, PRId32)
AC_DEFINE(DEV_HEXSTRING, PRIx32)
AC_DEFINE(DEV_CAST, (uint32_t))
elif test $ac_cv_sizeof_dev_t = "8"; then
AC_DEFINE(DEV_STRING, PRId64)
AC_DEFINE(DEV_HEXSTRING, PRIx64)
AC_DEFINE(DEV_CAST, (uint64_t))
else
AC_ERROR(can not detect the size of your system's dev_t type)
fi
AC_CHECK_LIB(acl, acl_get_file)
dnl Check for paths
AC_PREFIX_DEFAULT(/usr/local)
AC_CHECK_FUNC([asprintf], AC_DEFINE([HAVE_ASPRINTF]))
dnl
dnl Configure libxml2.
dnl
LIBXML2_VERSION_MIN=2.6.11
have_libxml2="1"
AC_ARG_WITH([xml2-config], [ --with-xml2-config libxml2 config program],
if test "x${with_xml2_config}" = "xno" ; then
XML2_CONFIG=
else
XML2_CONFIG="${with_xml2_config}"
fi
,
XML2_CONFIG=
)
if test "x${XML2_CONFIG}" != "x" ; then
if test ! -x "${XML2_CONFIG}" ; then
AC_MSG_ERROR([Unusable or missing xml2-config: ${XML2_CONFIG}])
fi
else
AC_PATH_PROG([XML2_CONFIG], [xml2-config], , [${PATH}])
if test "x${XML2_CONFIG}" = "x" ; then
AC_MSG_ERROR([Cannot configure without xml2-config])
fi
fi
dnl Make sure the version of libxml2 found is sufficient.
AC_MSG_CHECKING([for libxml >= ${LIBXML2_VERSION_MIN}])
LIBXML2_FOUND=`2>&1 ${XML2_CONFIG} --version`
LIBXML2_MAJOR=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $1}'`
LIBXML2_MINOR=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $2}' | tr a-z " " |awk '{print $1}'`
LIBXML2_BRANCH=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $3}' | tr a-z " " |awk '{print $1}'`
if test "x${LIBXML2_BRANCH}" = "x" ; then
LIBXML2_BRANCH=0
fi
LIBXML2_MAJOR_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $1}'`
LIBXML2_MINOR_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $2}'`
LIBXML2_BRANCH_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $3}'`
if test ${LIBXML2_MAJOR} -gt ${LIBXML2_MAJOR_MIN} \
-o ${LIBXML2_MAJOR} -eq ${LIBXML2_MAJOR_MIN} \
-a ${LIBXML2_MINOR} -gt ${LIBXML2_MINOR_MIN} \
-o ${LIBXML2_MAJOR} -eq ${LIBXML2_MAJOR_MIN} \
-a ${LIBXML2_MINOR} -eq ${LIBXML2_MINOR_MIN} \
-a ${LIBXML2_BRANCH} -ge $LIBXML2_BRANCH_MIN ; then
AC_MSG_RESULT([${LIBXML2_MAJOR}.${LIBXML2_MINOR}.${LIBXML2_BRANCH}])
have_libxml2="1"
CPPFLAGS="${CPPFLAGS} `${XML2_CONFIG} --cflags`"
LIBS="${LIBS} `${XML2_CONFIG} --libs`"
else
AC_MSG_RESULT([no])
have_libxml2="0"
fi
if test "x${have_libxml2}" = "x1" ; then
dnl Final sanity check, to make sure that xmlwriter is present.
AC_CHECK_HEADER([libxml/xmlwriter.h], , [have_libxml2="0"])
fi
if test "x${have_libxml2}" = "x0" ; then
AC_MSG_ERROR([Cannot build without libxml2])
fi
dnl
dnl Configure libz.
dnl
have_libz="1"
AC_CHECK_HEADERS([zlib.h], , [have_libz="0"])
AC_CHECK_LIB([z], [deflate], , [have_libz="0"])
if test "x${have_libz}" = "x0" ; then
AC_MSG_ERROR([Cannot build without libz])
fi
dnl
dnl Configure libbz2.
dnl
have_libbz2="1"
AC_CHECK_HEADERS([bzlib.h], , [have_libbz2="0"])
AC_CHECK_LIB([bz2], [BZ2_bzCompress], , [have_libbz2="0"])
if test "x${have_libbz2}" = "x1" ; then
AC_DEFINE([HAVE_LIBBZ2])
fi
dnl
dnl Configure libpthread.
dnl
have_libpthread="1"
AC_CHECK_HEADERS([pthread.h], , [have_pthread="0"])
AC_CHECK_LIB([pthread], [pthread_mutex_lock], , [have_pthread="0"])
if test "x${have_pthread}" = "x1" ; then
AC_DEFINE([HAVE_PTHREAD])
fi
dnl
dnl Process .in files.
dnl
AC_SUBST([cfghdrs])
AC_CONFIG_HEADER([$cfghdrs])
AC_SUBST([cfgoutputs])
AC_CONFIG_FILES([$cfgoutputs])
AC_OUTPUT

2
xar/include/.cvsignore Normal file
View File

@ -0,0 +1,2 @@
config.h
xar.h

37
xar/include/config.h Normal file
View File

@ -0,0 +1,37 @@
/* include/config.h. Generated from config.h.in by configure. */
/* #undef HAVE_SYS_STATFS_H */
#define HAVE_SYS_XATTR_H 1
/* #undef HAVE_SYS_EXTATTR_H */
#define HAVE_SYS_PARAM_H 1
/* #undef HAVE_LGETXATTR */
/* #undef HAVE_LSETXATTR */
#define HAVE_GETXATTR 1
#define HAVE_SETXATTR 1
#define HAVE_GETATTRLIST 1
#define HAVE_SETATTRLIST 1
#define HAVE_CHFLAGS 1
#define HAVE_STATVFS 1
#define HAVE_STATFS 1
/* #undef HAVE_EXT2FS_EXT2_FS_H */
#define HAVE_STRUCT_STAT_ST_FLAGS 1
/* #undef HAVE_STRUCT_STATVFS_F_FSTYPENAME */
#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1
#define HAVE_SYS_ACL_H 1
/* #undef HAVE_LIBUTIL_H */
#define HAVE_LIBPTHREAD 1
#define HAVE_ASPRINTF 1
#define HAVE_LIBBZ2 1
/* #undef HAVE_LIBLZMA */
#define HAVE_LCHOWN 1
#define HAVE_LCHMOD 1
#define HAVE_STRMODE 1
#define UID_STRING RId32
#define UID_CAST (uint32_t)
#define GID_STRING PRId32
#define GID_CAST (uint32_t)
#define INO_STRING PRId64
#define INO_HEXSTRING PRIx64
#define INO_CAST (uint64_t)
#define DEV_STRING PRId32
#define DEV_HEXSTRING PRIx32
#define DEV_CAST (uint32_t)

36
xar/include/config.h.in Normal file
View File

@ -0,0 +1,36 @@
#undef HAVE_SYS_STATFS_H
#undef HAVE_SYS_XATTR_H
#undef HAVE_SYS_EXTATTR_H
#undef HAVE_SYS_PARAM_H
#undef HAVE_LGETXATTR
#undef HAVE_LSETXATTR
#undef HAVE_GETXATTR
#undef HAVE_SETXATTR
#undef HAVE_GETATTRLIST
#undef HAVE_SETATTRLIST
#undef HAVE_CHFLAGS
#undef HAVE_STATVFS
#undef HAVE_STATFS
#undef HAVE_EXT2FS_EXT2_FS_H
#undef HAVE_STRUCT_STAT_ST_FLAGS
#undef HAVE_STRUCT_STATVFS_F_FSTYPENAME
#undef HAVE_STRUCT_STATFS_F_FSTYPENAME
#undef HAVE_SYS_ACL_H
#undef HAVE_LIBUTIL_H
#undef HAVE_LIBPTHREAD
#undef HAVE_ASPRINTF
#undef HAVE_LIBBZ2
#undef HAVE_LIBLZMA
#undef HAVE_LCHOWN
#undef HAVE_LCHMOD
#undef HAVE_STRMODE
#undef UID_STRING
#undef UID_CAST
#undef GID_STRING
#undef GID_CAST
#undef INO_STRING
#undef INO_HEXSTRING
#undef INO_CAST
#undef DEV_STRING
#undef DEV_HEXSTRING
#undef DEV_CAST

268
xar/include/xar.h Normal file
View File

@ -0,0 +1,268 @@
/*
* Copyright (c) 2005 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@opendarwin.org>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_H_
#define _XAR_H_
#if __cplusplus
extern "C" {
#endif
#define XAR_VERSION "1.8dev"
#include <sys/types.h>
#include <stdint.h>
#include <sys/stat.h>
#pragma pack(4)
struct xar_header {
uint32_t magic;
uint16_t size;
uint16_t version;
uint64_t toc_length_compressed;
uint64_t toc_length_uncompressed;
uint32_t cksum_alg;
};
#pragma pack()
typedef struct xar_header xar_header_t;
#define XAR_HEADER_MAGIC 0x78617221
#define XAR_EA_FORK "ea"
/* NONE is not supported for security reasons, and may not be supported by all implementations */
#define XAR_CKSUM_NONE 0
#define XAR_CKSUM_SHA1 1
/* MD5 is not supported for security reasons, and may not be supported by all implementations */
#define XAR_CKSUM_MD5 2
#define XAR_CKSUM_SHA256 3
#define XAR_CKSUM_SHA512 4
typedef void *xar_errctx_t;
typedef const struct __xar_file_t *xar_file_t;
typedef const struct __xar_iter_t *xar_iter_t;
typedef const struct __xar_t *xar_t;
typedef const struct __xar_subdoc_t *xar_subdoc_t;
typedef const struct __xar_signature_t *xar_signature_t;
typedef struct {
char *next_out;
unsigned int avail_out;
unsigned long long total_in;
unsigned long long total_out;
void *state;
} xar_stream;
typedef int32_t (*err_handler)(int32_t severit, int32_t instance, xar_errctx_t ctx, void *usrctx);
/* the signed_data must be allocated durring the callback and will be released by the xar lib after the callback */
typedef int32_t (*xar_signer_callback)(xar_signature_t sig, void *context, uint8_t *data, uint32_t length, uint8_t **signed_data, uint32_t *signed_len);
typedef void (*xar_progress_callback)(xar_t x, xar_file_t f, size_t sizeread);
#define READ 0
#define WRITE 1
/* xar stream return codes */
#define XAR_STREAM_OK 0
#define XAR_STREAM_END 1
#define XAR_STREAM_ERR -1
/* Valid xar options & values */
#define XAR_OPT_OWNERSHIP "ownership" /* setting owner/group behavior */
#define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */
#define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */
#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */
#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */
#define XAR_OPT_VAL_NONE "none"
#define XAR_OPT_VAL_SHA1 "sha1"
#define XAR_OPT_VAL_SHA256 "sha256"
#define XAR_OPT_VAL_SHA512 "sha512"
/* MD5 is not recommended for security reasons, and may not be supported by all implementations */
#define XAR_OPT_VAL_MD5 "md5"
#define XAR_OPT_COMPRESSION "compression" /* set the file compression type */
#define XAR_OPT_COMPRESSIONARG "compression-arg" /* set the compression opts */
#define XAR_OPT_VAL_GZIP "gzip"
#define XAR_OPT_VAL_BZIP "bzip2"
#define XAR_OPT_VAL_LZMA "lzma"
#define XAR_OPT_RSIZE "rsize" /* Read io buffer size */
#define XAR_OPT_COALESCE "coalesce" /* Coalesce identical heap blocks */
#define XAR_OPT_LINKSAME "linksame" /* Hardlink identical files */
#define XAR_OPT_PROPINCLUDE "prop-include" /* File property to include */
#define XAR_OPT_PROPEXCLUDE "prop-exclude" /* File property to exclude */
#define XAR_OPT_SAVESUID "savesuid" /* Preserve setuid/setgid bits */
#define XAR_OPT_VAL_TRUE "true"
#define XAR_OPT_VAL_FALSE "false"
/* xar signing algorithms */
#define XAR_SIG_SHA1RSA 1
/* xar error handler macros */
#define XAR_SEVERITY_DEBUG 1
#define XAR_SEVERITY_INFO 2
#define XAR_SEVERITY_NORMAL 3
#define XAR_SEVERITY_WARNING 4
#define XAR_SEVERITY_NONFATAL 5
#define XAR_SEVERITY_FATAL 6
#define XAR_ERR_ARCHIVE_CREATION 1
#define XAR_ERR_ARCHIVE_EXTRACTION 2
xar_t xar_open(const char *file, int32_t flags);
xar_t xar_open_digest_verify(const char *file, int32_t flags, void *expected_toc_digest, size_t expected_toc_digest_len);
int xar_close(xar_t x);
xar_header_t xar_header_get(xar_t x);
xar_file_t xar_add(xar_t x, const char *path);
xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length);
xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info);
xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath);
xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile);
int32_t xar_extract(xar_t x, xar_file_t f);
int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path);
int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer);
int32_t xar_extract_tobuffersz(xar_t x, xar_file_t f, char **buffer, size_t *size);
int32_t xar_extract_tostream_init(xar_t x, xar_file_t f, xar_stream *stream);
int32_t xar_extract_tostream(xar_stream *stream);
int32_t xar_extract_tostream_end(xar_stream *stream);
int32_t xar_verify(xar_t x, xar_file_t f);
int32_t xar_verify_progress(xar_t x, xar_file_t f, xar_progress_callback progress);
/* To get the checksum of the table of contents use this function.
* The function returns a alloced buffer that caller must free. */
void* xar_get_toc_checksum(xar_t x, size_t* buffer_size);
/* Returns XAR_CKSUM_* that maps to the type of the checksum. */
int32_t xar_get_toc_checksum_type(xar_t x);
const char *xar_opt_get(xar_t x, const char *option);
int32_t xar_opt_set(xar_t x, const char *option, const char *value);
int32_t xar_opt_unset(xar_t x, const char *option);
int32_t xar_prop_set(xar_file_t f, const char *key, const char *value);
int32_t xar_prop_create(xar_file_t f, const char *key, const char *value);
int32_t xar_prop_get(xar_file_t f, const char *key, const char **value);
xar_iter_t xar_iter_new(void);
void xar_iter_free(xar_iter_t i);
const char *xar_prop_first(xar_file_t f, xar_iter_t i);
const char *xar_prop_next(xar_iter_t i);
void xar_prop_unset(xar_file_t f, const char *key);
xar_file_t xar_file_first(xar_t x, xar_iter_t i);
xar_file_t xar_file_next(xar_iter_t i);
const char *xar_attr_get(xar_file_t f, const char *prop, const char *key);
int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value);
const char *xar_attr_first(xar_file_t f, const char *prop, xar_iter_t i);
const char *xar_attr_next(xar_iter_t i);
xar_subdoc_t xar_subdoc_new(xar_t x, const char *name);
int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value);
int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value);
int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value);
const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key);
xar_subdoc_t xar_subdoc_first(xar_t x);
xar_subdoc_t xar_subdoc_next(xar_subdoc_t s);
const char *xar_subdoc_name(xar_subdoc_t s);
int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **, unsigned int *);
int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *, unsigned int);
void xar_subdoc_remove(xar_subdoc_t s);
/* signature api for adding various signature types */
xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context);
/* extended signatures are ignored by previous versions of xar */
xar_signature_t xar_signature_new_extended(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context);
const char *xar_signature_type(xar_signature_t s);
xar_signature_t xar_signature_first(xar_t x);
xar_signature_t xar_signature_next(xar_signature_t s);
int32_t xar_signature_add_x509certificate(xar_signature_t sig, const uint8_t *cert_data, uint32_t cert_len );
int32_t xar_signature_get_x509certificate_count(xar_signature_t sig);
int32_t xar_signature_get_x509certificate_data(xar_signature_t sig, int32_t index, const uint8_t **cert_data, uint32_t *cert_len);
uint8_t xar_signature_copy_signed_data(xar_signature_t sig, uint8_t **data, uint32_t *length, uint8_t **signed_data, uint32_t *signed_length, off_t *signed_offset);
/* Helper functions - caller must free returned memory */
char *xar_get_size(xar_t x, xar_file_t f);
char *xar_get_type(xar_t x, xar_file_t f);
char *xar_get_mode(xar_t x, xar_file_t f);
char *xar_get_owner(xar_t x, xar_file_t f);
char *xar_get_group(xar_t x, xar_file_t f);
char *xar_get_mtime(xar_t x, xar_file_t f);
/* For helping calling apps harden against hacked archives that attempt to escape their extraction roots. */
int xar_path_issane(char* path);
/* These are for xar modules and should never be needed from a calling app */
void xar_register_errhandler(xar_t x, err_handler callback, void *usrctx);
xar_t xar_err_get_archive(xar_errctx_t ctx);
xar_file_t xar_err_get_file(xar_errctx_t ctx);
const char *xar_err_get_string(xar_errctx_t ctx);
int xar_err_get_errno(xar_errctx_t ctx);
void xar_err_set_file(xar_t x, xar_file_t f);
void xar_err_set_formatted_string(xar_t x, const char *format, ...);
void xar_err_set_string(xar_t x, const char *str);
void xar_err_set_errno(xar_t x, int e);
void xar_err_new(xar_t x);
int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err);
void xar_serialize(xar_t x, const char *file);
char *xar_get_path(xar_file_t f);
off_t xar_get_heap_offset(xar_t x);
uint64_t xar_ntoh64(uint64_t num);
#if __cplusplus
}
#endif
#endif /* _XAR_H_ */

268
xar/include/xar.h.in Normal file
View File

@ -0,0 +1,268 @@
/*
* Copyright (c) 2005 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@opendarwin.org>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_H_
#define _XAR_H_
#if __cplusplus
extern "C" {
#endif
#define XAR_VERSION "@XAR_VERSION@"
#include <sys/types.h>
#include <stdint.h>
#include <sys/stat.h>
#pragma pack(4)
struct xar_header {
uint32_t magic;
uint16_t size;
uint16_t version;
uint64_t toc_length_compressed;
uint64_t toc_length_uncompressed;
uint32_t cksum_alg;
};
#pragma pack()
typedef struct xar_header xar_header_t;
#define XAR_HEADER_MAGIC 0x78617221
#define XAR_EA_FORK "ea"
/* NONE is not supported for security reasons, and may not be supported by all implementations */
#define XAR_CKSUM_NONE 0
#define XAR_CKSUM_SHA1 1
/* MD5 is not supported for security reasons, and may not be supported by all implementations */
#define XAR_CKSUM_MD5 2
#define XAR_CKSUM_SHA256 3
#define XAR_CKSUM_SHA512 4
typedef void *xar_errctx_t;
typedef const struct __xar_file_t *xar_file_t;
typedef const struct __xar_iter_t *xar_iter_t;
typedef const struct __xar_t *xar_t;
typedef const struct __xar_subdoc_t *xar_subdoc_t;
typedef const struct __xar_signature_t *xar_signature_t;
typedef struct {
char *next_out;
unsigned int avail_out;
unsigned long long total_in;
unsigned long long total_out;
void *state;
} xar_stream;
typedef int32_t (*err_handler)(int32_t severit, int32_t instance, xar_errctx_t ctx, void *usrctx);
/* the signed_data must be allocated durring the callback and will be released by the xar lib after the callback */
typedef int32_t (*xar_signer_callback)(xar_signature_t sig, void *context, uint8_t *data, uint32_t length, uint8_t **signed_data, uint32_t *signed_len);
typedef void (*xar_progress_callback)(xar_t x, xar_file_t f, size_t sizeread);
#define READ 0
#define WRITE 1
/* xar stream return codes */
#define XAR_STREAM_OK 0
#define XAR_STREAM_END 1
#define XAR_STREAM_ERR -1
/* Valid xar options & values */
#define XAR_OPT_OWNERSHIP "ownership" /* setting owner/group behavior */
#define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */
#define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */
#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */
#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */
#define XAR_OPT_VAL_NONE "none"
#define XAR_OPT_VAL_SHA1 "sha1"
#define XAR_OPT_VAL_SHA256 "sha256"
#define XAR_OPT_VAL_SHA512 "sha512"
/* MD5 is not recommended for security reasons, and may not be supported by all implementations */
#define XAR_OPT_VAL_MD5 "md5"
#define XAR_OPT_COMPRESSION "compression" /* set the file compression type */
#define XAR_OPT_COMPRESSIONARG "compression-arg" /* set the compression opts */
#define XAR_OPT_VAL_GZIP "gzip"
#define XAR_OPT_VAL_BZIP "bzip2"
#define XAR_OPT_VAL_LZMA "lzma"
#define XAR_OPT_RSIZE "rsize" /* Read io buffer size */
#define XAR_OPT_COALESCE "coalesce" /* Coalesce identical heap blocks */
#define XAR_OPT_LINKSAME "linksame" /* Hardlink identical files */
#define XAR_OPT_PROPINCLUDE "prop-include" /* File property to include */
#define XAR_OPT_PROPEXCLUDE "prop-exclude" /* File property to exclude */
#define XAR_OPT_SAVESUID "savesuid" /* Preserve setuid/setgid bits */
#define XAR_OPT_VAL_TRUE "true"
#define XAR_OPT_VAL_FALSE "false"
/* xar signing algorithms */
#define XAR_SIG_SHA1RSA 1
/* xar error handler macros */
#define XAR_SEVERITY_DEBUG 1
#define XAR_SEVERITY_INFO 2
#define XAR_SEVERITY_NORMAL 3
#define XAR_SEVERITY_WARNING 4
#define XAR_SEVERITY_NONFATAL 5
#define XAR_SEVERITY_FATAL 6
#define XAR_ERR_ARCHIVE_CREATION 1
#define XAR_ERR_ARCHIVE_EXTRACTION 2
xar_t xar_open(const char *file, int32_t flags);
xar_t xar_open_digest_verify(const char *file, int32_t flags, void *expected_toc_digest, size_t expected_toc_digest_len);
int xar_close(xar_t x);
xar_header_t xar_header_get(xar_t x);
xar_file_t xar_add(xar_t x, const char *path);
xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length);
xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info);
xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath);
xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile);
int32_t xar_extract(xar_t x, xar_file_t f);
int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path);
int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer);
int32_t xar_extract_tobuffersz(xar_t x, xar_file_t f, char **buffer, size_t *size);
int32_t xar_extract_tostream_init(xar_t x, xar_file_t f, xar_stream *stream);
int32_t xar_extract_tostream(xar_stream *stream);
int32_t xar_extract_tostream_end(xar_stream *stream);
int32_t xar_verify(xar_t x, xar_file_t f);
int32_t xar_verify_progress(xar_t x, xar_file_t f, xar_progress_callback progress);
/* To get the checksum of the table of contents use this function.
* The function returns a alloced buffer that caller must free. */
void* xar_get_toc_checksum(xar_t x, size_t* buffer_size);
/* Returns XAR_CKSUM_* that maps to the type of the checksum. */
int32_t xar_get_toc_checksum_type(xar_t x);
const char *xar_opt_get(xar_t x, const char *option);
int32_t xar_opt_set(xar_t x, const char *option, const char *value);
int32_t xar_opt_unset(xar_t x, const char *option);
int32_t xar_prop_set(xar_file_t f, const char *key, const char *value);
int32_t xar_prop_create(xar_file_t f, const char *key, const char *value);
int32_t xar_prop_get(xar_file_t f, const char *key, const char **value);
xar_iter_t xar_iter_new(void);
void xar_iter_free(xar_iter_t i);
const char *xar_prop_first(xar_file_t f, xar_iter_t i);
const char *xar_prop_next(xar_iter_t i);
void xar_prop_unset(xar_file_t f, const char *key);
xar_file_t xar_file_first(xar_t x, xar_iter_t i);
xar_file_t xar_file_next(xar_iter_t i);
const char *xar_attr_get(xar_file_t f, const char *prop, const char *key);
int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value);
const char *xar_attr_first(xar_file_t f, const char *prop, xar_iter_t i);
const char *xar_attr_next(xar_iter_t i);
xar_subdoc_t xar_subdoc_new(xar_t x, const char *name);
int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value);
int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value);
int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value);
const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key);
xar_subdoc_t xar_subdoc_first(xar_t x);
xar_subdoc_t xar_subdoc_next(xar_subdoc_t s);
const char *xar_subdoc_name(xar_subdoc_t s);
int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **, unsigned int *);
int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *, unsigned int);
void xar_subdoc_remove(xar_subdoc_t s);
/* signature api for adding various signature types */
xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context);
/* extended signatures are ignored by previous versions of xar */
xar_signature_t xar_signature_new_extended(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context);
const char *xar_signature_type(xar_signature_t s);
xar_signature_t xar_signature_first(xar_t x);
xar_signature_t xar_signature_next(xar_signature_t s);
int32_t xar_signature_add_x509certificate(xar_signature_t sig, const uint8_t *cert_data, uint32_t cert_len );
int32_t xar_signature_get_x509certificate_count(xar_signature_t sig);
int32_t xar_signature_get_x509certificate_data(xar_signature_t sig, int32_t index, const uint8_t **cert_data, uint32_t *cert_len);
uint8_t xar_signature_copy_signed_data(xar_signature_t sig, uint8_t **data, uint32_t *length, uint8_t **signed_data, uint32_t *signed_length, off_t *signed_offset);
/* Helper functions - caller must free returned memory */
char *xar_get_size(xar_t x, xar_file_t f);
char *xar_get_type(xar_t x, xar_file_t f);
char *xar_get_mode(xar_t x, xar_file_t f);
char *xar_get_owner(xar_t x, xar_file_t f);
char *xar_get_group(xar_t x, xar_file_t f);
char *xar_get_mtime(xar_t x, xar_file_t f);
/* For helping calling apps harden against hacked archives that attempt to escape their extraction roots. */
int xar_path_issane(char* path);
/* These are for xar modules and should never be needed from a calling app */
void xar_register_errhandler(xar_t x, err_handler callback, void *usrctx);
xar_t xar_err_get_archive(xar_errctx_t ctx);
xar_file_t xar_err_get_file(xar_errctx_t ctx);
const char *xar_err_get_string(xar_errctx_t ctx);
int xar_err_get_errno(xar_errctx_t ctx);
void xar_err_set_file(xar_t x, xar_file_t f);
void xar_err_set_formatted_string(xar_t x, const char *format, ...);
void xar_err_set_string(xar_t x, const char *str);
void xar_err_set_errno(xar_t x, int e);
void xar_err_new(xar_t x);
int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err);
void xar_serialize(xar_t x, const char *file);
char *xar_get_path(xar_file_t f);
off_t xar_get_heap_offset(xar_t x);
uint64_t xar_ntoh64(uint64_t num);
#if __cplusplus
}
#endif
#endif /* _XAR_H_ */

250
xar/install-sh Normal file
View File

@ -0,0 +1,250 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

4
xar/lib/.cvsignore Normal file
View File

@ -0,0 +1,4 @@
Makefile.inc
librxar.*
libxar.*
*.d

205
xar/lib/Makefile.inc Normal file
View File

@ -0,0 +1,205 @@
#
# File lists.
#
# Internal headers.
LIBXAR_IINCS := asprintf.h
LIBXAR_IINCS := $(patsubst %, include/%, $(LIBXAR_IINCS))
LIBXAR_IINCS += include/config.h
# Headers.
LIBXAR_INCS :=
LIBXAR_INCS := $(patsubst %, include/%, $(LIBXAR_INCS))
LIBXAR_INCS += include/xar.h
# Sources.
LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c ea.c err.c
LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c lzmaxar.c linuxattr.c hash.c
LIBXAR_SRCS += signature.c stat.c subdoc.c util.c zxar.c script.c macho.c
LIBXAR_SRCS := $(patsubst %, lib/%, $(LIBXAR_SRCS))
# Libraries. librxar is created such that it's possible to run xar without
# first installing libxar.
LIBXAR_LANAME := libxar.la
LIBXAR_ANAME := libxar.a
ifeq (elf, macho)
LIBRXAR_SNAME := librxar.so.1
LIBRXAR_LNAME := librxar.so
LIBRXAR_L := lib/$(LIBRXAR_LNAME)
LIBXAR_SNAME := libxar.so.1
LIBXAR_LNAME := libxar.so
LIBXAR_L := lib/$(LIBXAR_LNAME)
endif
ifeq (macho, macho)
LIBRXAR_SNAME := librxar.1.dylib
LIBRXAR_LNAME := librxar.dylib
LIBRXAR_L := lib/$(LIBRXAR_LNAME)
LIBXAR_SNAME := libxar.1.dylib
LIBXAR_LNAME := libxar.dylib
LIBXAR_L := lib/$(LIBXAR_LNAME)
endif
ifeq (aout, macho)
LIBRXAR_SNAME := librxar.so.1.0
LIBRXAR_LNAME :=
LIBRXAR_L :=
LIBXAR_SNAME := libxar.so.1.0
LIBXAR_LNAME :=
LIBXAR_L :=
endif
LIBXAR_LA := lib/$(LIBXAR_LANAME)
LIBXAR_A := lib/$(LIBXAR_ANAME)
LIBRXAR_S := lib/$(LIBRXAR_SNAME)
LIBXAR_S := lib/$(LIBXAR_SNAME)
#
# Include generated dependency files.
#
-include $(LIBXAR_SRCS:%.c=%.d)
LDFLAGS := -Llib $(LDFLAGS)
#
# User make'ables.
#
lib_all : lib_shared lib_static $(LIBXAR_LA)
ifeq (yes, yes)
lib_shared : $(LIBRXAR_S) $(LIBXAR_S)
else
lib_shared :
endif
ifeq (yes, yes)
lib_static : $(LIBXAR_A)
else
lib_static :
endif
lib_install : lib_shared lib_static
.././install-sh -c -d $(DESTDIR)$(INCLUDEDIR)/xar
.././install-sh -c -m 0644 $(LIBXAR_INCS) $(DESTDIR)$(INCLUDEDIR)/xar
.././install-sh -c -d $(DESTDIR)$(LIBDIR)
ifeq (yes, yes)
.././install-sh -c -m 0755 $(LIBXAR_S) $(DESTDIR)$(LIBDIR)
ifneq ($(words "" $(LIBXAR_LNAME)), 1)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
ln -s $(LIBXAR_SNAME) $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
endif
endif
ifeq (yes, yes)
.././install-sh -c -m 0644 $(LIBXAR_A) $(DESTDIR)$(LIBDIR)
endif
.././install-sh -c -m 0644 $(LIBXAR_LA) $(DESTDIR)$(LIBDIR)
lib_uninstall :
rm -rf $(DESTDIR)$(INCLUDEDIR)/xar
ifeq (yes, yes)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_SNAME)
ifneq ($(words "" $(LIBXAR_LNAME)), 1)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
endif
endif
ifeq (yes, yes)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_ANAME)
endif
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LANAME)
lib_clean :
rm -f $(LIBRXAR_S) $(LIBRXAR_L)
rm -f $(LIBXAR_S) $(LIBXAR_L)
rm -f $(LIBXAR_A) $(LIBXAR_LA)
@rm -f lib/.libs/$(LIBXAR_LNAME)
@rm -f lib/.libs/$(LIBXAR_ANAME)
@-rmdir lib/.libs
rm -f $(LIBXAR_SRCS:%.c=%.o)
rm -f $(LIBXAR_SRCS:%.c=%.d)
rm -f $(LIBXAR_SRCS:%.c=%.static.o)
rm -f $(LIBXAR_SRCS:%.c=%.static.d)
lib_distclean :
#
# Various flags.
#
CPPFLAGS := -Iinclude $(CPPFLAGS)
CPPFLAGS := -Iinclude $(CPPFLAGS)
#
# Build rules.
#
# librxar is a version of the xar library that is usable without first
# installing libxar.
$(LIBRXAR_S) : $(LIBXAR_SRCS:%.c=%.o)
@mkdir -p $(@D)
ifeq (elf, macho)
$(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
endif
ifeq (macho, macho)
$(CC) -dynamiclib -compatibility_version 1 -current_version 1 -install_name /Users/ariel/LinuxHome/code/darling/src/xar/xar/$(LIBRXAR_S) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
endif
ifeq (aout, macho)
$(CC) -shared -o $@ $+
endif
ifneq ($(words "" $(LIBRXAR_L)), 1)
rm -f $(LIBRXAR_L)
ln -s $(LIBRXAR_SNAME) $(LIBRXAR_L)
endif
$(LIBXAR_S) : $(LIBXAR_SRCS:%.c=%.o)
@mkdir -p $(@D)
ifeq (elf, macho)
$(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
endif
ifeq (macho, macho)
$(CC) -dynamiclib -compatibility_version 1 -current_version 1 -install_name $(LIBDIR)/$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
endif
ifeq (aout, macho)
$(CC) -shared -o $@ $+
endif
ifneq ($(words "" $(LIBXAR_L)), 1)
rm -f $(LIBXAR_L)
ln -s $(LIBXAR_SNAME) $(LIBXAR_L)
endif
ifeq (yes, yes)
LT_LIBXAR_SNAME := $(LIBXAR_SNAME)
LT_LIBXAR_LNAME := $(LIBXAR_LNAME)
else
LT_LIBXAR_SNAME :=
LT_LIBXAR_LNAME :=
endif
ifeq (yes, yes)
LT_LIBXAR_ANAME := $(LIBXAR_ANAME)
else
LT_LIBXAR_ANAME :=
endif
$(LIBXAR_LA) : $(LIBXAR_LA).in
@mkdir -p lib/.libs
ifeq (yes, yes)
@ln -sf ../$(LIBXAR_LNAME) lib/.libs/$(LIBXAR_LNAME)
endif
ifeq (yes, yes)
@ln -sf ../$(LIBXAR_ANAME) lib/.libs/$(LIBXAR_ANAME)
endif
sed -e s/@LIBXAR_SNAME@/$(LT_LIBXAR_SNAME)/ -e s/@LIBXAR_LNAME@/$(LT_LIBXAR_LNAME)/ -e s/@LIBXAR_ANAME@/$(LT_LIBXAR_ANAME)/ < $< > $@
$(LIBXAR_A) : $(LIBXAR_SRCS:%.c=%.static.o)
@mkdir -p $(@D)
$(AR) cvr $@ $+
$(RANLIB) $@
lib/%.o : lib/%.c
@mkdir -p $(@D)
$(CC) $(S_CFLAGS) $(CPPFLAGS) -c $< -o $@
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
lib/%.static.o : lib/%.c
@mkdir -p $(@D)
$(CC) $(A_CFLAGS) $(CPPFLAGS) -c $< -o $@
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"

205
xar/lib/Makefile.inc.in Normal file
View File

@ -0,0 +1,205 @@
#
# File lists.
#
# Internal headers.
LIBXAR_IINCS := asprintf.h
LIBXAR_IINCS := $(patsubst %, @srcroot@include/%, $(LIBXAR_IINCS))
LIBXAR_IINCS += @objroot@include/config.h
# Headers.
LIBXAR_INCS :=
LIBXAR_INCS := $(patsubst %, @srcroot@include/%, $(LIBXAR_INCS))
LIBXAR_INCS += @objroot@include/xar.h
# Sources.
LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c ea.c err.c
LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c lzmaxar.c linuxattr.c hash.c
LIBXAR_SRCS += signature.c stat.c subdoc.c util.c zxar.c script.c macho.c
LIBXAR_SRCS := $(patsubst %, @srcroot@lib/%, $(LIBXAR_SRCS))
# Libraries. librxar is created such that it's possible to run xar without
# first installing libxar.
LIBXAR_LANAME := libxar.la
LIBXAR_ANAME := libxar.a
ifeq (elf, @abi@)
LIBRXAR_SNAME := librxar.so.@LIB_REV@
LIBRXAR_LNAME := librxar.so
LIBRXAR_L := @objroot@lib/$(LIBRXAR_LNAME)
LIBXAR_SNAME := libxar.so.@LIB_REV@
LIBXAR_LNAME := libxar.so
LIBXAR_L := @objroot@lib/$(LIBXAR_LNAME)
endif
ifeq (macho, @abi@)
LIBRXAR_SNAME := librxar.@LIB_REV@.dylib
LIBRXAR_LNAME := librxar.dylib
LIBRXAR_L := @objroot@lib/$(LIBRXAR_LNAME)
LIBXAR_SNAME := libxar.@LIB_REV@.dylib
LIBXAR_LNAME := libxar.dylib
LIBXAR_L := @objroot@lib/$(LIBXAR_LNAME)
endif
ifeq (aout, @abi@)
LIBRXAR_SNAME := librxar.so.@LIB_REV@.0
LIBRXAR_LNAME :=
LIBRXAR_L :=
LIBXAR_SNAME := libxar.so.@LIB_REV@.0
LIBXAR_LNAME :=
LIBXAR_L :=
endif
LIBXAR_LA := @objroot@lib/$(LIBXAR_LANAME)
LIBXAR_A := @objroot@lib/$(LIBXAR_ANAME)
LIBRXAR_S := @objroot@lib/$(LIBRXAR_SNAME)
LIBXAR_S := @objroot@lib/$(LIBXAR_SNAME)
#
# Include generated dependency files.
#
-include $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.d)
LDFLAGS := -L@objroot@lib $(LDFLAGS)
#
# User make'ables.
#
lib_all : lib_shared lib_static $(LIBXAR_LA)
ifeq (yes, @shared@)
lib_shared : $(LIBRXAR_S) $(LIBXAR_S)
else
lib_shared :
endif
ifeq (yes, @static@)
lib_static : $(LIBXAR_A)
else
lib_static :
endif
lib_install : lib_shared lib_static
@INSTALL@ -d $(DESTDIR)$(INCLUDEDIR)/xar
@INSTALL@ -m 0644 $(LIBXAR_INCS) $(DESTDIR)$(INCLUDEDIR)/xar
@INSTALL@ -d $(DESTDIR)$(LIBDIR)
ifeq (yes, @shared@)
@INSTALL@ -m 0755 $(LIBXAR_S) $(DESTDIR)$(LIBDIR)
ifneq ($(words "" $(LIBXAR_LNAME)), 1)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
ln -s $(LIBXAR_SNAME) $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
endif
endif
ifeq (yes, @static@)
@INSTALL@ -m 0644 $(LIBXAR_A) $(DESTDIR)$(LIBDIR)
endif
@INSTALL@ -m 0644 $(LIBXAR_LA) $(DESTDIR)$(LIBDIR)
lib_uninstall :
rm -rf $(DESTDIR)$(INCLUDEDIR)/xar
ifeq (yes, @shared@)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_SNAME)
ifneq ($(words "" $(LIBXAR_LNAME)), 1)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME)
endif
endif
ifeq (yes, @static@)
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_ANAME)
endif
rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LANAME)
lib_clean :
rm -f $(LIBRXAR_S) $(LIBRXAR_L)
rm -f $(LIBXAR_S) $(LIBXAR_L)
rm -f $(LIBXAR_A) $(LIBXAR_LA)
@rm -f @objroot@lib/.libs/$(LIBXAR_LNAME)
@rm -f @objroot@lib/.libs/$(LIBXAR_ANAME)
@-rmdir @objroot@lib/.libs
rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.o)
rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.d)
rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.static.o)
rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.static.d)
lib_distclean :
#
# Various flags.
#
CPPFLAGS := -I@objroot@include $(CPPFLAGS)
CPPFLAGS := -I@srcroot@include $(CPPFLAGS)
#
# Build rules.
#
# librxar is a version of the xar library that is usable without first
# installing libxar.
$(LIBRXAR_S) : $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.o)
@mkdir -p $(@D)
ifeq (elf, @abi@)
$(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@
endif
ifeq (macho, @abi@)
$(CC) -dynamiclib -compatibility_version @LIB_REV@ -current_version @LIB_REV@ -install_name @abs_objroot@$(LIBRXAR_S) -o $@ $+ $(LDFLAGS) @LIBS@
endif
ifeq (aout, @abi@)
$(CC) -shared -o $@ $+
endif
ifneq ($(words "" $(LIBRXAR_L)), 1)
rm -f $(LIBRXAR_L)
ln -s $(LIBRXAR_SNAME) $(LIBRXAR_L)
endif
$(LIBXAR_S) : $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.o)
@mkdir -p $(@D)
ifeq (elf, @abi@)
$(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@
endif
ifeq (macho, @abi@)
$(CC) -dynamiclib -compatibility_version @LIB_REV@ -current_version @LIB_REV@ -install_name $(LIBDIR)/$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@
endif
ifeq (aout, @abi@)
$(CC) -shared -o $@ $+
endif
ifneq ($(words "" $(LIBXAR_L)), 1)
rm -f $(LIBXAR_L)
ln -s $(LIBXAR_SNAME) $(LIBXAR_L)
endif
ifeq (yes, @shared@)
LT_LIBXAR_SNAME := $(LIBXAR_SNAME)
LT_LIBXAR_LNAME := $(LIBXAR_LNAME)
else
LT_LIBXAR_SNAME :=
LT_LIBXAR_LNAME :=
endif
ifeq (yes, @static@)
LT_LIBXAR_ANAME := $(LIBXAR_ANAME)
else
LT_LIBXAR_ANAME :=
endif
$(LIBXAR_LA) : $(LIBXAR_LA).in
@mkdir -p @objroot@lib/.libs
ifeq (yes, @shared@)
@ln -sf ../$(LIBXAR_LNAME) @objroot@lib/.libs/$(LIBXAR_LNAME)
endif
ifeq (yes, @static@)
@ln -sf ../$(LIBXAR_ANAME) @objroot@lib/.libs/$(LIBXAR_ANAME)
endif
sed -e s/@LIBXAR_SNAME@/$(LT_LIBXAR_SNAME)/ -e s/@LIBXAR_LNAME@/$(LT_LIBXAR_LNAME)/ -e s/@LIBXAR_ANAME@/$(LT_LIBXAR_ANAME)/ < $< > $@
$(LIBXAR_A) : $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.static.o)
@mkdir -p $(@D)
$(AR) cvr $@ $+
$(RANLIB) $@
@objroot@lib/%.o : @srcroot@lib/%.c
@mkdir -p $(@D)
$(CC) $(S_CFLAGS) $(CPPFLAGS) -c $< -o $@
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
@objroot@lib/%.static.o : @srcroot@lib/%.c
@mkdir -p $(@D)
$(CC) $(A_CFLAGS) $(CPPFLAGS) -c $< -o $@
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"

103
xar/lib/appledouble.h Normal file
View File

@ -0,0 +1,103 @@
/* Information pulled from:
* "AppleSingle/AppleDouble Formats for Foreign Files Developer's Note"
* (c) Apple Computer 1990
* File assembled by Rob Braun (bbraun@synack.net)
*/
#ifndef __APPLEDOUBLE__
#define __APPLEDOUBLE__
#include <sys/types.h>
#include <stdint.h>
/* Structure of an AppleSingle file:
* ----------------------
* | AppleSingleHeader |
* |--------------------|
* | ASH.entries # of |
* | AppleSingleEntry |
* | Descriptors |
* | 1 |
* | . |
* | . |
* | n |
* |--------------------|
* | Datablock 1 |
* |--------------------|
* | Datablock 2 |
* |--------------------|
* | Datablock n |
* ----------------------
*/
struct AppleSingleHeader {
uint32_t magic; /* Magic Number (0x00051600 for AS) */
uint32_t version; /* Version #. 0x00020000 */
char filler[16]; /* All zeros */
uint16_t entries; /* Number of entries in the file */
};
#define XAR_ASH_SIZE 26 /* sizeof(struct AppleSingleHeader) will be wrong
* due to padding. */
#define APPLESINGLE_MAGIC 0x00051600
#define APPLEDOUBLE_MAGIC 0x00051607
#define APPLESINGLE_VERSION 0x00020000
#define APPLEDOUBLE_VERSION 0x00020000
struct AppleSingleEntry {
uint32_t entry_id; /* What the entry is. See defines below */
uint32_t offset; /* offset of data, offset beginning of file */
uint32_t length; /* length of data. can be 0 */
};
/* Valid entry_id values */
/* Entries 1, 3, and 8 are typically created for all files.
* Macintosh Icon entries are rare, since those are typically in the resource
* fork.
*/
#define AS_ID_DATA 1 /* Data fork */
#define AS_ID_RESOURCE 2 /* Resource fork */
#define AS_ID_NAME 3 /* Name of the file */
#define AS_ID_COMMENT 4 /* Standard Macintosh comment */
#define AS_ID_BWICON 5 /* Standard Macintosh B&W icon */
#define AS_ID_COLORICON 6 /* Standard Macintosh Color icon */
/* There is no 7 */
#define AS_ID_DATES 8 /* File creation date, modification date, etc. */
#define AS_ID_FINDER 9 /* Finder Information */
#define AS_ID_MAC 10 /* Macintosh File information, attributes, etc. */
#define AS_ID_PRODOS 11 /* ProDOS file information */
#define AS_ID_MSDOS 12 /* MS-DOS file information */
#define AS_ID_SHORTNAME 13 /* AFP short name */
#define AS_ID_AFPINFO 14 /* AFP file information */
#define AS_ID_AFPDIR 15 /* AFP directory id */
/* 1-0x7FFFFFFF are reserved by Apple */
/* File Dates are stored as the # of seconds before or after
* 12am Jan 1, 2000 GMT. The default value is 0x80000000.
*/
struct MacTimes {
uint32_t creation;
uint32_t modification;
uint32_t backup;
uint32_t access;
};
/* Finder Information is two 16 byte quantities.
* Newly created files have all 0's in both entries.
*/
/* Macintosh File Info entry (10) a 32 bit bitmask. */
/* Entries can be placed in any order, although Apple recommends:
* Place the data block (1) last.
* Finder Info, File Dates Info, and Macintosh File Info first.
* Allocate resource for entries in 4K blocks.
*/
/* AppleDouble files are simply AppleSingle files without the data fork.
* The magic number is different as a read optimization.
*/
#endif /* __APPLEDOUBLE__ */

1739
xar/lib/archive.c Normal file

File diff suppressed because it is too large Load Diff

109
xar/lib/archive.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_ARCHIVE_H_
#define _XAR_ARCHIVE_H_
#include <zlib.h>
#include <libxml/hash.h>
#ifdef __APPLE__
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
#else
#include <openssl/evp.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include "xar.h"
#include "filetree.h"
#include "hash.h"
typedef int (*read_callback)(xar_t, xar_file_t, void *, size_t, void *context);
typedef int (*write_callback)(xar_t, xar_file_t, void *, size_t, void *context);
struct errctx {
const char *str;
int saved_errno;
xar_file_t file;
void *usrctx;
xar_t x;
};
struct __xar_t {
xar_prop_t props;
xar_attr_t attrs; /* archive options, such as rsize */
const char *prefix;
const char *ns;
const char *filler1;
const char *filler2;
xar_file_t files; /* file forest */
const char *filename; /* name of the archive we are operating on */
char *dirname; /* directory of the archive, used in creation */
int fd; /* open file descriptor for the archive */
int heap_fd; /* fd for tmp heap archive, used in creation */
off_t heap_offset; /* current offset within the heap */
off_t heap_len; /* current length of the heap */
xar_header_t header; /* header of the xar archive */
void *readbuf; /* buffer for reading/writing compressed toc */
size_t readbuf_len; /* length of readbuf */
size_t offset; /* offset into readbuf for keeping track
* between callbacks. */
size_t toc_count; /* current bytes read of the toc */
z_stream zs; /* gz state for compressing/decompressing toc */
char *path_prefix; /* used for distinguishing absolute paths */
err_handler ercallback; /* callback for errors/warnings */
struct errctx errctx; /* error callback context */
xar_subdoc_t subdocs; /* linked list of subdocs */
xar_signature_t signatures; /* linked list of signatures */
int32_t (*attrcopy_to_heap)(xar_t, xar_file_t, xar_prop_t, read_callback, void *);
int32_t (*attrcopy_from_heap)(xar_t, xar_file_t, xar_prop_t, write_callback, void *);
int32_t (*heap_to_archive)(xar_t);
uint64_t last_fileid; /* unique fileid's in the archive */
xmlHashTablePtr ino_hash; /* Hash for looking up hardlinked files (add)*/
xmlHashTablePtr link_hash; /* Hash for looking up hardlinked files (extract)*/
xmlHashTablePtr csum_hash; /* Hash for looking up checksums of files */
xar_hash_t toc_hash_ctx;
int toc_hash_size; /* size of toc hash that was copied during archive open */
void *toc_hash; /* copy of the toc hash copied during archive open */
int skipwarn;
struct stat sbcache;
};
#define XAR(x) ((struct __xar_t *)(x))
#endif /* _XAR_ARCHIVE_H_ */

148
xar/lib/arcmod.c Normal file
View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "arcmod.h"
#include "archive.h"
#include "stat.h"
#include "data.h"
#include "linuxattr.h"
#include "fbsdattr.h"
#include "darwinattr.h"
#include "ext2.h"
#include "xar.h"
#include <string.h>
struct arcmod xar_arcmods[] = {
{ xar_stat_archive, xar_stat_extract }, /* must be first */
{ xar_linuxattr_archive, xar_linuxattr_extract },
{ xar_fbsdattr_archive, xar_fbsdattr_extract },
{ xar_darwinattr_archive, xar_darwinattr_extract },
{ xar_ext2attr_archive, xar_ext2attr_extract },
{ xar_data_archive, xar_data_extract },
/* Add new modules here */
{ NULL, xar_set_perm },
{ NULL, xar_flags_extract }
};
/* xar_arcmod_archive
* x: archive to add the file to
* f: node representing the file
* file: the filesystem path to the file
* Returns: 0 on success
* Summary: This is the entry point to actual file archival.
*/
int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) {
int i;
int32_t ret;
for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) {
if( xar_arcmods[i].archive ) {
ret = xar_arcmods[i].archive(x, f, file, buffer, len);
if( ret < 0 ) {
return ret;
}
if( ret > 0 ) {
return 0;
}
}
}
return 0;
}
/* xar_arcmod_extract
* x: archive to extract the file from
* f: node representing the file
* file: the filesystem path to the target file
* Returns: 0 on success
* Summary: This is the entry point to actual file archival.
*/
int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
int i;
int32_t ret;
for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) {
if( xar_arcmods[i].extract ) {
ret = xar_arcmods[i].extract(x, f, file, buffer, len);
if( ret < 0 ) {
// If the extract failed we have corrupt asset on disk, remove, well try.
unlink(file);
return ret;
}
if( ret > 0 ) {
return 0;
}
}
}
return 0;
}
int32_t xar_arcmod_verify(xar_t x, xar_file_t f, xar_progress_callback p){
return xar_data_verify(x,f, p);
}
/* xar_check_prop
* x: xar archive
* name: name of property to check
* Description: If XAR_OPT_PROPINCLUDE is set at all, only properties
* specified for inclusion will be added.
* If XAR_OPT_PROPINCLUDE is not set, and XAR_OPT_PROPEXCLUDE is set,
* properies specified by XAR_OPT_PROPEXCLUDE will be omitted.
* Returns: 0 for not to include, 1 for include.
*/
int32_t xar_check_prop(xar_t x, const char *name) {
xar_attr_t i;
char includeset = 0;
for(i = XAR(x)->attrs; i; i = XAR_ATTR(i)->next) {
if( strcmp(XAR_ATTR(i)->key, XAR_OPT_PROPINCLUDE) == 0 ) {
if( strcmp(XAR_ATTR(i)->value, name) == 0 )
return 1;
includeset = 1;
}
}
if( includeset )
return 0;
for(i = XAR(x)->attrs; i; i = XAR_ATTR(i)->next) {
if( strcmp(XAR_ATTR(i)->key, XAR_OPT_PROPEXCLUDE) == 0 ) {
if( strcmp(XAR_ATTR(i)->value, name) == 0 )
return 0;
}
}
return 1;
}

59
xar/lib/arcmod.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_ARCMOD_H_
#define _XAR_ARCMOD_H_
#include "xar.h"
#include "filetree.h"
typedef int32_t (*arcmod_archive)(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len);
typedef int32_t (*arcmod_extract)(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len);
struct arcmod {
arcmod_archive archive;
arcmod_extract extract;
};
int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len);
int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len);
int32_t xar_arcmod_verify(xar_t x, xar_file_t f, xar_progress_callback p);
int32_t xar_check_prop(xar_t x, const char *name);
#endif /* _XAR_ARCMOD_H_ */

92
xar/lib/asprintf.h Normal file
View File

@ -0,0 +1,92 @@
//==============================================================================
//
// Copyright (C) 2005 Jason Evans <jasone@canonware.com>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice(s),
// this list of conditions and the following disclaimer unmodified other than
// the allowable addition of one or more copyright notices.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice(s), this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) `AS IS' AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
// NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//==============================================================================
//
// Emulate vasprintf() and asprintf().
//
//==============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
static inline int
vasprintf(char **rResult, const char *aFormat, va_list aAp)
{
int rVal;
char *result;
va_list ap;
#define XarAsprintfStartLen 16
result = (char *) malloc(XarAsprintfStartLen);
if (result == NULL)
{
rVal = -1;
goto RETURN;
}
va_copy(ap, aAp);
rVal = vsnprintf(result, XarAsprintfStartLen, aFormat, ap);
va_end(ap);
if (rVal == -1)
{
goto RETURN;
}
else if (rVal >= XarAsprintfStartLen)
{
free(result);
result = (char *) malloc(rVal + 1);
if (result == NULL)
{
rVal = -1;
goto RETURN;
}
va_copy(ap, aAp);
rVal = vsnprintf(result, rVal + 1, aFormat, aAp);
va_end(ap);
}
*rResult = result;
RETURN:
#undef XarAsprintfStartLen
return rVal;
}
static int
asprintf(char **rResult, const char *aFormat, ...)
{
int rVal;
va_list ap;
va_start(ap, aFormat);
rVal = vasprintf(rResult, aFormat, ap);
va_end(ap);
return rVal;
}

217
xar/lib/b64.c Normal file
View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2004 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 1-Oct-2004
* DRI: Rob Braun <bbraun@synack.net>
*/
#include <stdlib.h>
#include <string.h>
#ifdef _BTEST_
int main(int argc, char* argv[]) {
unsigned char* enc = benc(argv[1], strlen(argv[1]));
printf("%s", enc);
printf("%s\n", bdec(enc, strlen(enc)));
}
#endif
/*
* The code below derives from "Secure Programming Cookbook for C and
* C++"* and adapted by Kogule, Ryo (kogule@opendarwin.org).
*
* *John Viega and Matt Messier, O'Reilly, 2003
* http://www.secureprogramming.com/
*
* Readability improvements by Luke Bellandi, 2007 (luke@apple.com)
*/
typedef enum _B64CommandCodes {
B64_NullTerminator = -3,
B64_PaddingCharacter = -2,
B64_IgnorableCharacter = -1
} B64CommandCodes;
static char b64revtb[256] = {
-3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*0-15*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16-31*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /*32-47*/
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, /*48-63*/
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /*64-79*/
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /*80-95*/
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /*96-111*/
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /*112-127*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128-143*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*144-159*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*160-175*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*176-191*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*192-207*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*208-223*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*224-239*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /*240-255*/
};
typedef enum _B64CodecErrorCodes {
B64_noError = 0,
B64_decodeError = 1,
B64_bufferOverrun = 2
} B64CodecErrorCodes;
#define B64_INPUT_BLOCK_OFFSET ((inputIndex - 1 - ignorableCharacterCount) % 4)
static unsigned int raw_base64_decode(
const unsigned char *input, unsigned char *output, size_t inLengthToDecode,
size_t *outputDecodedLength)
{
int currentBase64Value;
unsigned int inputIndex = 0;
unsigned int ignorableCharacterCount = 0;
unsigned int i;
unsigned char decodedBuffer[3];
unsigned char currentInputBlockPaddingCharacterCount = 0;
size_t *decodedCharacterCount;
size_t dummyValue;
if (outputDecodedLength == NULL) {
// do this so that if caller passes in NULL for outputDecodedLength
// it can still be handled easily
decodedCharacterCount = &dummyValue;
} else {
decodedCharacterCount = outputDecodedLength;
}
*decodedCharacterCount = 0;
while ( (inputIndex <= inLengthToDecode) &&
(currentInputBlockPaddingCharacterCount == 0) )
{
currentBase64Value = b64revtb[input[inputIndex]];
inputIndex++;
switch (currentBase64Value) {
// [1] Handle control characters
case B64_NullTerminator:
if (B64_INPUT_BLOCK_OFFSET != 0) return B64_decodeError;
// copy remaining characters with padding
if (currentInputBlockPaddingCharacterCount > 0) {
for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) {
*output++ = decodedBuffer[i];
(*decodedCharacterCount)++;
}
}
return B64_noError;
case B64_PaddingCharacter:
if (B64_INPUT_BLOCK_OFFSET < 2) {
/* Invalid here -- only characters 3 and/or 4 of the
input block can be padding */
return B64_decodeError;
} else if (B64_INPUT_BLOCK_OFFSET == 2) {
/* inputIndex points to the next byte in the input buffer. If this is the last byte the
inputIndex is dangling past the end of the array. If it is, then by definition = is not
the next char. Just throw overrun.*/
if (inputIndex > inLengthToDecode)
{
return B64_bufferOverrun;
}
/* Make sure there's appropriate padding */
if (input[inputIndex] != '=') return B64_decodeError;
decodedBuffer[2] = 0;
currentInputBlockPaddingCharacterCount = 2;
break;
} else {
currentInputBlockPaddingCharacterCount = 1;
break;
}
return B64_noError;
case B64_IgnorableCharacter:
ignorableCharacterCount++;
break;
default:
// [2] Handle encoded data
switch (B64_INPUT_BLOCK_OFFSET) {
case 0:
decodedBuffer[0] = currentBase64Value << 2;
break;
case 1:
decodedBuffer[0] |= (currentBase64Value >> 4);
decodedBuffer[1] = currentBase64Value << 4;
break;
case 2:
decodedBuffer[1] |= (currentBase64Value >> 2);
decodedBuffer[2] = currentBase64Value << 6;
break;
case 3:
decodedBuffer[2] |= currentBase64Value;
for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) {
*output++ = decodedBuffer[i];
(*decodedCharacterCount)++;
}
break;
}
break;
}
}
if (inputIndex > inLengthToDecode)
{
return B64_bufferOverrun;
}
for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) {
*output++ = decodedBuffer[i];
(*decodedCharacterCount)++;
}
return B64_noError;
}
unsigned char* xar_from_base64(const unsigned char* input, size_t inputLength, size_t *outputLength)
{
int err;
unsigned char *output;
// N.B.: This is a conservative estimate of space needed. It is NOT
// an exact value -- the exact length of the decoded data will be
// calculated during the decode operation.
output = calloc(1, 3 * (inputLength / 4 + 1));
if (output == NULL) return NULL;
err = raw_base64_decode(input, output, inputLength, outputLength);
if (err != B64_noError) {
free(output);
return NULL;
}
return output;
}

12
xar/lib/b64.h Normal file
View File

@ -0,0 +1,12 @@
/*
* Rob Braun <bbraun@synack.net>
* 1-Oct-2004
* Copyright (c) 2004 Rob Braun. All rights reserved.
*/
#ifndef _XAR_BASE64_H_
#define _XAR_BASE64_H_
unsigned char* xar_from_base64(const unsigned char* input, size_t inputLength, size_t *outputLength);
#endif /* _XAR_BASE64_H_ */

294
xar/lib/bzxar.c Normal file
View File

@ -0,0 +1,294 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#ifdef HAVE_LIBBZ2
#include <bzlib.h>
#endif
#include "xar.h"
#include "filetree.h"
#include "io.h"
#ifdef HAVE_LIBBZ2
struct _bzip_context{
uint8_t bzipcompressed;
bz_stream bz;
};
#define BZIP2_CONTEXT(x) ((struct _bzip_context *)(*x))
#endif
int xar_bzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
#ifdef HAVE_LIBBZ2
if( !context || !BZIP2_CONTEXT(context) )
return 0;
if( BZIP2_CONTEXT(context)->bzipcompressed){
BZ2_bzDecompressEnd(&BZIP2_CONTEXT(context)->bz);
}
/* free the context */
free(BZIP2_CONTEXT(context));
*context = NULL;
#endif /* HAVE_LIBBZ2 */
return 0;
}
int xar_bzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
const char *opt;
xar_prop_t tmpp;
#ifdef HAVE_LIBBZ2
void *out = NULL;
size_t outlen, offset = 0;
int r;
/* on first run, we init the context and check the compression type */
if( !BZIP2_CONTEXT(context) ) {
*context = calloc(1,sizeof(struct _bzip_context));
opt = NULL;
tmpp = xar_prop_pget(p, "encoding");
if( tmpp )
opt = xar_attr_pget(f, tmpp, "style");
if( !opt ) return 0;
if( strcmp(opt, "application/x-bzip2") != 0 ) return 0;
BZ2_bzDecompressInit(&BZIP2_CONTEXT(context)->bz, 0, 0);
BZIP2_CONTEXT(context)->bzipcompressed = 1;
if( *inlen == 0 )
return 0;
}else if( !(BZIP2_CONTEXT(context)->bzipcompressed) ){
/* once the context has been initialized, then we have already
checked the compression type, so we need only check if we
actually are compressed */
return 0;
}
outlen = *inlen;
BZIP2_CONTEXT(context)->bz.next_in = *in;
BZIP2_CONTEXT(context)->bz.avail_in = *inlen;
BZIP2_CONTEXT(context)->bz.next_out = out;
BZIP2_CONTEXT(context)->bz.avail_out = 0;
while( BZIP2_CONTEXT(context)->bz.avail_in != 0 ) {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
BZIP2_CONTEXT(context)->bz.next_out = ((char *)out) + offset;
BZIP2_CONTEXT(context)->bz.avail_out = outlen - offset;
r = BZ2_bzDecompress(&BZIP2_CONTEXT(context)->bz);
if( (r != BZ_OK) && (r != BZ_STREAM_END) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error decompressing file");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
offset += outlen - offset - BZIP2_CONTEXT(context)->bz.avail_out;
if( (r == BZ_STREAM_END) && (offset == 0) )
break;
}
free(*in);
*in = out;
*inlen = offset;
#else
opt = NULL;
tmpp = xar_prop_pget(p, "encoding");
if( tmpp )
opt = xar_attr_pget(f, tmpp, "style");
if( !opt ) return 0;
if( strcmp(opt, "application/x-bzip2") != 0 ) return 0;
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_errno(x, 0);
xar_err_set_string(x, "bzip2 support not compiled in.");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
#endif /* HAVE_LIBBZ2 */
return 0;
}
int xar_bzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
#ifdef HAVE_LIBBZ2
xar_prop_t tmpp;
if( BZIP2_CONTEXT(context)->bzipcompressed){
BZ2_bzCompressEnd(&BZIP2_CONTEXT(context)->bz);
tmpp = xar_prop_pset(f, p, "encoding", NULL);
if( tmpp )
xar_attr_pset(f, tmpp, "style", "application/x-bzip2");
}
/* free the context */
free(BZIP2_CONTEXT(context));
*context = NULL;
#endif /* HAVE_LIBBZ2 */
return 0;
}
int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
const char *opt;
#ifdef HAVE_LIBBZ2
void *out = NULL;
size_t outlen, offset = 0;
int r;
/* on first run, we init the context and check the compression type */
if( !BZIP2_CONTEXT(context) ) {
int level = 9;
*context = calloc(1,sizeof(struct _bzip_context));
opt = xar_opt_get(x, XAR_OPT_COMPRESSION);
if( !opt )
return 0;
if( strcmp(opt, XAR_OPT_VAL_BZIP) != 0 )
return 0;
opt = xar_opt_get(x, XAR_OPT_COMPRESSIONARG);
if( opt ) {
int tmp;
errno = 0;
tmp = strtol(opt, NULL, 10);
if( errno == 0 ) {
if( (level >= 0) && (level <= 9) )
level = tmp;
}
}
BZ2_bzCompressInit(&BZIP2_CONTEXT(context)->bz, level, 0, 30);
BZIP2_CONTEXT(context)->bzipcompressed = 1;
}else if( !BZIP2_CONTEXT(context)->bzipcompressed ){
/* once the context has been initialized, then we have already
checked the compression type, so we need only check if we
actually are compressed */
return 0;
}
outlen = *inlen/2;
if(outlen == 0) outlen = 1024;
BZIP2_CONTEXT(context)->bz.next_in = *in;
BZIP2_CONTEXT(context)->bz.avail_in = *inlen;
BZIP2_CONTEXT(context)->bz.next_out = out;
BZIP2_CONTEXT(context)->bz.avail_out = 0;
if( *inlen != 0 ) {
do {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
BZIP2_CONTEXT(context)->bz.next_out = ((char *)out) + offset;
BZIP2_CONTEXT(context)->bz.avail_out = outlen - offset;
r = BZ2_bzCompress(&BZIP2_CONTEXT(context)->bz, BZ_RUN);
offset = outlen - BZIP2_CONTEXT(context)->bz.avail_out;
} while( r == BZ_RUN_OK && BZIP2_CONTEXT(context)->bz.avail_in != 0 );
} else {
do {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
BZIP2_CONTEXT(context)->bz.next_out = ((char *)out) + offset;
BZIP2_CONTEXT(context)->bz.avail_out = outlen - offset;
r = BZ2_bzCompress(&BZIP2_CONTEXT(context)->bz, BZ_FINISH);
offset = outlen - BZIP2_CONTEXT(context)->bz.avail_out;
} while( (r == BZ_FINISH_OK) && (r != BZ_STREAM_END /* no-op */) );
}
if( (r != BZ_RUN_OK && r != BZ_STREAM_END && r != BZ_SEQUENCE_ERROR) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error compressing file");
xar_err_set_errno(x, r);
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
free(*in);
*in = out;
*inlen = offset;
#else
opt = xar_opt_get(x, XAR_OPT_COMPRESSION);
if( !opt )
return 0;
if( strcmp(opt, XAR_OPT_VAL_BZIP) != 0 )
return 0;
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_errno(x, 0);
xar_err_set_string(x, "bzip2 support not compiled in.");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
#endif /* HAVE_LIBBZ2 */
return 0;
}

47
xar/lib/bzxar.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_BZLIB_H_
#define _XAR_BZLIB_H_
int xar_bzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int xar_bzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int xar_bzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
#endif /* _XAR_BZLIB_H_ */

814
xar/lib/darwinattr.c Normal file
View File

@ -0,0 +1,814 @@
/*
* Copyright (c) 2008 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 24-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include "xar.h"
#include "arcmod.h"
#include "b64.h"
#include <errno.h>
#include <string.h>
#include "util.h"
#include "linuxattr.h"
#include "io.h"
#include "appledouble.h"
#include "stat.h"
#include "archive.h"
#if defined(HAVE_SYS_XATTR_H)
#include <sys/xattr.h>
#endif
struct _darwinattr_context{
int fd;
char *finfo;
char *buf;
int len;
int off;
};
#define DARWINATTR_CONTEXT(x) ((struct _darwinattr_context *)(x))
#if defined(__APPLE__)
#ifdef HAVE_GETATTRLIST
#include <sys/attr.h>
#include <sys/vnode.h>
struct fi {
uint32_t length;
fsobj_type_t objtype;
char finderinfo[32];
};
/* finfo_read
* This is for archiving the finderinfo via the getattrlist method.
* This function is used from the nonea_archive() function.
*/
static int32_t finfo_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
if( len < 32 )
return -1;
if( DARWINATTR_CONTEXT(context)->finfo == NULL )
return 0;
memcpy(buf, DARWINATTR_CONTEXT(context)->finfo, 32);
DARWINATTR_CONTEXT(context)->finfo = NULL;
return 32;
}
/* finfo_write
* This is for extracting the finderinfo via the setattrlist method.
* This function is used from the nonea_extract() function.
*/
static int32_t finfo_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
struct attrlist attrs;
struct fi finfo;
if( len < 32 )
return -1;
if( DARWINATTR_CONTEXT(context)->finfo == NULL )
return 0;
memset(&attrs, 0, sizeof(attrs));
attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO;
getattrlist(DARWINATTR_CONTEXT(context)->finfo, &attrs, &finfo, sizeof(finfo), 0);
attrs.commonattr = ATTR_CMN_FNDRINFO;
if( setattrlist(DARWINATTR_CONTEXT(context)->finfo, &attrs, buf, 32, 0) != 0 )
return -1;
DARWINATTR_CONTEXT(context)->finfo = NULL;
return 32;
}
#endif /* HAVE_GETATTRLIST */
/* xar_rsrc_read
* This is the read callback function for archiving the resource fork via
* the ..namedfork method. This callback is used from nonea_archive()
*/
static int32_t xar_rsrc_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) {
int32_t r;
while(1) {
r = read(DARWINATTR_CONTEXT(context)->fd, inbuf, bsize);
if( (r < 0) && (errno == EINTR) )
continue;
return r;
}
}
#endif /* __APPLE__ */
/* xar_rsrc_write
* This is the write callback function for writing the resource fork
* back to the file via ..namedfork method. This is the callback used
* in nonea_extract() and underbar_extract().
*/
static int32_t xar_rsrc_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
int32_t r;
size_t off = 0;
do {
r = write(DARWINATTR_CONTEXT(context)->fd, ((char *)buf)+off, len-off);
if( (r < 0) && (errno != EINTR) )
return r;
off += r;
} while( off < len );
return off;
}
#ifdef __APPLE__
#if defined(HAVE_GETXATTR)
static int32_t xar_ea_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
if( DARWINATTR_CONTEXT(context)->buf == NULL )
return 0;
if( ((DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off)) <= len ) {
int siz = (DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off);
memcpy(buf, DARWINATTR_CONTEXT(context)->buf+DARWINATTR_CONTEXT(context)->off, siz);
free(DARWINATTR_CONTEXT(context)->buf);
DARWINATTR_CONTEXT(context)->buf = NULL;
DARWINATTR_CONTEXT(context)->off = 0;
DARWINATTR_CONTEXT(context)->len = 0;
return siz;
}
memcpy(buf, DARWINATTR_CONTEXT(context)->buf+DARWINATTR_CONTEXT(context)->off, len);
DARWINATTR_CONTEXT(context)->off += len;
if( DARWINATTR_CONTEXT(context)->off == DARWINATTR_CONTEXT(context)->len ) {
free(DARWINATTR_CONTEXT(context)->buf);
DARWINATTR_CONTEXT(context)->buf = NULL;
DARWINATTR_CONTEXT(context)->off = 0;
DARWINATTR_CONTEXT(context)->len = 0;
}
return len;
}
static int32_t xar_ea_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
if( DARWINATTR_CONTEXT(context)->buf == NULL )
return 0;
if( DARWINATTR_CONTEXT(context)->off == DARWINATTR_CONTEXT(context)->len )
return 0;
if( ((DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off)) <= len ) {
int siz = (DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off);
memcpy((DARWINATTR_CONTEXT(context)->buf)+(DARWINATTR_CONTEXT(context)->off), buf, siz);
return siz;
}
memcpy((DARWINATTR_CONTEXT(context)->buf)+(DARWINATTR_CONTEXT(context)->off), buf, len);
DARWINATTR_CONTEXT(context)->off += len;
return len;
}
static int32_t ea_archive(xar_t x, xar_file_t f, const char* file, void *context) {
char *buf, *i;
int ret, bufsz, attrsz;
int32_t retval = 0;
if( file == NULL )
return 0;
ret = listxattr(file, NULL, 0, XATTR_NOFOLLOW);
if( ret < 0 )
return -1;
if( ret == 0 )
return 0;
bufsz = ret;
TRYAGAIN:
buf = malloc(bufsz);
if( !buf )
goto TRYAGAIN;
ret = listxattr(file, buf, bufsz, XATTR_NOFOLLOW);
if( ret < 0 ) {
switch(errno) {
case ERANGE: bufsz = bufsz*2; free(buf); goto TRYAGAIN;
case ENOTSUP: retval = 0; goto BAIL;
default: retval = -1; goto BAIL;
};
}
if( ret == 0 ) {
retval = 0;
goto BAIL;
}
attrsz = ret;
for( i = buf; (i-buf) < attrsz; i += strlen(i)+1 ) {
xar_ea_t e;
ret = getxattr(file, i, NULL, 0, 0, XATTR_NOFOLLOW);
if( ret < 0 )
continue;
DARWINATTR_CONTEXT(context)->len = ret;
DARWINATTR_CONTEXT(context)->buf = malloc(DARWINATTR_CONTEXT(context)->len);
if( !DARWINATTR_CONTEXT(context)->buf )
goto BAIL;
ret = getxattr(file, i, DARWINATTR_CONTEXT(context)->buf, DARWINATTR_CONTEXT(context)->len, 0, XATTR_NOFOLLOW);
if( ret < 0 ) {
free(DARWINATTR_CONTEXT(context)->buf);
DARWINATTR_CONTEXT(context)->buf = NULL;
DARWINATTR_CONTEXT(context)->len = 0;
continue;
}
e = xar_ea_new(f, i);
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_ea_read, context) < 0) {
retval = -1;
goto BAIL;
}
}
BAIL:
free(buf);
return retval;
}
static int32_t ea_extract(xar_t x, xar_file_t f, const char* file, void *context) {
xar_prop_t p;
for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) {
const char *opt;
const char *name = NULL;
int len;
xar_prop_t tmpp;
name = xar_prop_getkey(p);
if( strncmp(name, XAR_EA_FORK, strlen(XAR_EA_FORK)) )
continue;
if( strlen(name) != strlen(XAR_EA_FORK) )
continue;
opt = NULL;
tmpp = xar_prop_pget(p, "size");
if( tmpp )
opt = xar_prop_getvalue(tmpp);
if( !opt )
continue;
len = strtol(opt, NULL, 10);
DARWINATTR_CONTEXT(context)->buf = malloc(len);
if( !DARWINATTR_CONTEXT(context)->buf )
return -1;
DARWINATTR_CONTEXT(context)->len = len;
if (XAR(x)->attrcopy_from_heap(x, f, p, xar_ea_write, context) < 0)
return -1;
name = NULL;
tmpp = xar_prop_pget(p, "name");
if( tmpp )
name = xar_prop_getvalue(tmpp);
if( !name )
continue;
setxattr(file, name, DARWINATTR_CONTEXT(context)->buf, DARWINATTR_CONTEXT(context)->len, 0, XATTR_NOFOLLOW);
free(DARWINATTR_CONTEXT(context)->buf);
DARWINATTR_CONTEXT(context)->buf = NULL;
DARWINATTR_CONTEXT(context)->len = 0;
DARWINATTR_CONTEXT(context)->off = 0;
}
return 0;
}
#endif /* HAVE_GETXATTR */
/* nonea_archive
* Archive the finderinfo and resource fork through getattrlist and
* ..namedfork methods rather than via EAs. This is mainly for 10.3
* and earlier support
*/
static int32_t nonea_archive(xar_t x, xar_file_t f, const char* file, void *context) {
char rsrcname[4096];
struct stat sb;
xar_ea_t e;
#ifdef HAVE_GETATTRLIST
struct attrlist attrs;
struct fi finfo;
int ret;
char z[32];
memset(&attrs, 0, sizeof(attrs));
attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO;
ret = getattrlist(file, &attrs, &finfo, sizeof(finfo), 0);
if( ret != 0 )
return -1;
memset(z, 0, sizeof(z));
if( memcmp(finfo.finderinfo, z, sizeof(finfo.finderinfo)) != 0 ) {
e = xar_ea_new(f, "com.apple.FinderInfo");
DARWINATTR_CONTEXT(context)->finfo = finfo.finderinfo;
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), finfo_read, context) < 0)
return -1;
}
#endif /* HAVE_GETATTRLIST */
memset(rsrcname, 0, sizeof(rsrcname));
snprintf(rsrcname, sizeof(rsrcname)-1, "%s/..namedfork/rsrc", file);
if( lstat(rsrcname, &sb) != 0 )
return 0;
if( sb.st_size == 0 )
return 0;
DARWINATTR_CONTEXT(context)->fd = open(rsrcname, O_RDONLY, 0);
if( DARWINATTR_CONTEXT(context)->fd < 0 )
return -1;
e = xar_ea_new(f, "com.apple.ResourceFork");
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_rsrc_read, context) < 0) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
close(DARWINATTR_CONTEXT(context)->fd);
return 0;
}
/* nonea_extract
* Extract the finderinfo and resource fork through setattrlist and
* ..namedfork methods rather than via EAs. This is mainly for 10.3
* and earlier support
*/
static int32_t nonea_extract(xar_t x, xar_file_t f, const char* file, void *context) {
char rsrcname[4096];
xar_prop_t p;
#ifdef HAVE_SETATTRLIST
struct attrlist attrs;
struct fi finfo;
int ret;
memset(&attrs, 0, sizeof(attrs));
attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO;
ret = getattrlist(file, &attrs, &finfo, sizeof(finfo), 0);
if( ret != 0 )
return -1;
DARWINATTR_CONTEXT(context)->finfo = (char *)file;
p = xar_ea_find(f, "com.apple.ResourceFork");
if( p ) {
if (XAR(x)->attrcopy_from_heap(x, f, p, finfo_write, context) < 0) {
return -1;
}
}
#endif /* HAVE_SETATTRLIST */
memset(rsrcname, 0, sizeof(rsrcname));
snprintf(rsrcname, sizeof(rsrcname)-1, "%s/..namedfork/rsrc", file);
DARWINATTR_CONTEXT(context)->fd = open(rsrcname, O_RDWR|O_TRUNC);
if( DARWINATTR_CONTEXT(context)->fd < 0 )
return 0;
p = xar_ea_find(f, "com.apple.ResourceFork");
if( p ) {
if (XAR(x)->attrcopy_from_heap(x, f, p, xar_rsrc_write, context) < 0) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
}
close(DARWINATTR_CONTEXT(context)->fd);
return 0;
}
#endif /* __APPLE__ */
/* xar_underbar_check
* Check to see if the file we're archiving is a ._ file. If so,
* stop the archival process.
*/
xar_file_t xar_underbar_check(xar_t x, xar_file_t f, const char* file, void *context) {
char *bname, *tmp;
tmp = strdup(file);
bname = basename(tmp);
if(bname && (bname[0] == '.') && (bname[1] == '_')) {
char *nonunderbar, *nupath, *tmp2, *dname;
struct stat sb;
nonunderbar = bname+2;
tmp2 = strdup(file);
dname = xar_safe_dirname(tmp2);
asprintf(&nupath, "%s/%s", dname, nonunderbar);
free(dname);
free(tmp2);
/* if there is no file that the ._ corresponds to, archive
* it like a normal file.
*/
if( stat(nupath, &sb) ) {
free(tmp);
free(nupath);
return NULL;
}
asprintf(&tmp2, "%s/..namedfork/rsrc", nupath);
/* If there is a file that the ._ file corresponds to, and
* there is no resource fork, assume the ._ file contains
* the file's resource fork, and skip it (to be picked up
* when the file is archived.
*/
if( stat(tmp2, &sb) ) {
xar_file_t tmpf;
tmpf = xar_file_find(XAR(x)->files, nupath);
if( !tmpf ) {
tmpf = xar_add(x, nupath);
}
free(nupath);
free(tmp2);
free(tmp);
return tmpf;
}
/* otherwise, we have a corresponding file and it supports
* resource forks, so we assume this is a detached ._ file
* and archive it as a real file.
*/
free(nupath);
free(tmp2);
free(tmp);
return NULL;
}
free(tmp);
return NULL;
}
#ifdef __APPLE__
/* This only really makes sense on OSX */
static int32_t underbar_archive(xar_t x, xar_file_t f, const char* file, void *context) {
struct stat sb;
char underbarname[4096], z[32];
char *dname, *bname, *tmp, *tmp2;
struct AppleSingleHeader ash;
struct AppleSingleEntry ase;
int num_entries = 0, i, r;
off_t off;
if( !file )
return 0;
tmp = strdup(file);
tmp2 = strdup(file);
dname = xar_safe_dirname(tmp2);
bname = basename(tmp);
memset(underbarname, 0, sizeof(underbarname));
snprintf(underbarname, sizeof(underbarname)-1, "%s/._%s", dname, bname);
free(tmp);
free(tmp2);
free(dname);
if( stat(underbarname, &sb) != 0 )
return 0;
DARWINATTR_CONTEXT(context)->fd = open(underbarname, O_RDONLY);
if( DARWINATTR_CONTEXT(context)->fd < 0 )
return -1;
memset(&ash, 0, sizeof(ash));
memset(&ase, 0, sizeof(ase));
r = read(DARWINATTR_CONTEXT(context)->fd, &ash, XAR_ASH_SIZE);
if( r < XAR_ASH_SIZE ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
if( ntohl(ash.magic) != APPLEDOUBLE_MAGIC ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
if( ntohl(ash.version) != APPLEDOUBLE_VERSION ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
off = XAR_ASH_SIZE;
num_entries = ntohs(ash.entries);
for(i = 0; i < num_entries; i++) {
off_t entoff;
r = read(DARWINATTR_CONTEXT(context)->fd, &ase, sizeof(ase));
if( r < sizeof(ase) ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
off+=r;
if( ntohl(ase.entry_id) == AS_ID_FINDER ) {
xar_ea_t e;
entoff = (off_t)ntohl(ase.offset);
if( lseek(DARWINATTR_CONTEXT(context)->fd, entoff, SEEK_SET) == -1 ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
r = read(DARWINATTR_CONTEXT(context)->fd, z, sizeof(z));
if( r < sizeof(z) ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
DARWINATTR_CONTEXT(context)->finfo = z;
e = xar_ea_new(f, "com.apple.FinderInfo");
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), finfo_read, context) < 0) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
if( lseek(DARWINATTR_CONTEXT(context)->fd, (off_t)off, SEEK_SET) == -1 ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
}
if( ntohl(ase.entry_id) == AS_ID_RESOURCE ) {
xar_ea_t e;
entoff = (off_t)ntohl(ase.offset);
if( lseek(DARWINATTR_CONTEXT(context)->fd, entoff, SEEK_SET) == -1 ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
e = xar_ea_new(f, "com.apple.ResourceFork");
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_rsrc_read, context) < 0) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
if( lseek(DARWINATTR_CONTEXT(context)->fd, (off_t)off, SEEK_SET) == -1 ) {
close(DARWINATTR_CONTEXT(context)->fd);
return -1;
}
}
}
close(DARWINATTR_CONTEXT(context)->fd);
DARWINATTR_CONTEXT(context)->fd = 0;
return 0;
}
#endif
/* underbar_extract
* Extract finderinfo and resource fork information to an appledouble
* ._ file.
*/
static int32_t underbar_extract(xar_t x, xar_file_t f, const char* file, void *context) {
char underbarname[4096];
char *dname, *bname, *tmp, *tmp2;
const char *rsrclenstr;
struct AppleSingleHeader ash;
struct AppleSingleEntry ase;
int num_entries = 0, rsrclen = 0, have_rsrc = 0, have_fi = 0;
xar_prop_t p;
xar_prop_t rfprop = NULL, fiprop = NULL;
fiprop = xar_ea_find(f, "com.apple.FinderInfo");
if( fiprop ) {
have_fi = 1;
num_entries++;
}
rfprop = xar_ea_find(f, "com.apple.ResourceFork");
if( rfprop ) {
have_rsrc = 1;
num_entries++;
}
if( num_entries == 0 )
return 0;
tmp = strdup(file);
tmp2 = strdup(file);
dname = xar_safe_dirname(tmp2);
bname = basename(tmp);
memset(underbarname, 0, sizeof(underbarname));
snprintf(underbarname, sizeof(underbarname)-1, "%s/._%s", dname, bname);
free(tmp);
free(tmp2);
free(dname);
DARWINATTR_CONTEXT(context)->fd = open(underbarname, O_RDWR | O_CREAT | O_TRUNC, 0);
if( DARWINATTR_CONTEXT(context)->fd < 0 )
return -1;
rsrclenstr = NULL;
if( rfprop ) {
p = xar_prop_pget(rfprop, "size");
if( p )
rsrclenstr = xar_prop_getvalue(p);
if( rsrclenstr )
rsrclen = strtol(rsrclenstr, NULL, 10);
}
memset(&ash, 0, sizeof(ash));
memset(&ase, 0, sizeof(ase));
ash.magic = htonl(APPLEDOUBLE_MAGIC);
ash.version = htonl(APPLEDOUBLE_VERSION);
ash.entries = htons(num_entries);
write(DARWINATTR_CONTEXT(context)->fd, &ash, XAR_ASH_SIZE);
ase.offset = htonl(XAR_ASH_SIZE + ntohs(ash.entries)*12);
if( have_fi ) {
ase.entry_id = htonl(AS_ID_FINDER);
ase.length = htonl(32);
write(DARWINATTR_CONTEXT(context)->fd, &ase, 12);
}
if( have_rsrc ) {
ase.entry_id = htonl(AS_ID_RESOURCE);
ase.offset = htonl(ntohl(ase.offset) + ntohl(ase.length));
ase.length = htonl(rsrclen);
write(DARWINATTR_CONTEXT(context)->fd, &ase, 12);
}
if( have_fi ) {
if (XAR(x)->attrcopy_from_heap(x, f, fiprop, xar_rsrc_write, context) < 0) {
close(DARWINATTR_CONTEXT(context)->fd);
DARWINATTR_CONTEXT(context)->fd = 0;
return -1;
}
}
if( have_rsrc ) {
if (XAR(x)->attrcopy_from_heap(x, f, rfprop, xar_rsrc_write, context) < 0) {
close(DARWINATTR_CONTEXT(context)->fd);
DARWINATTR_CONTEXT(context)->fd = 0;
return -1;
}
}
close(DARWINATTR_CONTEXT(context)->fd);
DARWINATTR_CONTEXT(context)->fd = 0;
xar_set_perm(x, f, underbarname, NULL, 0 );
return 0;
}
#if defined(__APPLE__)
static int32_t stragglers_archive(xar_t x, xar_file_t f, const char* file, void *context) {
#ifdef HAVE_GETATTRLIST
struct fits {
uint32_t length;
struct timespec ts;
};
struct fits fts;
struct attrlist attrs;
int ret;
if( !xar_check_prop(x, "FinderCreateTime") )
return 0;
memset(&attrs, 0, sizeof(attrs));
attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
attrs.commonattr = ATTR_CMN_CRTIME;
ret = getattrlist(file, &attrs, &fts, sizeof(fts), 0);
if( ret == 0 ) {
xar_prop_t tmpp;
tmpp = xar_prop_new(f, NULL);
if( tmpp ) {
char tmpc[128];
struct tm tm;
xar_prop_setkey(tmpp, "FinderCreateTime");
xar_prop_setvalue(tmpp, NULL);
memset(tmpc, 0, sizeof(tmpc));
gmtime_r(&fts.ts.tv_sec, &tm);
strftime(tmpc, sizeof(tmpc), "%FT%T", &tm);
xar_prop_pset(f, tmpp, "time", tmpc);
memset(tmpc, 0, sizeof(tmpc));
sprintf(tmpc, "%ld", fts.ts.tv_nsec);
xar_prop_pset(f, tmpp, "nanoseconds", tmpc);
}
}
#endif
return 0;
}
static int32_t stragglers_extract(xar_t x, xar_file_t f, const char* file, void *context) {
#ifdef HAVE_GETATTRLIST
const char *tmpc = NULL;
struct tm tm;
struct timespec ts;
struct attrlist attrs;
xar_prop_get(f, "FinderCreateTime/time", &tmpc);
if( tmpc ) {
strptime(tmpc, "%FT%T", &tm);
ts.tv_sec = timegm(&tm);
xar_prop_get(f, "FinderCreateTime/nanoseconds", &tmpc);
if( tmpc ) {
ts.tv_nsec = strtol(tmpc, NULL, 10);
memset(&attrs, 0, sizeof(attrs));
attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
attrs.commonattr = ATTR_CMN_CRTIME;
setattrlist(file, &attrs, &ts, sizeof(ts), 0);
}
}
#endif
return 0;
}
#endif /* __APPLE__ */
int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len)
{
struct _darwinattr_context context;
memset(&context,0,sizeof(struct _darwinattr_context));
#if defined(__APPLE__)
if( len )
return 0;
stragglers_archive(x, f, file, (void *)&context);
/* From here on out, props are only EA's */
if( !xar_check_prop(x, "ea") )
return 0;
#if defined(HAVE_GETXATTR)
if( ea_archive(x, f, file, (void *)&context) == 0 )
return 0;
#endif
if( nonea_archive(x, f, file, (void *)&context) == 0 )
return 0;
return underbar_archive(x, f, file, (void *)&context);
#endif /* __APPLE__ */
return 0;
}
int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len)
{
struct _darwinattr_context context;
memset(&context,0,sizeof(struct _darwinattr_context));
#if defined(__APPLE__)
if( len )
return 0;
stragglers_extract(x, f, file, (void *)&context);
#if defined(HAVE_GETXATTR)
if( ea_extract(x, f, file, (void *)&context) == 0 )
return 0;
#endif
if( nonea_extract(x, f, file, (void *)&context) == 0 )
return 0;
#endif /* __APPLE__ */
return underbar_extract(x, f, file, (void *)&context);
}

43
xar/lib/darwinattr.h Normal file
View File

@ -0,0 +1,43 @@
/*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Rob Braun <bbraun@synack.net>
* 23-Apr-2005
* Copyright (c) 2004 Rob Braun. All rights reserved.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_DARWINATTR_H_
#define _XAR_DARWINATTR_H_
xar_file_t xar_underbar_check(xar_t x, xar_file_t f, const char* file);
int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len);
int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len);
#endif /* _XAR_DARWINATTR_H_ */

273
xar/lib/data.c Normal file
View File

@ -0,0 +1,273 @@
/*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#define _FILE_OFFSET_BITS 64
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/types.h>
#include "xar.h"
#include "filetree.h"
#include "archive.h"
#include "io.h"
#include "arcmod.h"
#include "data.h"
#ifndef O_EXLOCK
#define O_EXLOCK 0
#endif
int32_t xar_data_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) {
int32_t r;
/* read from buffer, rather then fd,if available */
if(DATA_CONTEXT(context)->length){
char *readbuf = (char *)DATA_CONTEXT(context)->buffer;
size_t sizetoread = DATA_CONTEXT(context)->length - DATA_CONTEXT(context)->offset;
if( !sizetoread){
return 0;
}
if( sizetoread > bsize ){
sizetoread = bsize;
}
/* dont read passed the end of the buffer */
if((DATA_CONTEXT(context)->offset + sizetoread) > DATA_CONTEXT(context)->length){
return -1;
//sizetoread = (DATA_CONTEXT(context)->offset + sizetoread) - DATA_CONTEXT(context)->length;
}
readbuf += DATA_CONTEXT(context)->offset;
memcpy(inbuf,readbuf,sizetoread);
DATA_CONTEXT(context)->total += sizetoread;
DATA_CONTEXT(context)->offset += sizetoread;
return sizetoread;
}
while(1) {
r = read(DATA_CONTEXT(context)->fd, inbuf, bsize);
if( (r < 0) && (errno == EINTR) )
continue;
DATA_CONTEXT(context)->total += r;
return r;
}
}
int32_t xar_data_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
int32_t r;
size_t off = 0;
/* read from buffer, rather then fd,if available */
if(DATA_CONTEXT(context)->length){
char *writebuf = (char *)DATA_CONTEXT(context)->buffer;
/* dont write passed the end of the buffer */
if((DATA_CONTEXT(context)->offset + len) > DATA_CONTEXT(context)->length){
return -1;
}
writebuf += DATA_CONTEXT(context)->offset;
memcpy(writebuf,buf,len);
DATA_CONTEXT(context)->offset += len;
return len;
}
do {
r = write(DATA_CONTEXT(context)->fd, ((char *)buf)+off, len-off);
if( (r < 0) && (errno != EINTR) )
return r;
off += r;
} while( off < len );
return off;
}
/* xar_data_archive
* This is the arcmod archival entry point for archiving the file's
* data into the heap file.
*/
int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) {
const char *opt;
int32_t retval = 0;
struct _data_context context;
xar_prop_t tmpp;
memset(&context,0,sizeof(struct _data_context));
if( !xar_check_prop(x, "data") )
return 0;
xar_prop_get(f, "type", &opt);
if(!opt) return 0;
if( strcmp(opt, "file") != 0 ) {
if( strcmp(opt, "hardlink") == 0 ) {
opt = xar_attr_get(f, "type", "link");
if( !opt )
return 0;
if( strcmp(opt, "original") != 0 )
return 0;
/* else, we're an original hardlink, so keep going */
} else
return 0;
}
if( 0 == len ){
context.fd = open(file, O_RDONLY);
if( context.fd < 0 ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "io: Could not open file");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
}else{
context.buffer = (void *)buffer;
context.length = len;
context.offset = 0;
}
#ifdef F_NOCACHE
fcntl(context.fd, F_NOCACHE, 1);
#endif
tmpp = xar_prop_pset(f, NULL, "data", NULL);
retval = XAR(x)->attrcopy_to_heap(x, f, tmpp, xar_data_read,(void *)(&context));
if( context.total == 0 )
xar_prop_unset(f, "data");
if(context.fd > 0){
close(context.fd);
context.fd = -1;
}
return retval;
}
int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
const char *opt;
int32_t retval = 0;
struct _data_context context;
xar_prop_t tmpp;
memset(&context,0,sizeof(struct _data_context));
/* Only regular files are copied in and out of the heap here */
xar_prop_get(f, "type", &opt);
if( !opt ) return 0;
if( strcmp(opt, "file") != 0 ) {
if( strcmp(opt, "hardlink") == 0 ) {
opt = xar_attr_get(f, "type", "link");
if( !opt )
return 0;
if( strcmp(opt, "original") != 0 )
return 0;
/* else, we're an original hardlink, so keep going */
} else
return 0;
}
if ( len ){
context.length = len;
context.buffer = buffer;
context.offset = 0;
}else{
/* mode 600 since other modules may need to operate on the file
* prior to the real permissions being set.
*/
context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600);
if( context.fd < 0 ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "io: Could not create file");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
}
tmpp = xar_prop_pfirst(f);
if( tmpp )
tmpp = xar_prop_find(tmpp, "data");
if( !tmpp ) {
close(context.fd);
return 0;
}
retval = XAR(x)->attrcopy_from_heap(x, f, tmpp, xar_data_write, (void *)(&context));
if( context.fd > 0 ){
close(context.fd);
context.fd = -1;
}
return retval;
}
int32_t xar_data_verify(xar_t x, xar_file_t f, xar_progress_callback p)
{
const char *opt;
struct _data_context context;
xar_prop_t tmpp;
memset(&context,0,sizeof(struct _data_context));
context.progress = p;
/* Only regular files are copied in and out of the heap here */
xar_prop_get(f, "type", &opt);
if( !opt ) return 0;
if( strcmp(opt, "directory") == 0 ) {
return 0;
}
tmpp = xar_prop_pfirst(f);
if( tmpp )
tmpp = xar_prop_find(tmpp, "data");
if (!tmpp) // It appears that xar can have truely empty files, aka, no data. We should just fail to verify these files.
return 0; // After all, the checksum of blank is meaningless. So, failing to do so will cause a crash.
return XAR(x)->attrcopy_from_heap(x, f, tmpp, NULL , (void *)(&context));
}

57
xar/lib/data.h Normal file
View File

@ -0,0 +1,57 @@
/*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Rob Braun <bbraun@synack.net>
* 21-Apr-2004
* Copyright (c) 2004 Rob Braun. All rights reserved.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_DATA_H_
#define _XAR_DATA_H_
struct _data_context{
xar_progress_callback progress;
int fd;
void *buffer;
size_t length;
off_t offset;
off_t total;
};
#define DATA_CONTEXT(x) ((struct _data_context*)(x))
int32_t xar_data_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len);
int32_t xar_data_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len);
int32_t xar_data_verify(xar_t x, xar_file_t f, xar_progress_callback p);
#endif /* _XAR_DATA_H_ */

127
xar/lib/ea.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2008 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <libgen.h>
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include "xar.h"
#include "filetree.h"
#include "archive.h"
#include "b64.h"
#include "ea.h"
struct __xar_ea_t {
const struct __xar_prop_t *prop;
const struct __xar_ea_t *next;
};
#define XAR_EA(x) ((struct __xar_ea_t *)(x))
xar_ea_t xar_ea_new(xar_file_t f, const char *name)
{
xar_ea_t ret;
ret = calloc(sizeof(struct __xar_ea_t), 1);
if( !ret )
return NULL;
XAR_EA(ret)->prop = xar_prop_new(f, NULL);
if( !XAR_EA(ret)->prop ) {
free(ret);
return NULL;
}
xar_prop_setkey(XAR_EA(ret)->prop, "ea");
xar_prop_setvalue(XAR_EA(ret)->prop, NULL);
XAR_PROP(XAR_EA(ret)->prop)->attrs = xar_attr_new();
XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->key = strdup("id");
asprintf((char **)&XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->value, "%lld", XAR_FILE(f)->nexteaid++);
xar_prop_pset(f, XAR_EA(ret)->prop, "name", name);
return ret;
}
int32_t xar_ea_pset(xar_file_t f, xar_ea_t e, const char *key, const char *value){
if( xar_prop_pset(f, XAR_EA(e)->prop, key, value) )
return 0;
return -1;
}
int32_t xar_ea_pget(xar_ea_t e, const char *key, const char **value) {
xar_prop_t r = xar_prop_find(XAR_EA(e)->prop, key);
if( !r ) {
if( value )
*value = NULL;
return -1;
}
if(value)
*value = XAR_PROP(r)->value;
return 0;
}
xar_prop_t xar_ea_root(xar_ea_t e) {
return XAR_EA(e)->prop;
}
xar_prop_t xar_ea_find(xar_file_t f, const char *name)
{
xar_prop_t p;
for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) {
const char *tmp;
xar_prop_t tmpp;
tmp = xar_prop_getkey(p);
if( strncmp(tmp, XAR_EA_FORK, strlen(XAR_EA_FORK)) != 0 )
continue;
if( strlen(tmp) != strlen(XAR_EA_FORK) )
continue;
tmpp = xar_prop_pget(p, "name");
if( !tmpp )
continue;
tmp = xar_prop_getvalue(tmpp);
if( !tmp )
continue;
if( strcmp(tmp, name) == 0 )
return p;
}
return NULL;
}

15
xar/lib/ea.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef _XAR_EA_H_
#define _XAR_EA_H_
#include "xar.h"
#include "filetree.h"
typedef struct __xar_ea_t *xar_ea_t;
xar_ea_t xar_ea_new(xar_file_t f, const char *name);
int32_t xar_ea_pset(xar_file_t f, xar_ea_t e, const char *key, const char *value);
int32_t xar_ea_pget(xar_ea_t e, const char *key, const char **value);
xar_prop_t xar_ea_root(xar_ea_t e);
xar_prop_t xar_ea_find(xar_file_t f, const char *name);
#endif /* _XAR_EA_H_ */

101
xar/lib/err.c Normal file
View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "xar.h"
#include "archive.h"
#define ECTX(x) ((struct errctx *)(x))
void xar_register_errhandler(xar_t x, err_handler callback, void *usrctx) {
ECTX(&XAR(x)->errctx)->x = x;
ECTX(&XAR(x)->errctx)->usrctx = usrctx;
XAR(x)->ercallback = callback;
return;
}
xar_t xar_err_get_archive(xar_errctx_t ctx) {
return ECTX(ctx)->x;
}
xar_file_t xar_err_get_file(xar_errctx_t ctx) {
return ECTX(ctx)->file;
}
void xar_err_set_file(xar_t x, xar_file_t f) {
XAR(x)->errctx.file = f;
return;
}
const char *xar_err_get_string(xar_errctx_t ctx) {
return ECTX(ctx)->str;
}
void xar_err_set_string(xar_t x, const char *str) {
XAR(x)->errctx.str = strdup(str); // this leaks right now, but it's safer than the alternative
return;
}
void xar_err_set_formatted_string(xar_t x, const char *format, ...) {
va_list arg;
char *msg;
va_start(arg, format);
vasprintf(&msg, format, arg);
va_end(arg);
xar_err_set_string(x, msg);
free(msg);
}
int xar_err_get_errno(xar_errctx_t ctx) {
return ECTX(ctx)->saved_errno;
}
void xar_err_set_errno(xar_t x, int e) {
XAR(x)->errctx.saved_errno = e;
return;
}
void xar_err_new(xar_t x) {
memset(&XAR(x)->errctx, 0, sizeof(struct errctx));
XAR(x)->errctx.saved_errno = errno;
return;
}
int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err) {
if( XAR(x)->ercallback )
return XAR(x)->ercallback(sev, err, &XAR(x)->errctx, ECTX(&XAR(x)->errctx)->usrctx);
return 0;
}

257
xar/lib/ext2.c Normal file
View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2004 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 26-Oct-2004
* DRI: Rob Braun <bbraun@synack.net>
* Ported from xar-unsaxy 16-Apr-2005
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include <stdio.h>
#include <unistd.h>
#include "xar.h"
#include "arcmod.h"
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include "ext2.h"
#ifdef HAVE_EXT2FS_EXT2_FS_H
#include <ext2fs/ext2_fs.h>
#else
#if defined(HAVE_LINUX_EXT2_FS_H)
typedef uint32_t u32;
typedef uint8_t u8;
#include <linux/ext2_fs.h>
#endif
#endif
#define XAR_EXT2_FORK "ext2"
#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H)
static void x_addprop(xar_file_t f, const char *name) {
char opt[1024];
memset(opt, 0, sizeof(opt));
snprintf(opt, sizeof(opt)-1, "%s/%s", XAR_ATTR_FORK, name);
xar_prop_set(f, opt, NULL);
xar_attr_set(f, opt, "fstype", "ext2");
return;
}
#endif
int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len)
{
int ret = 0;
/* if archiving from a buffer, then there is no place to get extattr */
if ( len )
return 0;
#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H)
int fd, flags=0, version;
char *vstr;
const char *opt;
xar_prop_get(f, "type", &opt);
if(!opt) return 0;
if( strcmp(opt, "file") != 0 ) {
if( strcmp(opt, "hardlink") != 0 )
if( strcmp(opt, "directory") != 0 )
return 0;
}
fd = open(file, O_RDONLY);
if( fd < 0 ) {
return 0;
}
if( ioctl(fd, EXT2_IOC_GETVERSION, &version) < 0 ) {
ret = 0;
goto BAIL;
}
if( ioctl(fd, EXT2_IOC_GETFLAGS, &flags) < 0 ) {
ret = 0;
goto BAIL;
}
if( flags == 0 ) goto BAIL;
xar_prop_set(f, XAR_EXT2_FORK, NULL);
asprintf(&vstr, "%d", version);
xar_attr_set(f, XAR_EXT2_FORK, "version", vstr);
free(vstr);
if(! (flags & ~EXT2_SECRM_FL) )
x_addprop(f, "SecureDeletion");
if(! (flags & ~EXT2_UNRM_FL) )
x_addprop(f, "Undelete");
if(! (flags & ~EXT2_COMPR_FL) )
x_addprop(f, "Compress");
if(! (flags & ~EXT2_SYNC_FL) )
x_addprop(f, "Synchronous");
if(! (flags & ~EXT2_IMMUTABLE_FL) )
x_addprop(f, "Immutable");
if(! (flags & ~EXT2_APPEND_FL) )
x_addprop(f, "AppendOnly");
if(! (flags & ~EXT2_NODUMP_FL) )
x_addprop(f, "NoDump");
if(! (flags & ~EXT2_NOATIME_FL) )
x_addprop(f, "NoAtime");
if(! (flags & ~EXT2_DIRTY_FL) )
x_addprop(f, "CompDirty");
if(! (flags & ~EXT2_COMPRBLK_FL) )
x_addprop(f, "CompBlock");
#ifdef EXT2_NOCOMPR_FL
if(! (flags & ~EXT2_NOCOMPR_FL) )
x_addprop(f, "NoCompBlock");
#endif
if(! (flags & ~EXT2_ECOMPR_FL) )
x_addprop(f, "CompError");
if(! (flags & ~EXT2_BTREE_FL) )
x_addprop(f, "BTree");
if(! (flags & ~EXT2_INDEX_FL) )
x_addprop(f, "HashIndexed");
if(! (flags & ~EXT2_IMAGIC_FL) )
x_addprop(f, "iMagic");
#ifdef EXT3_JOURNAL_DATA_FL
if(! (flags & ~EXT3_JOURNAL_DATA_FL) )
x_addprop(f, "Journaled");
#endif
if(! (flags & ~EXT2_NOTAIL_FL) )
x_addprop(f, "NoTail");
if(! (flags & ~EXT2_DIRSYNC_FL) )
x_addprop(f, "DirSync");
if(! (flags & ~EXT2_TOPDIR_FL) )
x_addprop(f, "TopDir");
if(! (flags & ~EXT2_RESERVED_FL) )
x_addprop(f, "Reserved");
BAIL:
close(fd);
#endif
return ret;
}
#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H)
static int32_t e2prop_get(xar_file_t f, const char *name, char **value) {
char v[1024];
memset(v, 0, sizeof(v));
snprintf(v, sizeof(v)-1, "%s/%s", XAR_ATTR_FORK, name);
return xar_prop_get(f, v, (const char**)value);
}
#endif
int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len)
{
/* if extracting to a buffer, then there is no place to write extattr */
if ( len )
return 0;
#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H)
int fd = -1, version, flags = 0;
char *tmp;
if( xar_prop_get(f, XAR_EXT2_FORK, NULL) == 0 ) {
const char *temp;
temp = xar_attr_get(f, XAR_EXT2_FORK, "version");
version = strtol(temp, NULL, 10);
fd = open(file, O_RDONLY);
if( fd < 0 )
return 0;
ioctl(fd, EXT2_IOC_SETVERSION, &version);
}
if( xar_prop_get(f, XAR_ATTR_FORK, NULL) ) {
if( fd >= 0 ) close(fd);
return 0;
}
if( e2prop_get(f, "SecureDeletion", (char **)&tmp) == 0 )
flags |= EXT2_SECRM_FL;
if( e2prop_get(f, "Undelete", (char **)&tmp) == 0 )
flags |= EXT2_UNRM_FL ;
if( e2prop_get(f, "Compress", (char **)&tmp) == 0 )
flags |= EXT2_COMPR_FL ;
if( e2prop_get(f, "Synchronous", (char **)&tmp) == 0 )
flags |= EXT2_SYNC_FL ;
if( e2prop_get(f, "SystemImmutable", (char **)&tmp) == 0 )
flags |= EXT2_IMMUTABLE_FL ;
if( e2prop_get(f, "AppendOnly", (char **)&tmp) == 0 )
flags |= EXT2_APPEND_FL ;
if( e2prop_get(f, "NoDump", (char **)&tmp) == 0 )
flags |= EXT2_NODUMP_FL ;
if( e2prop_get(f, "NoAtime", (char **)&tmp) == 0 )
flags |= EXT2_NOATIME_FL ;
if( e2prop_get(f, "CompDirty", (char **)&tmp) == 0 )
flags |= EXT2_DIRTY_FL ;
if( e2prop_get(f, "CompBlock", (char **)&tmp) == 0 )
flags |= EXT2_COMPRBLK_FL ;
#ifdef EXT2_NOCOMPR_FL
if( e2prop_get(f, "NoCompBlock", (char **)&tmp) == 0 )
flags |= EXT2_NOCOMPR_FL ;
#endif
if( e2prop_get(f, "CompError", (char **)&tmp) == 0 )
flags |= EXT2_ECOMPR_FL ;
if( e2prop_get(f, "BTree", (char **)&tmp) == 0 )
flags |= EXT2_BTREE_FL ;
if( e2prop_get(f, "HashIndexed", (char **)&tmp) == 0 )
flags |= EXT2_INDEX_FL ;
if( e2prop_get(f, "iMagic", (char **)&tmp) == 0 )
flags |= EXT2_IMAGIC_FL ;
#ifdef EXT3_JOURNAL_DATA_FL
if( e2prop_get(f, "Journaled", (char **)&tmp) == 0 )
flags |= EXT3_JOURNAL_DATA_FL ;
#endif
if( e2prop_get(f, "NoTail", (char **)&tmp) == 0 )
flags |= EXT2_NOTAIL_FL ;
if( e2prop_get(f, "DirSync", (char **)&tmp) == 0 )
flags |= EXT2_DIRSYNC_FL ;
if( e2prop_get(f, "TopDir", (char **)&tmp) == 0 )
flags |= EXT2_TOPDIR_FL ;
if( fd < 0 ) {
fd = open(file, O_RDONLY);
if( fd < 0 )
return 0;
}
ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
close(fd);
#endif
return 0;
}

42
xar/lib/ext2.h Normal file
View File

@ -0,0 +1,42 @@
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Rob Braun <bbraun@synack.net>
* 26-Oct-2004
* Copyright (c) 2004 Rob Braun. All rights reserved.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_EXT2_H_
#define _XAR_EXT2_H_
#define XAR_ATTR_FORK "attribute"
int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len);
int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len);
#endif /* _XAR_EXT2_H_ */

344
xar/lib/fbsdattr.c Normal file
View File

@ -0,0 +1,344 @@
/*
* Copyright (c) 2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 28-Oct-2004
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#include <unistd.h>
#include "xar.h"
#include "arcmod.h"
#include "b64.h"
#include "io.h"
#include "archive.h"
#include <errno.h>
#include <string.h>
#include <sys/types.h>
/* FreeBSD Extended Attribute Headers */
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/extattr.h>
#endif
#ifdef HAVE_SYS_EXTATTR_H
struct _fbsdattr_context{
const char *file;
const char *attrname;
void *buf;
int off;
int bufsz;
int ns;
};
#define FBSDATTR_CONTEXT(x) ((struct _fbsdattr_context *)(x))
int32_t xar_fbsdattr_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
if( !FBSDATTR_CONTEXT(context)->buf ) {
FBSDATTR_CONTEXT(context)->bufsz = extattr_get_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attrname, NULL, 0);
if( FBSDATTR_CONTEXT(context)->bufsz < 0 )
return -1;
FBSDATTR_CONTEXT(context)->buf = malloc(FBSDATTR_CONTEXT(context)->bufsz);
if( !FBSDATTR_CONTEXT(context)->buf )
return -1;
FBSDATTR_CONTEXT(context)->bufsz = extattr_get_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attrname, FBSDATTR_CONTEXT(context)->buf, FBSDATTR_CONTEXT(context)->bufsz);
}
if( (FBSDATTR_CONTEXT(context)->bufsz - FBSDATTR_CONTEXT(context)->off) <= len ) {
int32_t ret;
ret = FBSDATTR_CONTEXT(context)->bufsz - FBSDATTR_CONTEXT(context)->off;
memcpy(buf, FBSDATTR_CONTEXT(context)->buf+FBSDATTR_CONTEXT(context)->off, ret);
FBSDATTR_CONTEXT(context)->off += ret;
return(ret);
} else {
memcpy(buf, FBSDATTR_CONTEXT(context)->buf+FBSDATTR_CONTEXT(context)->off, len);
FBSDATTR_CONTEXT(context)->buf += len;
return(len);
}
}
int32_t xar_fbsdattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
return extattr_set_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attrname, buf, len);
}
#endif
int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len)
{
#ifdef HAVE_SYS_EXTATTR_H
char *buf = NULL;
int ret, retval=0, bufsz, i;
#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
struct statvfs sfs;
#else
struct statfs sfs;
#endif
char *fsname = NULL;
int namespace = EXTATTR_NAMESPACE_USER;
struct _fbsdattr_context context;
memset(&context,0,sizeof(struct _fbsdattr_context));
/* no fbsdattr attributes for data to a buffer */
if(len)
return 0;
if(file == NULL)
return 0;
if( !xar_check_prop(x, "ea") )
return 0;
TRYAGAIN:
/* extattr_list_link()'s man page does not define the return
* value. The kernel source comments say 0 for success, -1 for
* failure. However, the observed behavior is # of bytes
* used, 0 if none, -1 on error.
* Also, errno is not documented to be set to anything useful
* if buf is too small. We are using an undocumented "feature"
* that if the data argument is NULL, it will return the number
* of bytes that would have been written (beware, return value
* does not indicate success or failure on it's own. Need to
* check the return value *and* the parameters.
*/
ret = extattr_list_link(file, namespace, NULL, 0);
if( ret < 0 ) {
if( namespace == EXTATTR_NAMESPACE_USER ) {
namespace = EXTATTR_NAMESPACE_SYSTEM;
goto TRYAGAIN;
} else {
/* If we get eperm on system namespace, don't
* return error. This is expected for normal
* users trying to archive the system namespace
* on freebsd 6.2. On netbsd 3.1, they've decided
* to return EOPNOTSUPP instead.
*/
if( errno == EPERM )
ret = 0;
else if( errno == EOPNOTSUPP )
ret = 0;
else {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error archiving EA");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION);
ret = 0;
}
goto BAIL;
}
}
bufsz = ret;
buf = malloc(bufsz);
if( !buf ) {
retval = -1;
goto BAIL;
}
memset(buf, 0, bufsz);
ret = extattr_list_link(file, namespace, buf, bufsz);
if( ret < 0 ) {
switch(errno) {
case ENOTSUP: retval=0; goto BAIL;
default: retval=-1; goto BAIL;
};
}
/* Even though 0 is a documented success, observed behavior
* indicates 0 means all perms were satisfied, etc, but
* no extattrs were found to list.
*/
if( ret == 0 ) {
if( namespace == EXTATTR_NAMESPACE_USER ) {
namespace = EXTATTR_NAMESPACE_SYSTEM;
goto TRYAGAIN;
} else {
/* If we get eperm on system namespace, don't
* return error. This is expected for normal
* users trying to archive the system namespace
* on freebsd 6.2. On netbsd 3.1, they've decided
* to return EOPNOTSUPP instead.
*/
if( errno == EPERM )
ret = 0;
else if( errno == EOPNOTSUPP )
ret = 0;
else {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error archiving EA");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION);
ret = 0;
}
goto BAIL;
}
}
#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
statvfs(file, &sfs);
#else
statfs(file, &sfs);
#endif
fsname = sfs.f_fstypename;
/* extattr_list_link() does not return the series of keys NUL
* separated, as documented in the man page. Instead, it
* returns things DNS style, with a 1 byte length followed by
* the key, repeated for as many keys as there are.
*/
for( i=0; i < ret; i++ ) {
char key[256];
char *ns;
char tempnam[1024];
xar_ea_t e;
memset(key, 0, sizeof(key));
memcpy(key, buf+i+1, buf[i]);
i += buf[i] ;
extattr_namespace_to_string(namespace, &ns);
memset(tempnam, 0, sizeof(tempnam));
snprintf(tempnam, sizeof(tempnam)-1, "%s.%s", ns, key);
FBSDATTR_CONTEXT(&context)->ns = namespace;
FBSDATTR_CONTEXT(&context)->file = file;
FBSDATTR_CONTEXT(&context)->attrname = key;
e = xar_ea_new(f, tempnam);
xar_ea_pset(f, e, "fstype", fsname);
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_fbsdattr_read, &context) < 0) {
ret = -1;
goto BAIL;
}
free(FBSDATTR_CONTEXT(&context)->buf);
FBSDATTR_CONTEXT(&context)->buf = NULL;
FBSDATTR_CONTEXT(&context)->off = 0;
}
if( namespace == EXTATTR_NAMESPACE_USER ) {
namespace = EXTATTR_NAMESPACE_SYSTEM;
free(buf);
buf = NULL;
goto TRYAGAIN;
}
BAIL:
free(buf);
return ret;
#else
return 0;
#endif
}
int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len)
{
#ifdef HAVE_SYS_EXTATTR_H
char *fsname = "bogus";
xar_prop_t p;
#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
struct statvfs sfs;
#else
struct statfs sfs;
#endif
int eaopt = 0;
struct _fbsdattr_context context;
memset(&context,0,sizeof(struct _fbsdattr_context));
/* no fbsdattr attributes for data to a buffer */
if(len){
return 0;
}
#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
statvfs(file, &sfs);
#else
statfs(file, &sfs);
#endif
fsname = sfs.f_fstypename;
for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) {
const char *fs = NULL;
const char *prop;
const char *eaname = NULL;
xar_prop_t tmpp;
prop = xar_prop_getkey(p);
if( strncmp(prop, XAR_EA_FORK, strlen(XAR_EA_FORK) != 0 ) )
continue;
if( strlen(prop) != strlen(XAR_EA_FORK) )
continue;
tmpp = xar_prop_pget(p, "fstype");
if( tmpp )
fs = xar_prop_getvalue(tmpp);
if( !eaopt && fs && strcmp(fs, fsname) != 0 ) {
continue;
}
tmpp = xar_prop_pget(p, "name");
if( tmpp )
eaname = xar_prop_getvalue(tmpp);
if( !eaname )
continue;
if( strncmp(eaname, "user.", 5) == 0 ) {
FBSDATTR_CONTEXT(&context)->ns = EXTATTR_NAMESPACE_USER;
FBSDATTR_CONTEXT(&context)->attrname = eaname + 5;
} else if( strncmp(eaname, "system.", 7) == 0 ) {
FBSDATTR_CONTEXT(&context)->ns = EXTATTR_NAMESPACE_SYSTEM;
FBSDATTR_CONTEXT(&context)->attrname = eaname + 7;
} else {
continue;
}
FBSDATTR_CONTEXT(&context)->file = file;
if (XAR(x)->attrcopy_from_heap(x, f, p, xar_fbsdattr_write, &context) < 0)
return -1;
}
#endif
return 0;
}

41
xar/lib/fbsdattr.h Normal file
View File

@ -0,0 +1,41 @@
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Rob Braun <bbraun@synack.net>
* 26-Oct-2004
* Copyright (c) 2004 Rob Braun. All rights reserved.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_FBSDATTR_H_
#define _XAR_FBSDATTR_H_
int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len);
int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len);
#endif /* _XAR_FBSDATTR_H_ */

1103
xar/lib/filetree.c Normal file

File diff suppressed because it is too large Load Diff

144
xar/lib/filetree.h Normal file
View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_FILETREE_H_
#define _XAR_FILETREE_H_
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#include <libxml/xmlwriter.h>
#include <libxml/xmlreader.h>
struct __xar_attr_t {
const char *key;
const char *value;
const char *ns;
const struct __xar_attr_t *next;
};
typedef const struct __xar_attr_t *xar_attr_t;
struct __xar_prop_t {
const char *key;
const char *value;
const struct __xar_prop_t *parent;
const struct __xar_prop_t *children;
const struct __xar_prop_t *next;
const struct __xar_attr_t *attrs;
const struct __xar_file_t *file;
const char *prefix;
const char *ns;
};
typedef const struct __xar_prop_t *xar_prop_t;
#include "ea.h"
struct __xar_file_t {
const struct __xar_prop_t *props;
const struct __xar_attr_t *attrs;
const char *prefix;
const char *ns;
const char *fspath;
char parent_extracted;
const struct __xar_file_t *parent;
const struct __xar_file_t *children;
const struct __xar_file_t *next;
xar_ea_t eas;
uint64_t nexteaid;
};
/* Overview:
* xar_file_t's exist within a xar_archive_t. xar_prop_t's exist
* within xar_file_t's and xar_attr_t's exist within xar_prop_t's
* and xar_file_t's.
* Basically, a xar_file_t is a container for xar_prop_t's.
* xar_attr_t's are things like: <foo bar=5>blah</foo>
* In this example, foo is the key of a xar_prop_t, and blah is
* the value. bar is the key of a xar_attr_t which is part of
* foo's xar_prop_t, and 5 is bar's value.
* xar_file_t's have xar_attr_t's for the case of:
* <file id=42>
* The file has an attribute of "id" with a value of "42".
*/
struct __xar_iter_t {
const void *iter;
char *path;
void *node;
int nochild;
};
/* Convenience macros for dereferencing the structs */
#define XAR_ATTR(x) ((struct __xar_attr_t *)(x))
#define XAR_FILE(x) ((struct __xar_file_t *)(x))
#define XAR_PROP(x) ((struct __xar_prop_t *)(x))
#define XAR_ITER(x) ((struct __xar_iter_t *)(x))
void xar_file_free(xar_file_t f);
xar_attr_t xar_attr_new(void);
int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value);
int32_t xar_attr_pset(xar_file_t f, xar_prop_t p, const char *key, const char *value);
const char *xar_attr_get(xar_file_t f, const char *prop, const char *key);
const char *xar_attr_pget(xar_file_t f, xar_prop_t p, const char *key);
void xar_attr_free(xar_attr_t a);
void xar_file_serialize(xar_file_t f, xmlTextWriterPtr writer);
xar_file_t xar_file_unserialize(xar_t x, xar_file_t parent, xmlTextReaderPtr reader);
xar_file_t xar_file_find(xar_file_t f, const char *path);
xar_file_t xar_file_new(xar_file_t f);
xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent);
void xar_file_free(xar_file_t f);
void xar_prop_serialize(xar_prop_t p, xmlTextWriterPtr writer);
int32_t xar_prop_unserialize(xar_file_t f, xar_prop_t parent, xmlTextReaderPtr reader);
void xar_prop_free(xar_prop_t p);
xar_prop_t xar_prop_new(xar_file_t f, xar_prop_t parent);
xar_prop_t xar_prop_pset(xar_file_t f, xar_prop_t p, const char *key, const char *value);
xar_prop_t xar_prop_find(xar_prop_t p, const char *key);
xar_prop_t xar_prop_pget(xar_prop_t p, const char *key);
const char *xar_prop_getkey(xar_prop_t p);
const char *xar_prop_getvalue(xar_prop_t p);
int32_t xar_prop_setkey(xar_prop_t p, const char *key);
int32_t xar_prop_setvalue(xar_prop_t p, const char *value);
xar_prop_t xar_prop_pfirst(xar_file_t f);
xar_prop_t xar_prop_pnext(xar_prop_t p);
void xar_prop_punset(xar_file_t f, xar_prop_t p);
#endif /* _XAR_FILETREE_H_ */

407
xar/lib/hash.c Normal file
View File

@ -0,0 +1,407 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <zlib.h>
#ifdef __APPLE__
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
#else
#include <openssl/evp.h>
#endif
#include "xar.h"
#include "hash.h"
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#pragma mark Hash Wrapper Object
#ifdef __APPLE__
CCDigestRef digestRef_from_name(const char* name, unsigned int *outHashSize) {
CCDigestRef result = NULL;
if (NULL != outHashSize)
*outHashSize = 0;
if (0 == strcasecmp(name, "sha512")) {
result = CCDigestCreate(kCCDigestSHA512);
if (NULL != outHashSize)
*outHashSize = CC_SHA512_DIGEST_LENGTH;
} else if (0 == strcasecmp(name, "sha256")) {
result = CCDigestCreate(kCCDigestSHA256);
if (NULL != outHashSize)
*outHashSize = CC_SHA256_DIGEST_LENGTH;
} else if (0 == strcasecmp(name, "sha") || !strcasecmp(name, "sha1")) {
result = CCDigestCreate(kCCDigestSHA1);
if (NULL != outHashSize)
*outHashSize = CC_SHA1_DIGEST_LENGTH;
#ifdef XAR_SUPPORT_MD5
} else if (0 == strcasecmp(name, "md5")) {
result = CCDigestCreate(kCCDigestMD5);
if (NULL != outHashSize)
*outHashSize = CC_MD5_DIGEST_LENGTH;
#endif // XAR_SUPPORT_MD5
}
return result;
}
#endif // __APPLE__
struct __xar_hash_t {
const char *digest_name;
void *context;
#ifdef __APPLE__
CCDigestRef digest;
#else
EVP_MD_CTX digest;
const EVP_MD *type;
#endif
unsigned int length;
};
#define HASH_CTX(x) ((struct __xar_hash_t *)(x))
xar_hash_t xar_hash_new(const char *digest_name, void *context) {
struct __xar_hash_t *hash = calloc(1, sizeof(struct __xar_hash_t));
if( ! hash )
return NULL; // errno will already be set
if( context )
HASH_CTX(hash)->context = context;
#ifdef __APPLE__
HASH_CTX(hash)->digest = digestRef_from_name(digest_name, &HASH_CTX(hash)->length);
#else
OpenSSL_add_all_digests();
HASH_CTX(hash)->type = EVP_get_digestbyname(digest_name);
EVP_DigestInit(&HASH_CTX(hash)->digest, HASH_CTX(hash)->type);
#endif
HASH_CTX(hash)->digest_name = strdup(digest_name);
return hash;
}
void *xar_hash_get_context(xar_hash_t hash) {
return HASH_CTX(hash)->context;
}
const char *xar_hash_get_digest_name(xar_hash_t hash) {
return HASH_CTX(hash)->digest_name;
}
void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte) {
#ifdef __APPLE__
CCDigestUpdate(HASH_CTX(hash)->digest, buffer, nbyte);
#else
EVP_DigestUpdate(&HASH_CTX(hash)->digest, buffer, nbyte);
#endif
}
void *xar_hash_finish(xar_hash_t hash, size_t *nbyte) {
#ifdef __APPLE__
void *buffer = calloc(1, CC_SHA512_DIGEST_LENGTH); // current biggest digest size This is what OpenSSL uses
#else
void *buffer = calloc(1, EVP_MAX_MD_SIZE);
#endif
if( ! buffer )
return NULL;
#ifdef __APPLE__
CCDigestFinal(HASH_CTX(hash)->digest, buffer);
CCDigestDestroy(HASH_CTX(hash)->digest);
#else
EVP_DigestFinal(&HASH_CTX(hash)->digest, buffer, &HASH_CTX(hash)->length);
#endif
*nbyte = HASH_CTX(hash)->length;
free((void *)HASH_CTX(hash)->digest_name);
free((void *)hash);
return buffer;
}
#undef HASH_CTX
#pragma mark datamod
struct _hash_context {
xar_hash_t archived;
xar_hash_t unarchived;
uint64_t count;
};
#define CONTEXT(x) ((struct _hash_context *)(*x))
static char *_xar_format_hash(const unsigned char* m,unsigned int len) {
char *result = malloc((2*len)+1);
char hexValue[3];
unsigned int itr = 0;
result[0] = '\0';
for(itr = 0;itr < len;itr++) {
sprintf(hexValue,"%02x",m[itr]);
strncat(result,hexValue,2);
}
return result;
}
int32_t xar_hash_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
return xar_hash_fromheap_out(x,f,p,*in,*inlen,context);
}
int32_t xar_hash_fromheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context) {
if (!context)
return 0;
if(!CONTEXT(context) || (! CONTEXT(context)->unarchived) ) {
const char *opt;
xar_prop_t tmpp;
opt = NULL;
tmpp = xar_prop_pget(p, "extracted-checksum");
if( tmpp ) {
opt = xar_attr_pget(f, tmpp, "style");
} else {
// The xar-1.7 release in OS X Yosemite accidentally wrote <unarchived-checksum>
// instead of <extracted-checksum>. Since archives like this are now in the wild,
// we check for both.
tmpp = xar_prop_pget(p, "unarchived-checksum");
if( tmpp ) {
opt = xar_attr_pget(f, tmpp, "style");
}
}
// If there's an <archived-checksum> and no <extracted-checksum> (or
// <unarchived-checksum>), the archive is malformed.
if ( !opt && xar_prop_pget(p, "archived-checksum") ) {
xar_err_new(x);
xar_err_set_string(x, "No extracted-checksum");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
if( !opt )
opt = xar_opt_get(x, XAR_OPT_FILECKSUM);
if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) )
return 0;
if (!CONTEXT(context)) {
*context = calloc(1, sizeof(struct _hash_context));
if( ! *context )
return -1;
}
if( ! CONTEXT(context)->unarchived ) {
CONTEXT(context)->unarchived = xar_hash_new(opt, NULL);
if( ! CONTEXT(context)->unarchived ) {
free(*context);
*context = NULL;
return -1;
}
}
}
if( inlen == 0 )
return 0;
CONTEXT(context)->count += inlen;
xar_hash_update(CONTEXT(context)->unarchived, in, inlen);
return 0;
}
int32_t xar_hash_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
return xar_hash_toheap_out(x,f,p,*in,*inlen,context);
}
int32_t xar_hash_toheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context) {
const char *opt;
xar_prop_t tmpp;
opt = NULL;
tmpp = xar_prop_pget(p, "archived-checksum");
if( tmpp )
opt = xar_attr_pget(f, tmpp, "style");
if( !opt )
opt = xar_opt_get(x, XAR_OPT_FILECKSUM);
if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) )
return 0;
if( ! CONTEXT(context) ) {
*context = calloc(1, sizeof(struct _hash_context));
if( ! *context )
return -1;
}
if( ! CONTEXT(context)->archived ) {
CONTEXT(context)->archived = xar_hash_new(opt, NULL);
if( ! CONTEXT(context)->archived ) {
free(*context);
*context = NULL;
return -1;
}
}
if( inlen == 0 )
return 0;
CONTEXT(context)->count += inlen;
xar_hash_update(CONTEXT(context)->archived, in, inlen);
return 0;
}
int32_t xar_hash_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
const char *archived_style = NULL, *unarchived_style = NULL;
size_t archived_length = -1, unarchived_length = -1;
void *archived_hash = NULL, *unarchived_hash = NULL;
if( ! CONTEXT(context) )
return 0;
else if( CONTEXT(context)->count == 0 )
goto DONE;
archived_style = strdup(xar_hash_get_digest_name(CONTEXT(context)->archived));
unarchived_style = strdup(xar_hash_get_digest_name(CONTEXT(context)->unarchived));
archived_hash = xar_hash_finish(CONTEXT(context)->archived, &archived_length);
unarchived_hash = xar_hash_finish(CONTEXT(context)->unarchived, &unarchived_length);
char *str;
xar_prop_t tmpp;
str = _xar_format_hash(archived_hash, archived_length);
if( f ) {
tmpp = xar_prop_pset(f, p, "archived-checksum", str);
if( tmpp )
xar_attr_pset(f, tmpp, "style", archived_style);
}
free(str);
str = _xar_format_hash(unarchived_hash, unarchived_length);
if( f ) {
tmpp = xar_prop_pset(f, p, "extracted-checksum", str);
if( tmpp )
xar_attr_pset(f, tmpp, "style", unarchived_style);
}
free(str);
DONE:
free((void *)archived_style);
free((void *)unarchived_style);
free(archived_hash);
free(unarchived_hash);
free(*context);
*context = NULL;
return 0;
}
int32_t xar_hash_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
if(!CONTEXT(context))
return 0;
int32_t result = 0;
const char *archived_hash = NULL, *archived_style = NULL;
// Fetch the existing hash from the archive
if( CONTEXT(context)->archived ) {
xar_prop_t tmpp = xar_prop_pget(p, "archived-checksum");
if( tmpp ) {
archived_style = xar_attr_pget(f, tmpp, "style");
archived_hash = xar_prop_getvalue(tmpp);
}
// We have the fetched hash; now get the calculated hash
if( archived_hash && archived_style ) {
size_t calculated_length = -1;
const char *calculated_style = strdup(xar_hash_get_digest_name(CONTEXT(context)->archived));
void *calculated_buffer = xar_hash_finish(CONTEXT(context)->archived, &calculated_length);
char *calculated_hash = _xar_format_hash(calculated_buffer, calculated_length);
free(calculated_buffer);
// Compare
int hash_match = ( strcmp(archived_hash, calculated_hash) == 0 );
int style_match = (strcmp(archived_style, calculated_style) == 0 );
if( ! hash_match || ! style_match ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_formatted_string(x, "archived-checksum %s's do not match", archived_style);
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
result = -1;
}
free((void *)calculated_style);
free(calculated_hash);
}
}
// Clean up the unarchived hash as well, if we have one
if( CONTEXT(context)->unarchived ) {
size_t length = -1;
void *hash = xar_hash_finish(CONTEXT(context)->unarchived, &length);
free(hash);
}
if(*context) {
free(*context);
*context = NULL;
}
return result;
}

63
xar/lib/hash.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_HASH_H_
#define _XAR_HASH_H_
#include "filetree.h"
#pragma mark Hash Wrapper Object
typedef struct __xar_hash_t *xar_hash_t;
xar_hash_t xar_hash_new(const char *digest_name, void *context);
void *xar_hash_get_context(xar_hash_t hash);
const char *xar_hash_get_digest_name(xar_hash_t hash); // returns inner pointer
void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte);
void *xar_hash_finish(xar_hash_t hash, size_t *nbyte);
#pragma mark datamod
int32_t xar_hash_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int32_t xar_hash_fromheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context);
int32_t xar_hash_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
int32_t xar_hash_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int32_t xar_hash_toheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context);
int32_t xar_hash_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
#endif /* _XAR_HASH_H_ */

871
xar/lib/io.c Normal file
View File

@ -0,0 +1,871 @@
/*
* Copyright (c) 2005-2008 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#define _FILE_OFFSET_BITS 64
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/types.h>
#include <assert.h>
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include "xar.h"
#include "filetree.h"
#include "archive.h"
#include "io.h"
#include "zxar.h"
#include "bzxar.h"
#include "lzmaxar.h"
#include "hash.h"
#include "script.h"
#include "macho.h"
#include "util.h"
#include "data.h"
#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX)
#define LLONG_MAX LONG_LONG_MAX
#endif
#if !defined(LLONG_MIN) && defined(LONG_LONG_MIN)
#define LLONG_MIN LONG_LONG_MIN
#endif
// IMPORTANT: Keep datamod count up to date in io.h!
struct datamod xar_datamods[] = {
{ xar_hash_fromheap_in,
xar_hash_fromheap_out,
xar_hash_fromheap_done,
xar_hash_toheap_in,
xar_hash_toheap_out,
xar_hash_toheap_done
},
{ (fromheap_in)NULL,
(fromheap_out)NULL,
(fromheap_done)NULL,
xar_script_in,
(toheap_out)NULL,
xar_script_done
},
{ (fromheap_in)NULL,
(fromheap_out)NULL,
(fromheap_done)NULL,
NULL,
(toheap_out)NULL,
NULL
},
{ xar_gzip_fromheap_in,
(fromheap_out)NULL,
xar_gzip_fromheap_done,
xar_gzip_toheap_in,
(toheap_out)NULL,
xar_gzip_toheap_done
},
{ xar_bzip_fromheap_in,
(fromheap_out)NULL,
xar_bzip_fromheap_done,
xar_bzip_toheap_in,
(toheap_out)NULL,
xar_bzip_toheap_done
},
{ xar_lzma_fromheap_in,
(fromheap_out)NULL,
xar_lzma_fromheap_done,
xar_lzma_toheap_in,
(toheap_out)NULL,
xar_lzma_toheap_done
}
};
size_t xar_io_get_rsize(xar_t x) {
size_t bsize;
const char *opt = NULL;
opt = xar_opt_get(x, "rsize");
if( !opt ) {
bsize = 4096;
} else {
bsize = strtol(opt, NULL, 0);
if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) {
bsize = 4096;
}
}
return bsize;
}
off_t xar_io_get_heap_base_offset(xar_t x) {
return XAR(x)->toc_count + sizeof(xar_header_t);
}
size_t xar_io_get_toc_checksum_length_for_type(const char *type) {
if( !type ) {
return 0;
} else if( strcmp(type, XAR_OPT_VAL_NONE) == 0 ) {
return 0;
} else if( strcmp(type, XAR_OPT_VAL_SHA1) == 0 ) {
return 20;
} else if( strcmp(type, XAR_OPT_VAL_SHA256) == 0 ) {
return 32;
} else if( strcmp(type, XAR_OPT_VAL_SHA512) == 0 ) {
return 64;
} else if( strcmp(type, XAR_OPT_VAL_MD5) == 0 ) {
// Left in place regardless of XAR_SUPPORT_MD5 for proper archive parsing
return 16;
} else {
return 0;
}
}
size_t xar_io_get_toc_checksum_length(xar_t x) {
switch(XAR(x)->header.cksum_alg) {
case XAR_CKSUM_NONE:
// Left in place even though it is no longer supported for archive parsing
return 0;
case XAR_CKSUM_SHA1:
return 20;
case XAR_CKSUM_SHA256:
return 32;
case XAR_CKSUM_SHA512:
return 64;
case XAR_CKSUM_MD5:
// Left in place regardless of XAR_SUPPORT_MD5 for proper archive parsing
return 16;
default:
fprintf(stderr, "Unknown hashing algorithm, skipping\n");
return 0;
};
}
off_t xar_io_get_file_offset(xar_t x, xar_file_t f, xar_prop_t p) {
xar_prop_t tmpp;
const char *opt = NULL;
tmpp = xar_prop_pget(p, "offset");
if( tmpp ) {
opt = xar_prop_getvalue(tmpp);
if (opt == NULL){
return -1;
}
return strtoll(opt, NULL, 0);
} else {
return -1;
}
}
int64_t xar_io_get_length(xar_prop_t p) {
const char *opt = NULL;
int64_t fsize = 0;
xar_prop_t tmpp;
tmpp = xar_prop_pget(p, "length");
if( tmpp )
opt = xar_prop_getvalue(tmpp);
if( !opt ) {
return 0;
} else {
fsize = strtoll(opt, NULL, 10);
if( ((fsize == LLONG_MAX) || (fsize == LLONG_MIN)) && (errno == ERANGE) ) {
return -1;
}
}
return fsize;
}
static void xar_io_seek(xar_t x, xar_file_t f, off_t seekoff) {
int r;
if( XAR(x)->fd >= 0 ) {
r = lseek(XAR(x)->fd, seekoff, SEEK_SET);
if( r == -1 ) {
if( errno == ESPIPE ) {
ssize_t rr;
char *buf;
unsigned int len;
len = seekoff - XAR(x)->toc_count;
len -= sizeof(xar_header_t);
if( XAR(x)->heap_offset > len ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Unable to seek");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
len -= XAR(x)->heap_offset;
buf = malloc(len);
assert(buf);
rr = xar_read_fd(XAR(x)->fd, buf, len);
if( rr < len ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Unable to seek");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
XAR(x)->heap_offset += rr;
free(buf);
}
} else {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Unable to seek");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
}
}
}
int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, xar_prop_t p, read_callback rcb, void *context) {
int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod));
void *modulecontext[modulecount];
int r, i;
size_t bsize, rsize;
int64_t readsize=0, writesize=0, inc = 0, this_write=0;
void *inbuf;
char *tmpstr = NULL;
const char *opt = NULL, *csum = NULL;
off_t orig_heap_offset = XAR(x)->heap_offset;
xar_file_t tmpf = NULL;
xar_prop_t tmpp = NULL;
memset(modulecontext, 0, sizeof(void*)*modulecount);
bsize = xar_io_get_rsize(x);
r = 1;
// (Apple) allocate once
inbuf = malloc(bsize);
if( !inbuf )
return -1;
while(r != 0) {
r = rcb(x, f, inbuf, bsize, context);
if( r < 0 ) {
free(inbuf);
return -1;
}
readsize+=r;
inc += r;
rsize = r;
/* filter the data through the in modules */
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].th_in ) {
xar_datamods[i].th_in(x, f, p, &inbuf, &rsize, &(modulecontext[i]));
}
}
/* filter the data through the out modules */
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].th_out )
xar_datamods[i].th_out(x, f, p, inbuf, rsize, &(modulecontext[i]));
}
size_t written = 0;
if( rsize != 0 ) {
while(written < rsize) {
this_write = xar_write_fd(XAR(x)->heap_fd, inbuf, rsize);
if( this_write < 0 ) {
xar_err_new(x);
xar_err_set_string(x, "write(2) error when writing to heap");
xar_err_set_errno(x, errno);
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
free(inbuf);
return -1;
}
written += this_write;
}
}
XAR(x)->heap_offset += written;
writesize += written;
}
free(inbuf);
/* If size is 0, don't bother having anything in the heap */
if( readsize == 0 ) {
XAR(x)->heap_offset = orig_heap_offset;
lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].th_done )
xar_datamods[i].th_done(x, f, p, &(modulecontext[i]));
}
return 0;
}
/* finish up anything that still needs doing */
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].th_done )
xar_datamods[i].th_done(x, f, p, &(modulecontext[i]));
}
XAR(x)->heap_len += writesize;
tmpp = xar_prop_pget(p, "archived-checksum");
if( tmpp )
csum = xar_prop_getvalue(tmpp);
if( csum )
tmpf = xmlHashLookup(XAR(x)->csum_hash, BAD_CAST(csum));
if( tmpf ) {
const char *attr = xar_prop_getkey(p);
opt = xar_opt_get(x, XAR_OPT_LINKSAME);
if( opt && (strcmp(attr, "data") == 0) ) {
const char *id = xar_attr_pget(tmpf, NULL, "id");
xar_prop_pset(f, NULL, "type", "hardlink");
tmpp = xar_prop_pfirst(f);
if( tmpp )
tmpp = xar_prop_find(tmpp, "type");
if( tmpp )
xar_attr_pset(f, tmpp, "link", id);
xar_prop_pset(tmpf, NULL, "type", "hardlink");
tmpp = xar_prop_pfirst(tmpf);
if( tmpp )
tmpp = xar_prop_find(tmpp, "type");
if( tmpp )
xar_attr_pset(tmpf, tmpp, "link", "original");
tmpp = xar_prop_pfirst(f);
if( tmpp )
tmpp = xar_prop_find(tmpp, "data");
xar_prop_punset(f, tmpp);
XAR(x)->heap_offset = orig_heap_offset;
lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
XAR(x)->heap_len -= writesize;
return 0;
}
opt = xar_opt_get(x, XAR_OPT_COALESCE);
if( opt ) {
long long tmpoff;
const char *offstr = NULL;
tmpp = xar_prop_pfirst(tmpf);
if( tmpp ) {
const char *key;
key = xar_prop_getkey(p);
tmpp = xar_prop_find(tmpp, key);
}
if( tmpp )
tmpp = xar_prop_pget(tmpp, "offset");
if( tmpp )
offstr = xar_prop_getvalue(tmpp);
if( offstr ) {
tmpoff = strtoll(offstr, NULL, 10);
XAR(x)->heap_offset = orig_heap_offset;
lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
orig_heap_offset = tmpoff;
XAR(x)->heap_len -= writesize;
}
}
} else if( csum ) {
xmlHashAddEntry(XAR(x)->csum_hash, BAD_CAST(csum), XAR_FILE(f));
} else {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "No archived-checksum");
xar_err_callback(x, XAR_SEVERITY_WARNING, XAR_ERR_ARCHIVE_CREATION);
}
asprintf(&tmpstr, "%"PRIu64, readsize);
xar_prop_pset(f, p, "size", tmpstr);
free(tmpstr);
asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset);
xar_prop_pset(f, p, "offset", tmpstr);
free(tmpstr);
tmpstr = (char *)xar_opt_get(x, XAR_OPT_COMPRESSION);
if( tmpstr && (strcmp(tmpstr, XAR_OPT_VAL_NONE) == 0) ) {
xar_prop_pset(f, p, "encoding", NULL);
tmpp = xar_prop_pget(p, "encoding");
if( tmpp )
xar_attr_pset(f, tmpp, "style", "application/octet-stream");
}
asprintf(&tmpstr, "%"PRIu64, writesize);
xar_prop_pset(f, p, "length", tmpstr);
free(tmpstr);
return 0;
}
/* xar_copy_from_heap
* This is the arcmod extraction entry point for extracting the file's
* data from the heap file.
* It is assumed the heap_fd is already positioned appropriately.
*/
int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, xar_prop_t p, write_callback wcb, void *context) {
int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod));
void *modulecontext[modulecount];
int r, i;
size_t bsize, def_bsize;
int64_t fsize, inc = 0, seekoff, readsofar = 0;
void *inbuf;
const char *opt;
xar_prop_t tmpp;
memset(modulecontext, 0, sizeof(void*)*modulecount);
def_bsize = xar_io_get_rsize(x);
seekoff = xar_io_get_file_offset(x, f, p);
if( seekoff == -1 ) {
wcb(x, f, NULL, 0, context);
return 0;
} else if( ((seekoff == LLONG_MAX) || (seekoff == LLONG_MIN)) && (errno == ERANGE) ) {
return -1;
}
seekoff += xar_io_get_heap_base_offset(x);
xar_io_seek(x, f, seekoff);
fsize = xar_io_get_length(p);
if( fsize == 0 )
return 0;
if( fsize < 0 )
return -1;
bsize = def_bsize;
inbuf = malloc(bsize);
if( !inbuf ) {
return -1;
}
while(1) {
/* Size has been reached */
if( fsize == inc )
break;
if( (fsize - inc) < bsize )
bsize = fsize - inc;
r = read(XAR(x)->fd, inbuf, bsize);
if( r == 0 )
break;
if( (r < 0) && (errno == EINTR) )
continue;
if( r < 0 ) {
free(inbuf);
return -1;
}
XAR(x)->heap_offset += r;
inc += r;
bsize = r;
/* filter the data through the in modules */
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].fh_in ) {
int32_t ret;
ret = xar_datamods[i].fh_in(x, f, p, &inbuf, &bsize, &(modulecontext[i]));
if( ret < 0 ) {
free(inbuf); // (Apple) don't leak inbuf
return -1;
}
}
}
/* Only due the write phase, if there is a write function to call */
if(wcb){
/* filter the data through the out modules */
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].fh_out ) {
int32_t ret;
ret = xar_datamods[i].fh_out(x, f, p, inbuf, bsize, &(modulecontext[i]));
if( ret < 0 ) {
free(inbuf); // (Apple) don't leak inbuf
return -1;
}
}
}
wcb(x, f, inbuf, bsize, context);
}
readsofar += bsize;
if (DATA_CONTEXT(context)->progress)
DATA_CONTEXT(context)->progress(x, f, readsofar);
bsize = def_bsize;
}
free(inbuf);
/* finish up anything that still needs doing */
for( i = 0; i < modulecount; i++) {
if( xar_datamods[i].fh_done ) {
int32_t ret;
ret = xar_datamods[i].fh_done(x, f, p, &(modulecontext[i]));
if( ret < 0 )
return ret;
}
}
return 0;
}
/* xar_attrcopy_from_heap_to_heap
* This does a simple copy of the heap data from one head (read-only) to another heap (write only).
* This does not set any properties or attributes of the file, so this should not be used alone.
*/
int32_t xar_attrcopy_from_heap_to_heap(xar_t xsource, xar_file_t fsource, xar_prop_t p, xar_t xdest, xar_file_t fdest){
int r, off;
size_t bsize;
int64_t fsize, inc = 0, seekoff, writesize=0;
off_t orig_heap_offset = XAR(xdest)->heap_offset;
void *inbuf;
const char *opt;
char *tmpstr = NULL;
xar_prop_t tmpp;
bsize = xar_io_get_rsize(xsource);
seekoff = xar_io_get_file_offset(xsource, fsource, p);
if( seekoff < 0 )
return -1;
seekoff += XAR(xsource)->toc_count + sizeof(xar_header_t);
xar_io_seek(xsource, fsource, seekoff);
fsize = xar_io_get_length(p);
if( fsize == 0 )
return 0;
if( fsize < 0 )
return -1;
inbuf = malloc(bsize);
if( !inbuf ) {
return -1;
}
while(1) {
/* Size has been reached */
if( fsize == inc )
break;
if( (fsize - inc) < bsize )
bsize = fsize - inc;
r = read(XAR(xsource)->fd, inbuf, bsize);
if( r == 0 )
break;
if( (r < 0) && (errno == EINTR) )
continue;
if( r < 0 ) {
free(inbuf);
return -1;
}
XAR(xsource)->heap_offset += r;
inc += r;
bsize = r;
off = 0;
do {
r = write(XAR(xdest)->heap_fd, ((char *)inbuf)+off, r-off );
off += r;
writesize += r;
} while( off < r );
XAR(xdest)->heap_offset += off;
XAR(xdest)->heap_len += off;
}
asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset);
opt = xar_prop_getkey(p);
tmpp = xar_prop_pfirst(fdest);
if( tmpp )
tmpp = xar_prop_find(tmpp, opt);
if( tmpp )
xar_prop_pset(fdest, tmpp, "offset", tmpstr);
free(tmpstr);
free(inbuf);
/* It is the caller's responsibility to copy the attributes of the file, etc, this only copies the data in the heap */
return 0;
}
static int32_t flush_stream(xar_stream *stream) {
xar_stream_state_t *state = (xar_stream_state_t *)(stream->state);
if( state->pending_buf && stream->avail_out ) {
size_t len = state->pending_buf_size;
if( stream->avail_out < len ) {
len = stream->avail_out;
}
memcpy(stream->next_out, state->pending_buf, len);
stream->next_out += len;
stream->avail_out -= len;
stream->total_out += len;
if( state->pending_buf_size == len ) {
state->pending_buf_size = 0;
free(state->pending_buf);
state->pending_buf = NULL;
} else if( state->pending_buf_size > len ) {
state->pending_buf_size -= len;
memcpy(state->pending_buf, state->pending_buf + len, state->pending_buf_size);
}
}
return XAR_STREAM_OK;
}
static int32_t write_to_stream(void *inbuf, size_t inlen, xar_stream *stream) {
xar_stream_state_t *state = (xar_stream_state_t *)stream->state;
size_t len = inlen;
if( stream->avail_out < len ) {
len = stream->avail_out;
}
memcpy(stream->next_out, inbuf, len);
stream->next_out += len;
stream->avail_out -= len;
stream->total_out += len;
if( inlen > len ) {
state->pending_buf_size = inlen - len;
state->pending_buf = malloc(state->pending_buf_size);
memcpy(state->pending_buf, ((char *)inbuf) + len, state->pending_buf_size);
}
return XAR_STREAM_OK;
}
int32_t xar_attrcopy_from_heap_to_stream_init(xar_t x, xar_file_t f, xar_prop_t p, xar_stream *stream) {
xar_stream_state_t *state;
off_t seekoff;
seekoff = xar_io_get_file_offset(x, f, p);
if( seekoff < 0 )
return XAR_STREAM_ERR;
state = calloc(1, sizeof(xar_stream_state_t));
if( !state ) {
return XAR_STREAM_ERR;
}
stream->state = (void*)state;
state->bsize = xar_io_get_rsize(x);
state->modulecount = (sizeof(xar_datamods)/sizeof(struct datamod));
state->modulecontext = calloc(1, sizeof(void*)*state->modulecount);
if( !state->modulecontext ) {
free(state);
return XAR_STREAM_ERR;
}
seekoff += XAR(x)->toc_count + sizeof(xar_header_t);
xar_io_seek(x, f, seekoff);
stream->total_in = 0;
stream->total_out = 0;
state->fsize = xar_io_get_length(p);
if(state->fsize == 0) {
return XAR_STREAM_OK;
} else if(state->fsize == -1) {
free(state->modulecontext);
free(state);
return XAR_STREAM_ERR;
}
state->pending_buf = NULL;
state->pending_buf_size = 0;
state->x = x;
state->f = f;
state->p = p;
return XAR_STREAM_OK;
}
int32_t xar_attrcopy_from_heap_to_stream(xar_stream *stream) {
xar_stream_state_t *state = stream->state;
int r, i;
size_t bsize;
void *inbuf;
if( state->pending_buf_size ) {
return flush_stream(stream);
}
bsize = state->bsize;
inbuf = malloc(bsize);
if( !inbuf ) {
return XAR_STREAM_ERR;
}
/* Size has been reached */
if( state->fsize == stream->total_in ) {
free(inbuf);
return XAR_STREAM_END;
}
if( (state->fsize - stream->total_in) < bsize )
bsize = state->fsize - stream->total_in;
r = read(XAR(state->x)->fd, inbuf, bsize);
if( r == 0 ) {
free(inbuf);
return XAR_STREAM_END;
}
if( (r < 0) && (errno == EINTR) ) {
free(inbuf);
return XAR_STREAM_OK;
}
if( r < 0 ) {
free(inbuf);
return XAR_STREAM_ERR;
}
XAR(state->x)->heap_offset += r;
stream->total_in += r;
bsize = r;
/* filter the data through the in modules */
for( i = 0; i < state->modulecount; i++) {
if( xar_datamods[i].fh_in ) {
int32_t ret;
ret = xar_datamods[i].fh_in(state->x, state->f, state->p, &inbuf, &bsize, &(state->modulecontext[i]));
if( ret < 0 )
return XAR_STREAM_ERR;
}
}
/* filter the data through the out modules */
for( i = 0; i < state->modulecount; i++) {
if( xar_datamods[i].fh_out ) {
int32_t ret;
ret = xar_datamods[i].fh_out(state->x, state->f, state->p, inbuf, bsize, &(state->modulecontext[i]));
if( ret < 0 )
return XAR_STREAM_ERR;
}
}
write_to_stream(inbuf, bsize, stream);
free(inbuf);
return XAR_STREAM_OK;
}
int32_t xar_attrcopy_from_heap_to_stream_end(xar_stream *stream) {
xar_stream_state_t *state = (xar_stream_state_t *)stream->state;
int i;
/* finish up anything that still needs doing */
for( i = 0; i < state->modulecount; i++) {
if( xar_datamods[i].fh_done ) {
int32_t ret;
ret = xar_datamods[i].fh_done(state->x, state->f, state->p, &(state->modulecontext[i]));
if( ret < 0 )
return ret;
}
}
if( state->pending_buf ) {
free(state->pending_buf);
}
free(state->modulecontext);
free(state);
return XAR_STREAM_OK;
}
/* xar_heap_to_archive
* x: archive to operate on
* Returns 0 on success, -1 on error
* Summary: copies the heap into the archive.
*/
int32_t xar_heap_to_archive(xar_t x) {
long bsize;
ssize_t r;
int off;
const char *opt;
char *b;
opt = xar_opt_get(x, "rsize");
if( !opt ) {
bsize = 4096;
} else {
bsize = strtol(opt, NULL, 0);
if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) {
bsize = 4096;
}
}
b = calloc(1, bsize);
if( !b ) return -1;
lseek(XAR(x)->heap_fd, 0, SEEK_SET);
while(1) {
r = read(XAR(x)->heap_fd, b, bsize);
if( r == 0 ) break;
if( (r < 0) && (errno == EINTR) ) continue;
if( r < 0 ) {
free(b);
return -1;
}
size_t writesize = r;
off = 0;
do {
r = write(XAR(x)->fd, b+off, writesize-off);
if( (r < 0) && (errno != EINTR) ) {
free(b);
return -1;
}
off += r;
} while( off < bsize && off < writesize ); // writesize should always be less than bsize.
}
free(b);
return 0;
}

96
xar/lib/io.h Normal file
View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_IO_H_
#define _XAR_IO_H_
#include "archive.h"
//typedef int (*read_callback)(xar_t, xar_file_t, void *, size_t, void *context);
//typedef int (*write_callback)(xar_t, xar_file_t, void *, size_t, void *context);
typedef int (*fromheap_in)(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
typedef int (*fromheap_out)(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context);
typedef int (*fromheap_done)(xar_t x, xar_file_t f, xar_prop_t p, void **context);
typedef int (*toheap_in)(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
typedef int (*toheap_out)(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context);
typedef int (*toheap_done)(xar_t x, xar_file_t f, xar_prop_t p, void **context);
struct datamod {
fromheap_in fh_in;
fromheap_out fh_out;
fromheap_done fh_done;
toheap_in th_in;
toheap_out th_out;
toheap_done th_done;
};
typedef struct xar_stream_state {
char *pending_buf;
size_t pending_buf_size;
void **modulecontext;
int modulecount;
size_t bsize;
int64_t fsize;
xar_t x;
xar_file_t f;
xar_prop_t p;
} xar_stream_state_t;
size_t xar_io_get_rsize(xar_t x);
off_t xar_io_get_heap_base_offset(xar_t x);
size_t xar_io_get_toc_checksum_length_for_type(const char *type);
size_t xar_io_get_toc_checksum_length(xar_t x);
off_t xar_io_get_file_offset(xar_t x, xar_file_t f, xar_prop_t p);
int64_t xar_io_get_length(xar_prop_t p);
int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, xar_prop_t p, read_callback rcb, void *context);
int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, xar_prop_t p, write_callback wcb, void *context);
int32_t xar_attrcopy_from_heap_to_heap(xar_t xsource, xar_file_t fsource, xar_prop_t p, xar_t xdest, xar_file_t fdest);
int32_t xar_attrcopy_from_heap_to_stream_init(xar_t x, xar_file_t f, xar_prop_t p, xar_stream *stream);
int32_t xar_attrcopy_from_heap_to_stream(xar_stream *stream);
int32_t xar_attrcopy_from_heap_to_stream_end(xar_stream *stream);
int32_t xar_heap_to_archive(xar_t x);
#pragma mark internal
// IMPORTANT: Keep count synchronized with declaration in io.c!
extern struct datamod xar_datamods[6];
#endif /* _XAR_IO_H_ */

35
xar/lib/libxar.la.in Normal file
View File

@ -0,0 +1,35 @@
# libxar.la - a libtool library file
# Generated by Xar 1.8dev for libtool
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='@LIBXAR_SNAME@'
# Names of this library.
library_names='@LIBXAR_SNAME@ @LIBXAR_LNAME@'
# The name of the static archive.
old_library='@LIBXAR_ANAME@'
# Libraries that this one depends upon.
dependency_libs='-lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm'
# Version information for libxar.
current=0
age=0
revision=1
# Is this an already installed library?
installed=no
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/usr/local/lib'

35
xar/lib/libxar.la.in.in Normal file
View File

@ -0,0 +1,35 @@
# libxar.la - a libtool library file
# Generated by @PACKAGE_STRING@ for libtool
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='@LIBXAR_SNAME@'
# Names of this library.
library_names='@LIBXAR_SNAME@ @LIBXAR_LNAME@'
# The name of the static archive.
old_library='@LIBXAR_ANAME@'
# Libraries that this one depends upon.
dependency_libs='@LIBS@'
# Version information for libxar.
current=0
age=0
revision=@LIB_REV@
# Is this an already installed library?
installed=no
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='@LIBDIR@'

275
xar/lib/linuxattr.c Normal file
View File

@ -0,0 +1,275 @@
/*
* Copyright (c) 2004 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 26-Oct-2004
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <libgen.h>
#include "xar.h"
#include "arcmod.h"
#include "b64.h"
#include <errno.h>
#include <string.h>
#include "util.h"
#include "linuxattr.h"
#include "io.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_STATFS_H /* Nonexistant future OS needs this */
#include <sys/statfs.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_XATTR_H
#include <sys/xattr.h>
#endif
#ifndef EXT3_SUPER_MAGIC
#define EXT3_SUPER_MAGIC 0xEF53
#endif
#ifndef JFS_SUPER_MAGIC
#define JFS_SUPER_MAGIC 0x3153464a
#endif
#ifndef REISERFS_SUPER_MAGIC
#define REISERFS_SUPER_MAGIC 0x52654973
#endif
#ifndef XFS_SUPER_MAGIC
#define XFS_SUPER_MAGIC 0x58465342
#endif
#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__)
struct _linuxattr_context{
const char *file;
const char *attrname;
xar_ea_t ea;
void *buf;
int off;
int bufsz;
};
#define LINUXATTR_CONTEXT(x) ((struct _linuxattr_context *)(x))
int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void * buf, size_t len, void *context) {
if( !LINUXATTR_CONTEXT(context)->buf ) {
int r;
LINUXATTR_CONTEXT(context)->bufsz = 1024;
AGAIN2:
LINUXATTR_CONTEXT(context)->buf = malloc(LINUXATTR_CONTEXT(context)->bufsz);
if(!LINUXATTR_CONTEXT(context)->buf)
goto AGAIN2;
memset(LINUXATTR_CONTEXT(context)->buf, 0, LINUXATTR_CONTEXT(context)->bufsz);
r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, LINUXATTR_CONTEXT(context)->buf, LINUXATTR_CONTEXT(context)->bufsz);
if( r < 0 ) {
switch(errno) {
case ERANGE: LINUXATTR_CONTEXT(context)->bufsz *= 2; free(LINUXATTR_CONTEXT(context)->buf); goto AGAIN2;
case ENOTSUP: free(LINUXATTR_CONTEXT(context)->buf); return 0;
default: break;
};
return -1;
}
LINUXATTR_CONTEXT(context)->bufsz = r;
}
if( (LINUXATTR_CONTEXT(context)->bufsz-LINUXATTR_CONTEXT(context)->off) <= len ) {
int32_t ret;
ret = LINUXATTR_CONTEXT(context)->bufsz - LINUXATTR_CONTEXT(context)->off;
memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, ret);
LINUXATTR_CONTEXT(context)->off += ret;
return(ret);
} else {
memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, len);
LINUXATTR_CONTEXT(context)->buf = ((char *)LINUXATTR_CONTEXT(context)->buf) + len;
return len;
}
}
int32_t xar_linuxattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
return lsetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, buf, len, 0);
}
#endif
int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len)
{
#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__)
char *i, *buf = NULL;
int ret, retval=0, bufsz = 1024;
struct statfs sfs;
char *fsname = NULL;
struct _linuxattr_context context;
memset(&context,0,sizeof(struct _linuxattr_context));
/* data from buffers don't have linuxattr */
if(len)
return 0;
if( file == NULL )
return 0;
if( !xar_check_prop(x, "ea") )
return 0;
TRYAGAIN:
buf = malloc(bufsz);
if(!buf)
goto TRYAGAIN;
ret = llistxattr(file, buf, bufsz);
if( ret < 0 ) {
switch(errno) {
case ERANGE: bufsz = bufsz*2; free(buf); goto TRYAGAIN;
case ENOTSUP: retval = 0; goto BAIL;
default: retval = -1; goto BAIL;
};
}
if( ret == 0 ) goto BAIL;
memset(&sfs, 0, sizeof(sfs));
statfs(file, &sfs);
switch(sfs.f_type) {
case EXT3_SUPER_MAGIC: fsname = "ext3"; break; /* assume ext3 */
case JFS_SUPER_MAGIC: fsname = "jfs" ; break;
case REISERFS_SUPER_MAGIC:fsname = "reiser" ; break;
case XFS_SUPER_MAGIC: fsname = "xfs" ; break;
default: retval=0; goto BAIL;
};
for( i=buf; (i-buf) < ret; i += strlen(i)+1 ) {
xar_ea_t e;
context.bufsz = 0;
context.off = 0;
context.buf = NULL;
context.file = file;
e = xar_ea_new(f, i);
xar_ea_pset(f, e, "fstype", fsname);
context.attrname = i;
context.ea = e;
if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_linuxattr_read,&context) < 0) {
retval = -1;
goto BAIL;
}
free(context.buf);
context.attrname = NULL;
}
BAIL:
free(buf);
return retval;
#endif
return 0;
}
int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len)
{
#if defined HAVE_SYS_XATTR_H && defined(HAVE_LSETXATTR) && !defined(__APPLE__)
const char *fsname = "bogus";
struct statfs sfs;
int eaopt = 0;
struct _linuxattr_context context;
xar_prop_t p;
memset(&context,0,sizeof(struct _linuxattr_context));
/* data buffers, can't store linux attrs */
if(len){
return 0;
}
/* Check for EA extraction behavior */
memset(&sfs, 0, sizeof(sfs));
if( statfs(file, &sfs) != 0 ) {
char *tmp, *bname;
tmp = strdup(file);
bname = safe_dirname(tmp);
statfs(bname, &sfs);
free(tmp);
free(bname);
}
switch(sfs.f_type) {
case EXT3_SUPER_MAGIC: fsname = "ext3"; break; /* assume ext3 */
case JFS_SUPER_MAGIC: fsname = "jfs" ; break;
case REISERFS_SUPER_MAGIC:fsname = "reiser" ; break;
case XFS_SUPER_MAGIC: fsname = "xfs" ; break;
};
for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) {
const char *fs = NULL;
const char *prop;
const char *eaname = NULL;
xar_prop_t tmpp;
prop = xar_prop_getkey(p);
if( strncmp(prop, XAR_EA_FORK, strlen(XAR_EA_FORK)) != 0 )
continue;
if( strlen(prop) != strlen(XAR_EA_FORK) )
continue;
tmpp = xar_prop_pget(p, "fstype");
if( tmpp )
fs = xar_prop_getvalue(tmpp);
if( !eaopt && fs && strcmp(fs, fsname) != 0 ) {
continue;
}
if( !fs )
continue;
tmpp = xar_prop_pget(p, "name");
if( tmpp )
eaname = xar_prop_getvalue(tmpp);
context.file = file;
context.attrname = eaname;
if (XAR(x)->attrcopy_from_heap(x, f, p, xar_linuxattr_write, &context) < 0)
return -1;
}
#endif
return 0;
}

41
xar/lib/linuxattr.h Normal file
View File

@ -0,0 +1,41 @@
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Rob Braun <bbraun@synack.net>
* 26-Oct-2004
* Copyright (c) 2004 Rob Braun. All rights reserved.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_LINUXATTR_H_
#define _XAR_LINUXATTR_H_
int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len);
int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len);
#endif /* _XAR_LINUXATTR_H_ */

357
xar/lib/lzmaxar.c Normal file
View File

@ -0,0 +1,357 @@
/*
* Copyright (c) 2005 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 19-Sep-2007
* DRI: Anders F Bjorklund <afb@rpm5.org>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#ifdef HAVE_LIBLZMA
#include <lzma.h>
#endif
#include "xar.h"
#include "filetree.h"
#include "io.h"
#ifdef HAVE_LIBLZMA
#ifndef UINT32_C
#define UINT32_C(v) (v ## U) /* from <stdint.h> normally */
#endif
#ifndef LZMA_VERSION
#define LZMA_VERSION UINT32_C(40420000) /* = 4.42.0alpha6 */
#endif
struct _lzma_context{
uint8_t lzmacompressed;
lzma_stream lzma;
lzma_options_stream options;
lzma_allocator allocator;
#if LZMA_VERSION < 40420010U
lzma_memory_limitter *limit;
#else
lzma_memlimit *limit;
#endif
};
#define preset_level 7
#define memory_limit 93*1024*1024 /* 1=1M, 5=24M, 6=39M, 7=93M, 8=185M, 9=369M */
#define LZMA_CONTEXT(x) ((struct _lzma_context *)(*x))
#endif
int xar_lzma_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
#ifdef HAVE_LIBLZMA
if( !context || !LZMA_CONTEXT(context) )
return 0;
if( LZMA_CONTEXT(context)->lzmacompressed){
lzma_end(&LZMA_CONTEXT(context)->lzma);
}
/* free the context */
free(LZMA_CONTEXT(context));
*context = NULL;
#endif
return 0;
}
int xar_lzma_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
const char *opt;
xar_prop_t tmpp;
#ifdef HAVE_LIBLZMA
void *out = NULL;
size_t outlen, offset = 0;
lzma_ret r;
/* on first run, we init the context and check the compression type */
if( !LZMA_CONTEXT(context) ) {
*context = calloc(1,sizeof(struct _lzma_context));
opt = NULL;
tmpp = xar_prop_pget(p, "encoding");
if( tmpp )
opt = xar_attr_pget(f, tmpp, "style");
if( !opt ) return 0;
if( strcmp(opt, "application/x-lzma") != 0 ) return 0;
lzma_init_decoder();
LZMA_CONTEXT(context)->lzma = LZMA_STREAM_INIT_VAR;
r = lzma_stream_decoder(&LZMA_CONTEXT(context)->lzma, NULL, NULL);
if( (r != LZMA_OK) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error decompressing file");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
LZMA_CONTEXT(context)->lzmacompressed = 1;
}else if( !LZMA_CONTEXT(context)->lzmacompressed ){
/* once the context has been initialized, then we have already
checked the compression type, so we need only check if we
actually are compressed */
return 0;
}
outlen = *inlen;
LZMA_CONTEXT(context)->lzma.next_in = *in;
LZMA_CONTEXT(context)->lzma.avail_in = *inlen;
LZMA_CONTEXT(context)->lzma.next_out = out;
LZMA_CONTEXT(context)->lzma.avail_out = 0;
while( LZMA_CONTEXT(context)->lzma.avail_in != 0 ) {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset;
LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset;
r = lzma_code(&(LZMA_CONTEXT(context)->lzma), LZMA_RUN);
if( (r != LZMA_OK) && (r != LZMA_STREAM_END) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_errno(x, r);
xar_err_set_string(x, "Error decompressing file");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
offset += outlen - offset - LZMA_CONTEXT(context)->lzma.avail_out;
if( (r == LZMA_STREAM_END) && (offset == 0) )
break;
}
free(*in);
*in = out;
*inlen = offset;
#else
opt = NULL;
tmpp = xar_prop_pget(p, "encoding");
if( tmpp )
opt = xar_attr_pget(f, tmpp, "style");
if( !opt ) return 0;
if( strcmp(opt, "application/x-lzma") != 0 ) return 0;
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_errno(x, 0);
xar_err_set_string(x, "lzma support not compiled in.");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
#endif /* HAVE_LIBLZMA */
return 0;
}
int xar_lzma_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
#ifdef HAVE_LIBLZMA
xar_prop_t tmpp;
if( LZMA_CONTEXT(context)->lzmacompressed){
lzma_end(&LZMA_CONTEXT(context)->lzma);
#if LZMA_VERSION < 40420010U
lzma_memory_limitter_end(LZMA_CONTEXT(context)->limit, 1);
#else
lzma_memlimit_end(LZMA_CONTEXT(context)->limit, 1);
#endif
tmpp = xar_prop_pset(f, p, "encoding", NULL);
if( tmpp )
xar_attr_pset(f, tmpp, "style", "application/x-lzma");
}
/* free the context */
free(LZMA_CONTEXT(context));
*context = NULL;
#endif /* HAVE_LIBLZMA */
return 0;
}
int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
const char *opt;
#ifdef HAVE_LIBLZMA
void *out = NULL;
size_t outlen, offset = 0;
lzma_ret r;
/* on first run, we init the context and check the compression type */
if( !LZMA_CONTEXT(context) ) {
int level = preset_level;
*context = calloc(1,sizeof(struct _lzma_context));
opt = xar_opt_get(x, XAR_OPT_COMPRESSION);
if( !opt )
return 0;
if( strcmp(opt, XAR_OPT_VAL_LZMA) != 0 )
return 0;
opt = xar_opt_get(x, XAR_OPT_COMPRESSIONARG);
if( opt ) {
int tmp;
errno = 0;
tmp = strtol(opt, NULL, 10);
if( errno == 0 ) {
if( (level >= 0) && (level <= 9) )
level = tmp;
}
}
lzma_init_encoder();
LZMA_CONTEXT(context)->options.check = LZMA_CHECK_CRC64;
LZMA_CONTEXT(context)->options.has_crc32 = 1; /* true */
LZMA_CONTEXT(context)->options.alignment = 0;
#if defined (__ppc__) || defined (powerpc) || defined (__ppc64__)
LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_POWERPC;
#elif defined (__i386__) || defined (__amd64__) || defined(__x86_64__)
LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_X86;
#else
LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_COPY;
#endif
LZMA_CONTEXT(context)->options.filters[0].options = NULL;
LZMA_CONTEXT(context)->options.filters[1].id = LZMA_FILTER_LZMA;
LZMA_CONTEXT(context)->options.filters[1].options = (lzma_options_lzma *)(lzma_preset_lzma + level - 1);
/* Terminate the filter options array. */
LZMA_CONTEXT(context)->options.filters[2].id = UINT64_MAX;
LZMA_CONTEXT(context)->lzma = LZMA_STREAM_INIT_VAR;
#if LZMA_VERSION < 40420010U
LZMA_CONTEXT(context)->limit = lzma_memory_limitter_create(memory_limit);
LZMA_CONTEXT(context)->allocator.alloc = (void*) lzma_memory_alloc;
LZMA_CONTEXT(context)->allocator.free = (void*) lzma_memory_free;
#else
LZMA_CONTEXT(context)->limit = lzma_memlimit_create(memory_limit);
LZMA_CONTEXT(context)->allocator.alloc = (void*) lzma_memlimit_alloc;
LZMA_CONTEXT(context)->allocator.free = (void*) lzma_memlimit_free;
#endif
LZMA_CONTEXT(context)->allocator.opaque = LZMA_CONTEXT(context)->limit;
LZMA_CONTEXT(context)->lzma.allocator = &LZMA_CONTEXT(context)->allocator;
r = lzma_stream_encoder_single(&LZMA_CONTEXT(context)->lzma, &(LZMA_CONTEXT(context)->options));
if( (r != LZMA_OK) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error compressing file");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
LZMA_CONTEXT(context)->lzmacompressed = 1;
if( *inlen == 0 )
return 0;
}else if( !LZMA_CONTEXT(context)->lzmacompressed ){
/* once the context has been initialized, then we have already
checked the compression type, so we need only check if we
actually are compressed */
return 0;
}
outlen = *inlen/2;
if(outlen == 0) outlen = 1024;
LZMA_CONTEXT(context)->lzma.next_in = *in;
LZMA_CONTEXT(context)->lzma.avail_in = *inlen;
LZMA_CONTEXT(context)->lzma.next_out = out;
LZMA_CONTEXT(context)->lzma.avail_out = 0;
if( *inlen != 0 ) {
do {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
if( out == NULL ) abort();
LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset;
LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset;
r = lzma_code(&LZMA_CONTEXT(context)->lzma, LZMA_RUN);
offset = outlen - LZMA_CONTEXT(context)->lzma.avail_out;
} while( r == LZMA_OK && LZMA_CONTEXT(context)->lzma.avail_in != 0);
} else {
do {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ if( out == NULL ) abort();
LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset;
LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset;
r = lzma_code(&LZMA_CONTEXT(context)->lzma, LZMA_FINISH);
offset = outlen - LZMA_CONTEXT(context)->lzma.avail_out;
} while( r == LZMA_OK && r != LZMA_STREAM_END);
}
if( (r != LZMA_OK && r != LZMA_STREAM_END) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error compressing file");
xar_err_set_errno(x, r);
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
free(*in);
*in = out;
*inlen = offset;
#else
opt = xar_opt_get(x, XAR_OPT_COMPRESSION);
if( !opt )
return 0;
if( strcmp(opt, XAR_OPT_VAL_LZMA) != 0 )
return 0;
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_errno(x, 0);
xar_err_set_string(x, "lzma support not compiled in.");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
#endif /* HAVE_LIBLZMA */
return 0;
}

47
xar/lib/lzmaxar.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2005 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* DRI:
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_LZMA_H_
#define _XAR_LZMA_H_
int xar_lzma_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int xar_lzma_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int xar_lzma_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
#endif /* _XAR_LZMA_H_ */

407
xar/lib/macho.c Normal file
View File

@ -0,0 +1,407 @@
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include "macho.h"
#include "util.h"
#include "data.h"
#include "arcmod.h"
#include "xar.h"
#define BIT64 0x01000000
#define PPC 0x00000012
#define I386 0x00000007
struct machexecutables {
struct mach_header mh;
struct lc *lc;
uint32_t curlc;
uint64_t nextlc;
char **strings;
uint32_t stringsz;
uint8_t byteswapped;
uint8_t bits;
};
struct _macho_context{
struct fat_header fath; /* Need to read and buffer the fat header */
struct fat_arch *arches; /* Read and buffer array of arches */
uint32_t curarch; /* Current arch being parsed */
struct machexecutables *me;
uint64_t nextme; /* Offset of the next mach header */
uint32_t curme; /* Current me being parsed */
unsigned char buffer[512]; /* Place to store incomplete struct info */
uint16_t buffersz; /* Keep track of how much of buffer is used*/
uint16_t state; /* Keep track of what we're looking for */
uint64_t curroffset; /* Current offset in file */
uint8_t byteswapped; /* Keep track of whether we're byteswapping*/
};
/* Looking for... */
enum {
lf_fatheader = 0,
lf_inc_fatheader,
lf_archheader,
lf_inc_archheader,
lf_machheader,
lf_inc_machheader,
lf_loadcommand,
lf_inc_loadcommand,
lf_lcstr,
lf_inc_lcstr,
lf_none
};
#define MACHO_CONTEXT(x) ((struct _macho_context *)(*x))
static const char *macho_cpustr(uint32_t cputype)
{
const char *cpustr;
switch(cputype) {
case PPC: cpustr = "ppc"; break;
case I386: cpustr = "i386"; break;
case PPC|BIT64: cpustr = "ppc64"; break;
default: cpustr = "unknown"; break;
};
return cpustr;
}
/* Returns number of bytes consumed during the parsing process */
static int32_t macho_parse(xar_file_t f, void *in, size_t inlen, struct _macho_context *context)
{
int32_t consumed = 0;
switch( context->state ) {
case(lf_fatheader):
if( inlen >= sizeof(struct fat_header) ) {
struct fat_header *fh = (struct fat_header *)in;
if( fh->magic == 0xcafebabe ) {
context->fath.magic = fh->magic;
context->fath.nfat_arch = fh->nfat_arch;
context->arches = calloc(1,sizeof(struct fat_arch) * fh->nfat_arch);
context->me = calloc(1,sizeof(struct machexecutables) * fh->nfat_arch);
context->state = lf_archheader;
context->byteswapped = 0;
context->curarch = 0;
consumed = 8;
xar_prop_set(f, "contents/type", "Mach-O Fat File");
} else if( fh->magic == 0xbebafeca ) {
context->fath.magic = xar_swap32(fh->magic);
context->fath.nfat_arch = xar_swap32(fh->nfat_arch);
context->arches = calloc(1,sizeof(struct fat_arch) * context->fath.nfat_arch);
context->me = calloc(1,sizeof(struct machexecutables) * context->fath.nfat_arch);
context->state = lf_archheader;
context->byteswapped = 1;
context->curarch = 0;
consumed = 8;
xar_prop_set(f, "contents/type", "Mach-O Fat File");
} else {
context->me = calloc(1,sizeof(struct machexecutables));
context->curme = 0;
context->state = lf_machheader;
}
} else {
uint32_t *tmp = in;
if( (*tmp == 0xcafebabe) || (*tmp == 0xbebafeca) ) {
memcpy(context->buffer, in, inlen);
context->buffersz = inlen;
consumed = (int32_t)inlen;
context->state = lf_inc_fatheader;
} else {
context->me = calloc(1,sizeof(struct machexecutables));
context->curme = 0;
context->state = lf_machheader;
}
}
break;
case lf_archheader:
if( inlen >= sizeof(struct fat_arch) ) {
struct fat_arch *fa = in;
if( context->byteswapped ) {
context->arches[context->curarch].cputype = xar_swap32(fa->cputype);
context->arches[context->curarch].cpusubtype = xar_swap32(fa->cpusubtype);
context->arches[context->curarch].offset = xar_swap32(fa->offset);
context->arches[context->curarch].size = xar_swap32(fa->size);
context->arches[context->curarch].alighn = xar_swap32(fa->alighn);
} else {
memcpy(&context->arches[context->curarch], in, sizeof(struct fat_arch));
}
context->curarch++;
if( context->curarch >=context->fath.nfat_arch ) {
context->nextme = context->arches[0].offset;
context->state = lf_machheader;
}
consumed = sizeof(struct fat_arch);
} else {
memcpy(context->buffer, in, inlen);
context->buffersz = inlen;
consumed = (int32_t)inlen;
context->state = lf_inc_archheader;
}
break;
case lf_machheader:
if( (context->curroffset+inlen) <= context->nextme )
consumed = inlen;
else {
uint64_t off;
unsigned char *tmpin = in;
off = context->nextme - context->curroffset;
tmpin += off;
if( (inlen-off) >= sizeof(struct mach_header) ) {
const char *cpustr;
char *typestr, *typestr2;
struct mach_header *mh = (struct mach_header *)tmpin;
switch(mh->magic) {
case 0xcffaedfe:
context->me[context->curme].bits = 64;
context->me[context->curme].byteswapped = 1;
break;
case 0xcefaedfe:
context->me[context->curme].bits = 32;
context->me[context->curme].byteswapped = 1;
break;
case 0xfeedface:
context->me[context->curme].bits = 32;
break;
case 0xfeedfacf:
context->me[context->curme].bits = 64;
break;
default:
context->state = lf_none;
return inlen;
};
if( context->me[context->curme].byteswapped ) {
context->me[context->curme].mh.magic = xar_swap32(mh->magic);
context->me[context->curme].mh.cputype = xar_swap32(mh->cputype);
context->me[context->curme].mh.cpusubtype = xar_swap32(mh->cpusubtype);
context->me[context->curme].mh.filetype = xar_swap32(mh->filetype);
context->me[context->curme].mh.ncmds = xar_swap32(mh->ncmds);
context->me[context->curme].mh.sizeofcmds = xar_swap32(mh->sizeofcmds);
context->me[context->curme].mh.flags = xar_swap32(mh->flags);
} else {
memcpy(&context->me[context->curme].mh, tmpin, sizeof(struct mach_header));
}
cpustr = macho_cpustr(context->me[context->curme].mh.cputype);
switch(context->me[context->curme].mh.filetype) {
case 0x01: typestr = "Mach-O Object"; break;
case 0x02: typestr = "Mach-O Executable"; break;
case 0x03: typestr = "Mach-O Fixed VM Library"; break;
case 0x04: typestr = "Mach-O core"; break;
case 0x05: typestr = "Mach-O Preloaded Executable"; break;
case 0x06: typestr = "Mach-O Dylib"; break;
case 0x07: typestr = "Mach-O Dylinker"; break;
case 0x08: typestr = "Mach-O Bundle"; break;
case 0x09: typestr = "Mach-O Stub"; break;
default: typestr = "Unknown"; break;
};
if( xar_prop_get(f, "contents/type", (const char **)&typestr2) ) {
xar_prop_set(f, "contents/type", typestr);
}
asprintf(&typestr2, "contents/%s/type", cpustr);
xar_prop_set(f, typestr2, typestr);
free(typestr2);
context->me[context->curme].lc = malloc(sizeof(struct lc) * context->me[context->curme].mh.ncmds);
context->me[context->curme].strings = malloc(sizeof(char *) * context->me[context->curme].mh.ncmds);
context->me[context->curme].curlc = 0;
consumed = off + sizeof(struct mach_header);
if( context->me[context->curme].bits == 64 )
consumed += 4;
context->me[context->curme].nextlc = context->curroffset + consumed;
context->state = lf_loadcommand;
} else {
memcpy(context->buffer, tmpin, inlen-off);
context->buffersz = inlen-off;
consumed = (int32_t)inlen;
context->state = lf_inc_machheader;
}
}
break;
case lf_loadcommand:
if( (context->curroffset+inlen) <= context->me[context->curme].nextlc )
consumed = inlen;
else {
uint64_t off;
unsigned char *tmpin = in;
off = context->me[context->curme].nextlc - context->curroffset;
tmpin += off;
if( (inlen-off) >= sizeof(struct lc) ) {
if( context->me[context->curme].byteswapped ) {
struct lc *lc = (struct lc *)tmpin;
context->me[context->curme].lc[context->me[context->curme].curlc].cmd = xar_swap32(lc->cmd);
context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize = xar_swap32(lc->cmdsize);
} else {
memcpy(&context->me[context->curme].lc[context->me[context->curme].curlc], tmpin, sizeof(struct lc));
}
consumed = off + sizeof(struct lc);
context->me[context->curme].nextlc += context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize;
if( (context->me[context->curme].lc[context->me[context->curme].curlc].cmd == 0xc) || (context->me[context->curme].lc[context->me[context->curme].curlc].cmd == 0xd) ) {
context->state = lf_lcstr;
} else {
context->me[context->curme].curlc++;
if( context->me[context->curme].curlc >= context->me[context->curme].mh.ncmds ) {
context->curme++;
if( context->fath.nfat_arch ) {
if( context->curme >= context->fath.nfat_arch ) {
context->state = lf_none;
} else {
context->nextme = context->arches[context->curme].offset;
context->state = lf_machheader;
}
} else {
context->state = lf_none;
}
}
}
} else {
memcpy(context->buffer, ((char *)in)+off, inlen-off);
context->buffersz = inlen-off;
consumed = inlen;
context->state = lf_inc_loadcommand;
}
}
break;
case lf_lcstr:
if( inlen >= (context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize-8) ) {
const char *tmpstr;
uint32_t cmdsize = context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize;
uint32_t *offsetp, offset;
char *lib, *propstr;
offsetp = in;
if( context->me[context->curme].byteswapped )
offset = xar_swap32(*offsetp);
else
offset = *offsetp;
lib = calloc(1,(cmdsize - offset)+1);
memcpy(lib, ((char *)in)+(offset - 8), cmdsize - offset);
tmpstr = macho_cpustr(context->me[context->curme].mh.cputype);
asprintf(&propstr, "contents/%s/library", tmpstr);
xar_prop_create(f, propstr, lib);
free(lib);
free(propstr);
consumed = cmdsize-8;
context->state = lf_loadcommand;
context->me[context->curme].curlc++;
if( context->me[context->curme].curlc >= context->me[context->curme].mh.ncmds ) {
context->curme++;
if( context->fath.nfat_arch ) {
if( context->curme >= context->fath.nfat_arch ) {
context->state = lf_none;
} else {
context->nextme = context->arches[context->curme].offset;
context->state = lf_machheader;
}
} else {
context->state = lf_none;
}
}
} else {
memcpy(context->buffer, in, inlen);
context->buffersz = inlen;
consumed = inlen;
context->state = lf_inc_lcstr;
}
break;
case lf_none:
default:
consumed = inlen;
break;
};
return consumed;
}
int32_t xar_macho_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
int32_t consumed = 0, total = 0;
if( strcmp(xar_prop_getkey(p), "data") != 0 )
return 0;
if( !xar_check_prop(x, "contents") )
return 0;
if( !*context ) {
*context = calloc(1,sizeof(struct _macho_context));
}
while( total < *inlen ) {
consumed = macho_parse(f, ((char *)*in)+total, *inlen-total, MACHO_CONTEXT(context));
total += consumed;
MACHO_CONTEXT(context)->curroffset += consumed;
}
return 0;
}
int32_t xar_macho_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
if( MACHO_CONTEXT(context) ){
int i;
if( MACHO_CONTEXT(context)->fath.nfat_arch ) {
for(i = 0; i < MACHO_CONTEXT(context)->fath.nfat_arch; i++) {
if( MACHO_CONTEXT(context)->me[i].lc )
free(MACHO_CONTEXT(context)->me[i].lc);
if( MACHO_CONTEXT(context)->me[i].strings )
free(MACHO_CONTEXT(context)->me[i].strings);
}
} else {
if( MACHO_CONTEXT(context)->me ) {
if( MACHO_CONTEXT(context)->me[0].lc )
free(MACHO_CONTEXT(context)->me[0].lc);
if( MACHO_CONTEXT(context)->me[0].strings )
free(MACHO_CONTEXT(context)->me[0].strings);
}
}
if( MACHO_CONTEXT(context)->me )
free(MACHO_CONTEXT(context)->me);
if( MACHO_CONTEXT(context)->arches )
free(MACHO_CONTEXT(context)->arches);
free(*context);
}
return 0;
}

69
xar/lib/macho.h Normal file
View File

@ -0,0 +1,69 @@
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _MACHO_H_
#define _MACHO_H_
#include "xar.h"
#include "filetree.h"
struct mach_header {
uint32_t magic;
uint32_t cputype;
uint32_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
};
struct lc {
uint32_t cmd;
uint32_t cmdsize;
};
struct fat_header {
uint32_t magic;
uint32_t nfat_arch;
};
struct fat_arch {
uint32_t cputype;
uint32_t cpusubtype;
uint32_t offset;
uint32_t size;
uint32_t alighn;
};
int32_t xar_macho_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int32_t xar_macho_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
#endif /* _MACHO_H_ */

111
xar/lib/script.c Normal file
View File

@ -0,0 +1,111 @@
/*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <limits.h>
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include "xar.h"
#include "filetree.h"
#include "arcmod.h"
struct _script_context{
int initted;
};
#define SCRIPT_CONTEXT(x) ((struct _script_context*)(*x))
int32_t xar_script_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
char *buf = *in;
xar_prop_t tmpp;
if(!SCRIPT_CONTEXT(context)){
*context = calloc(1,sizeof(struct _script_context));
}
if( SCRIPT_CONTEXT(context)->initted )
return 0;
if( !xar_check_prop(x, "contents") )
return 0;
/* Sanity check *inlen, which really shouldn't be more than a
* few kbytes...
*/
if( *inlen > INT_MAX )
return 0;
/*We only run on the begining of the file, so once we init, we don't run again*/
SCRIPT_CONTEXT(context)->initted = 1;
if( (*inlen > 2) && (buf[0] == '#') && (buf[1] == '!') ) {
char *exe;
int i;
exe = malloc(*inlen);
if( !exe )
return -1;
memset(exe, 0, *inlen);
for(i = 2; (i < *inlen) && (buf[i] != '\0') && (buf[i] != '\n') && (buf[i] != ' '); ++i) {
exe[i-2] = buf[i];
}
tmpp = xar_prop_pset(f, p, "contents", NULL);
if( tmpp ) {
xar_prop_pset(f, tmpp, "type", "script");
xar_prop_pset(f, tmpp, "interpreter", exe);
}
free(exe);
}
return 0;
}
int32_t xar_script_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
if(!SCRIPT_CONTEXT(context)){
return 0;
}
if( *context ){
free(*context);
*context = NULL;
}
return 0;
}

39
xar/lib/script.h Normal file
View File

@ -0,0 +1,39 @@
/*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _SCRIPT_H_
#define _SCRIPT_H_
int32_t xar_script_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int32_t xar_script_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
#endif /* _SCRIPT_H_ */

558
xar/lib/signature.c Normal file
View File

@ -0,0 +1,558 @@
/*
* Copyright (c) 2006 Apple Computer, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 6-July-2006
* DRI: Christopher Ryan <ryanc@apple.com>
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libxml/xmlwriter.h>
#include <libxml/xmlreader.h>
#include <inttypes.h> /* for PRIu64 */
#include <unistd.h>
#include "xar.h"
#include "archive.h"
#include "b64.h"
#include "signature.h"
struct _signature_copy_context{
void *buffer;
size_t length;
off_t offset;
};
#ifdef __APPLE__
xar_signature_t xar_signature_new_internal(xar_t x, int is_extended, const char *type, int32_t length, xar_signer_callback callback, void *callback_context)
#else
xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context)
#endif
{
xar_signature_t ret;
if( XAR(x)->files ){
xar_err_new(x);
xar_err_set_string(x, "Signatures must be added before files are added");
xar_err_callback(x, XAR_SEVERITY_WARNING, XAR_ERR_ARCHIVE_CREATION);
return NULL;
}
ret = malloc(sizeof(struct __xar_signature_t));
if( ! ret )
return NULL;
memset(XAR_SIGNATURE(ret), 0, sizeof(struct __xar_signature_t));
XAR_SIGNATURE(ret)->type = strdup(type);
XAR_SIGNATURE(ret)->len = length;
XAR_SIGNATURE(ret)->offset = XAR(x)->heap_offset;
XAR_SIGNATURE(ret)->signer_callback = callback;
XAR_SIGNATURE(ret)->callback_context = callback_context;
#ifdef __APPLE__
XAR_SIGNATURE(ret)->is_extended = is_extended;
#endif
/* Pre allocate space in the heap */
XAR(x)->heap_offset += length;
XAR(x)->heap_len += length;
// Put the new on at the end of the list
if( XAR_SIGNATURE(XAR(x)->signatures) ) {
struct __xar_signature_t *sig;
// (Apple) Find the end of the signatures list
// The open source code seems to smash list items 1 through n when the head of this list is already defined
// despite the fact that the xar signatures are implemented as a list. This is an Apple xar 1.4 edit
// to allow that list to grow beyond 2
for( sig = XAR_SIGNATURE(XAR(x)->signatures); sig->next; sig = sig->next);
sig->next = XAR_SIGNATURE(ret);
} else
XAR(x)->signatures = ret;
XAR_SIGNATURE(ret)->x = x;
return ret;
}
#ifdef __APPLE__
xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context)
{
return xar_signature_new_internal(x, 0, type, length, callback, callback_context);
}
#endif
xar_signature_t xar_signature_new_extended(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context)
{
#ifdef __APPLE__
return xar_signature_new_internal(x, 1, type, length, callback, callback_context);
#else
return xar_signature_new(x, type, length, callback, callback_context);
#endif
}
const char *xar_signature_type(xar_signature_t s)
{
if( !s )
return NULL;
return XAR_SIGNATURE(s)->type;
}
/* Add x509 cert data to this signature */
int32_t xar_signature_add_x509certificate(xar_signature_t sig, const uint8_t *cert_data, uint32_t cert_len )
{
struct __xar_x509cert_t *newcert;
if( !sig )
return -1;
newcert = malloc(sizeof(struct __xar_x509cert_t));
memset(newcert, 0, sizeof(struct __xar_x509cert_t));
newcert->content = malloc(sizeof(const char)*cert_len);
memcpy(newcert->content,cert_data,cert_len);
newcert->len = cert_len;
if( XAR_SIGNATURE(sig)->x509certs ){
struct __xar_x509cert_t *cert;
// Find the end of the linked list
for( cert = XAR_SIGNATURE(sig)->x509certs; cert->next; cert = cert->next );
cert->next = newcert;
}else{
XAR_SIGNATURE(sig)->x509certs = newcert;
}
XAR_SIGNATURE(sig)->x509cert_count++;
return 0;
}
int32_t xar_signature_get_x509certificate_count(xar_signature_t sig)
{
if( !sig ){
return 0;
}
return XAR_SIGNATURE(sig)->x509cert_count;
}
int32_t xar_signature_get_x509certificate_data(xar_signature_t sig, int32_t index, const uint8_t **cert_data, uint32_t *cert_len)
{
struct __xar_x509cert_t *cert;
int i = 0;
/* If there are no certs to return, return immediatly */
if( !XAR_SIGNATURE(sig)->x509cert_count ){
if( cert_data )
*cert_data = 0;
return -1;
}
/* Loop through the certs, copying each one's string ptr to the array */
for( cert = XAR_SIGNATURE(sig)->x509certs; cert; cert = cert->next ){
if( i == index ){
if( cert_data )
*cert_data = cert->content;
if( cert_len )
*cert_len = cert->len;
break;
}
i++;
}
/* If the cert iterator is still valid, we did not find the proper index */
if( !cert ){
return -1;
}
return 0;
}
xar_signature_t xar_signature_first(xar_t x)
{
return XAR(x)->signatures;
}
xar_signature_t xar_signature_next(xar_signature_t s)
{
return XAR_SIGNATURE(s)->next;
}
int32_t _xar_signature_read_from_heap(xar_t x ,off_t offset,size_t length,uint8_t *data)
{
off_t seek_off = XAR(x)->toc_count + sizeof(xar_header_t) + offset;
int r = 0;
r = lseek(XAR(x)->fd, seek_off, SEEK_SET);
/* can't seek to the proper location */
if( -1 == r ){
xar_err_new(x);
xar_err_set_string(x, "Unable to seek");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
r = read(XAR(x)->fd,data,length);
if( r != length ){
xar_err_new(x);
xar_err_set_string(x, "Unable to read");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
return 0;
}
/* This method retrieves the signed data for this segment as well as the data the signed data is signing */
uint8_t xar_signature_copy_signed_data(xar_signature_t sig, uint8_t **data, uint32_t *length, uint8_t **signed_data, uint32_t *signed_length, off_t *signed_offset)
{
uint32_t offset = 0;
xar_t x = NULL;
const char *value;
// xar 1.6 fails this method if any of data, length, signed_data, signed_length are NULL
// within OS X we use this method to get combinations of signature, signed data, or signed_offset,
// so this method checks and sets these out values independently
if( !sig )
return -1;
x = XAR_SIGNATURE(sig)->x;
/* Get the checksum, to be used for signing. If we support multiple checksums
in the future, all checksums should be retrieved */
if(length) {
if(0 == xar_prop_get( XAR_FILE(x) , "checksum/size", &value)){
*length = strtoull( value, (char **)NULL, 10);
}
if(0 == xar_prop_get( XAR_FILE(x) , "checksum/offset", &value)){
offset = strtoull( value, (char **)NULL, 10);
}
if(data) {
*data = malloc(sizeof(char)*(*length));
// This function will either read all of length or return -1. Check and bubble up.
if (_xar_signature_read_from_heap(x, offset, *length, *data) != 0)
return -1;
}
}
/* read signature data */
offset = XAR_SIGNATURE(sig)->offset;
// This parameter is an Apple edit
// This out value is ignored OS X in SL, but this method prototype is included in the 10.5 SDK
if( signed_offset )
*signed_offset = offset;
if(signed_length) {
*signed_length = XAR_SIGNATURE(sig)->len;
if(signed_data) {
*signed_data = malloc(sizeof(char)*(*signed_length));
// This function will either read all of length or return -1. Check and bubble up.
if (_xar_signature_read_from_heap(x, offset, *signed_length, *signed_data) != 0)
return -1;
}
}
return 0;
}
xar_signature_t xar_signature_unserialize(xar_t x, xmlTextReaderPtr reader)
{
struct __xar_signature_t *ret = NULL;
#ifdef __APPLE__
const xmlChar *sig_type = NULL;
#endif
const xmlChar *value = NULL;
const xmlChar *name = NULL;
int type;
size_t outputLength = 0;
ret = malloc(sizeof(struct __xar_signature_t));
if( ! ret )
return NULL;
memset(ret, 0, sizeof(struct __xar_signature_t));
ret->x = x;
/* Read One Signature Element */
#ifdef __APPLE__
sig_type = xmlTextReaderConstLocalName(reader);
if(strcmp((const char*)sig_type, "x-signature") == 0) {
ret->is_extended = 1;
}
#endif
/* Retrieve the type attr */
value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"style");
if( value ){
ret->type = strdup((const char *)value);
}
/* Look for the rest of the child elements */
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
name = xmlTextReaderConstLocalName(reader);
if (value) {
xmlFree((void*)value);
value = NULL;
}
if (!name) { /* archive corruption */
return NULL;
}
if( type == XML_READER_TYPE_ELEMENT ) {
if(strcmp((const char*)name, "size") == 0) {
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
if( type == XML_READER_TYPE_TEXT ) {
value = xmlTextReaderConstValue(reader);
ret->len = strtoull( (const char *)value, (char **)NULL, 10);
value = NULL; /* We don't want to accidentally release this const. */
}else if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
} else if( strcmp((const char*)name, "offset") == 0 ){
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
if( type == XML_READER_TYPE_TEXT ) {
value = xmlTextReaderConstValue(reader);
ret->offset = strtoull( (const char *)value, (char **)NULL, 10);
value = NULL; /* We don't want to accidentally release this const. */
}else if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
} else if( strcmp((const char*)name, "KeyInfo") == 0 ){
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
name = xmlTextReaderConstLocalName(reader);
if( type == XML_READER_TYPE_ELEMENT ) {
if(strcmp((const char*)name, "X509Data") == 0) {
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
name = xmlTextReaderConstLocalName(reader);
if( type == XML_READER_TYPE_ELEMENT ) {
if(strcmp((const char*)name, "X509Certificate") == 0) {
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
if( type == XML_READER_TYPE_TEXT ) {
unsigned char *sig_data = NULL;
value = xmlTextReaderConstValue(reader);
/* this method allocates the resulting data */
sig_data = xar_from_base64(value, strlen((const char *)value), &outputLength);
if(sig_data){
/* for convience we just use the same method, which means multiple allocations */
xar_signature_add_x509certificate(ret, sig_data, outputLength);
free(sig_data);
}else{
ret = NULL;
}
value = NULL; /* We don't want to accidentally release this const. */
//break;
}else if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
}
}else if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
}
}else if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
}
}else if( type == XML_READER_TYPE_TEXT ) {
value = xmlTextReaderConstValue(reader);
value = NULL; /* We don't want to accidentally release this const. */
break;
}else if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
if (value) {
xmlFree((void*)value);
value = NULL;
}
return ret;
}
/*
<signature style="SHA1withRSA">
<offset>20</offset>
<size>256</size>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIICXTCCA...base64...</X509Certificate>
</X509Data>
</KeyInfo>
</signature>
*/
/* This function will serialize an entire list of signatures */
int32_t xar_signature_serialize(xar_signature_t sig, xmlTextWriterPtr writer)
{
if( !sig ) return 0;
/* <signature type='EncryptionAlgorithm'> */
#ifdef __APPLE__
const char* element_name = XAR_SIGNATURE(sig)->is_extended ? "x-signature" : "signature";
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST(element_name), NULL);
#else
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("signature"), NULL);
#endif
/* write out the style */
xmlTextWriterWriteAttribute(writer, BAD_CAST("style"), BAD_CAST(XAR_SIGNATURE(sig)->type));
/* <offset> */
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("offset"), NULL);
xmlTextWriterWriteFormatString(writer, "%"PRIu64, (uint64_t)(XAR_SIGNATURE(sig)->offset));
xmlTextWriterEndElement(writer);
/* <size> */
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("size"), NULL);
xmlTextWriterWriteFormatString(writer, "%d", (XAR_SIGNATURE(sig)->len));
xmlTextWriterEndElement(writer);
/* <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> */
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("KeyInfo"), NULL);
xmlTextWriterWriteAttribute(writer, BAD_CAST("xmlns"), BAD_CAST("http://www.w3.org/2000/09/xmldsig#"));
/* If we have x509 certs, write them out */
if( XAR_SIGNATURE(sig)->x509certs ){
struct __xar_x509cert_t *cert;
/* <X509Data> */
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("X509Data"), NULL);
/* Loop through the certs, copying each one's string ptr to the array */
for( cert = XAR_SIGNATURE(sig)->x509certs; cert; cert = cert->next ){
xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("X509Certificate"), NULL);
xmlTextWriterWriteBase64( writer, (const char *)cert->content, 0, cert->len);
xmlTextWriterEndElement(writer);
}
/* </X509Data> */
xmlTextWriterEndElement(writer);
}
/* </KeyInfo> */
xmlTextWriterEndElement(writer);
/* </signature> */
xmlTextWriterEndElement(writer);
/* serialize the next signature */
if( XAR_SIGNATURE(sig)->next )
xar_signature_serialize(XAR_SIGNATURE(sig)->next,writer);
return 0;
}
void _xar_signature_remove_cert(struct __xar_x509cert_t *cert)
{
struct __xar_x509cert_t *next;
if( !cert )
return;
next = cert->next;
if( cert->content )
free(cert->content);
free(cert);
_xar_signature_remove_cert(next);
return;
}
void xar_signature_remove(xar_signature_t sig)
{
xar_signature_t next;
if( !sig )
return;
next = XAR_SIGNATURE(sig)->next;
if( XAR_SIGNATURE(sig)->type )
free(XAR_SIGNATURE(sig)->type);
if( XAR_SIGNATURE(sig)->x509cert_count ){
_xar_signature_remove_cert(XAR_SIGNATURE(sig)->x509certs);
}
free(XAR_SIGNATURE(sig));
/* remove the next one in the list */
xar_signature_remove(next);
return;
}

73
xar/lib/signature.h Normal file
View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2006 Apple Computer, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 6-July-2006
* DRI: Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_SIGNATURE_H_
#define _XAR_SIGNATURE_H_
#include "xar.h"
struct __xar_x509cert_t{
uint8_t *content;
int32_t len;
struct __xar_x509cert_t *next;
};
struct __xar_signature_t {
char *type;
int32_t len;
off_t offset;
int32_t x509cert_count;
struct __xar_x509cert_t *x509certs;
struct __xar_signature_t *next;
xar_signer_callback signer_callback; /* callback for signing */
void *callback_context; /* context for callback */
xar_t x;
#ifdef __APPLE__
int is_extended;
#endif
};
#define XAR_SIGNATURE(x) ((struct __xar_signature_t *)(x))
#ifdef __APPLE__
xar_signature_t xar_signature_new_internal(xar_t x, int is_extended, const char *type, int32_t length, xar_signer_callback callback, void *callback_context);
#endif
int32_t xar_signature_serialize(xar_signature_t sig, xmlTextWriterPtr writer);
xar_signature_t xar_signature_unserialize(xar_t x, xmlTextReaderPtr reader);
/* deallocates the link list of xar signatures */
void xar_signature_remove(xar_signature_t sig);
#endif /* _XAR_SIGNATURE_H_ */

825
xar/lib/stat.c Normal file
View File

@ -0,0 +1,825 @@
/*
* Copyright (c) 2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2003, Apple Computer, Inc.
* filetype_name() and associated structure.
* DRI: Kevin Van Vechten <kvv@apple.com>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#define _FILE_OFFSET_BITS 64
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <libxml/hash.h>
#include <libxml/xmlstring.h>
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
#include "xar.h"
#include "arcmod.h"
#include "archive.h"
#include "util.h"
#ifndef LLONG_MIN
#define LLONG_MIN LONG_LONG_MIN
#endif
#ifndef LLONG_MAX
#define LLONG_MAX LONG_LONG_MAX
#endif
static struct {
const char *name;
mode_t type;
} filetypes [] = {
{ "file", S_IFREG },
{ "directory", S_IFDIR },
{ "symlink", S_IFLNK },
{ "fifo", S_IFIFO },
{ "character special", S_IFCHR },
{ "block special", S_IFBLK },
{ "socket", S_IFSOCK },
#ifdef S_IFWHT
{ "whiteout", S_IFWHT },
#endif
{ NULL, 0 }
};
static const char * filetype_name (mode_t mode) {
unsigned int i;
for (i = 0; filetypes[i].name; i++)
if (mode == filetypes[i].type)
return (filetypes[i].name);
return ("unknown");
}
static xar_file_t xar_link_lookup(xar_t x, dev_t dev, ino_t ino, xar_file_t f) {
char key[32];
xar_file_t ret;
memset(key, 0, sizeof(key));
snprintf(key, sizeof(key)-1, "%08" DEV_HEXSTRING "%08" INO_HEXSTRING, DEV_CAST dev, INO_CAST ino);
ret = xmlHashLookup(XAR(x)->ino_hash, BAD_CAST(key));
if( ret == NULL ) {
xmlHashAddEntry(XAR(x)->ino_hash, BAD_CAST(key), XAR_FILE(f));
return NULL;
}
return ret;
}
static int32_t aacls(xar_t x, xar_file_t f, const char *file) {
#ifdef HAVE_SYS_ACL_H
#if !defined(__APPLE__)
acl_t a;
const char *type;
xar_prop_get(f, "type", &type);
if( !type || (strcmp(type, "symlink") == 0) )
return 0;
if( !xar_check_prop(x, "acl") )
return 0;
a = acl_get_file(file, ACL_TYPE_DEFAULT);
if( a ) {
char *t;
acl_entry_t e;
/* If the acl is empty, or not valid, skip it */
if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 )
goto NEXT;
t = acl_to_text(a, NULL);
if( t ) {
xar_prop_set(f, "acl/default", t);
acl_free(t);
}
acl_free(a);
}
NEXT:
a = acl_get_file(file, ACL_TYPE_ACCESS);
if( a ) {
char *t;
acl_entry_t e;
/* If the acl is empty, or not valid, skip it */
if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 )
goto DONE;
t = acl_to_text(a, NULL);
if( t ) {
xar_prop_set(f, "acl/access", t);
acl_free(t);
}
acl_free(a);
}
DONE:
#else /* !__APPLE__ */
acl_entry_t e = NULL;
acl_t a;
int i;
if( !xar_check_prop(x, "acl") )
return 0;
a = acl_get_file(file, ACL_TYPE_EXTENDED);
if( !a )
return 0;
for( i = 0; acl_get_entry(a, e == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &e) == 0; i++ ) {
char *t;
t = acl_to_text(a, NULL);
if( t ) {
xar_prop_set(f, "acl/appleextended", t);
acl_free(t);
}
}
acl_free(a);
#endif /* !__APPLE__ */
#endif
return 0;
}
static int32_t eacls(xar_t x, xar_file_t f, const char *file) {
#ifdef HAVE_SYS_ACL_H
#if !defined(__APPLE__)
const char *t;
acl_t a;
const char *type;
xar_prop_get(f, "type", &type);
if( !type || (strcmp(type, "symlink") == 0) )
return 0;
xar_prop_get(f, "acl/default", &t);
if( t ) {
a = acl_from_text(t);
if( !a ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error extracting default acl from toc");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
if( acl_set_file(file, ACL_TYPE_DEFAULT, a) != 0 ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error setting default acl");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
}
}
xar_prop_get(f, "acl/access", &t);
if( t ) {
a = acl_from_text(t);
if( !a ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error extracting access acl from toc");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error setting access acl");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
acl_free(a);
}
}
#else /* !__APPLE__ */
const char *t;
acl_t a;
xar_prop_get(f, "acl/appleextended", &t);
if( t ) {
a = acl_from_text(t);
if( !a ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error extracting access acl from toc");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
} else {
if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) {
xar_err_new(x);
xar_err_set_errno(x, errno);
xar_err_set_string(x, "Error setting access acl");
xar_err_set_file(x, f);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
acl_free(a);
}
}
#endif /* !__APPLE__ */
#endif
return 0;
}
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
#define XAR_FLAG_FORK "flags"
static void x_addflag(xar_file_t f, const char *name) {
char opt[1024];
memset(opt, 0, sizeof(opt));
snprintf(opt, sizeof(opt)-1, "%s/%s", XAR_FLAG_FORK, name);
xar_prop_set(f, opt, NULL);
return;
}
#endif
static int32_t flags_archive(xar_t x, xar_file_t f, const struct stat *sb) {
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
if( !sb->st_flags )
return 0;
if( !xar_check_prop(x, XAR_FLAG_FORK) )
return 0;
#ifdef UF_NODUMP
if( sb->st_flags & UF_NODUMP )
x_addflag(f, "UserNoDump");
#endif
#ifdef UF_IMMUTABLE
if( sb->st_flags & UF_IMMUTABLE )
x_addflag(f, "UserImmutable");
#endif
#ifdef UF_APPEND
if( sb->st_flags & UF_APPEND )
x_addflag(f, "UserAppend");
#endif
#ifdef UF_OPAQUE
if( sb->st_flags & UF_OPAQUE )
x_addflag(f, "UserOpaque");
#endif
#ifdef SF_ARCHIVED
if( sb->st_flags & SF_ARCHIVED )
x_addflag(f, "SystemArchived");
#endif
#ifdef SF_IMMUTABLE
if( sb->st_flags & SF_IMMUTABLE )
x_addflag(f, "SystemImmutable");
#endif
#ifdef SF_APPEND
if( sb->st_flags & SF_APPEND )
x_addflag(f, "SystemAppend");
#endif
#endif /* HAVE_STRUCT_STAT_ST_FLAGS */
return 0;
}
#ifdef HAVE_CHFLAGS
static int32_t x_getprop(xar_file_t f, const char *name, char **value) {
char v[1024];
memset(v, 0, sizeof(v));
snprintf(v, sizeof(v)-1, "%s/%s", XAR_FLAG_FORK, name);
return xar_prop_get(f, v, (const char **)value);
}
#endif
int32_t xar_flags_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
#ifdef HAVE_CHFLAGS
char *tmp;
u_int flags = 0;
if( xar_prop_get(f, XAR_FLAG_FORK, NULL) )
return 0;
#ifdef UF_NODUMP
if( x_getprop(f, "UserNoDump", (char **)&tmp) == 0 )
flags |= UF_NODUMP;
#endif
#ifdef UF_IMMUTABLE
if( x_getprop(f, "UserImmutable", (char **)&tmp) == 0 )
flags |= UF_IMMUTABLE;
#endif
#ifdef UF_APPEND
if( x_getprop(f, "UserAppend", (char **)&tmp) == 0 )
flags |= UF_APPEND;
#endif
#ifdef UF_OPAQUE
if( x_getprop(f, "UserOpaque", (char **)&tmp) == 0 )
flags |= UF_OPAQUE;
#endif
#ifdef SF_ARCHIVED
if( x_getprop(f, "SystemArchived", (char **)&tmp) == 0 )
flags |= SF_ARCHIVED;
#endif
#ifdef SF_IMMUTABLE
if( x_getprop(f, "SystemImmutable", (char **)&tmp) == 0 )
flags |= SF_IMMUTABLE;
#endif
#ifdef SF_APPEND
if( x_getprop(f, "SystemAppend", (char **)&tmp) == 0 )
flags |= SF_APPEND;
#endif
if( !flags )
return 0;
if( chflags(file, flags) != 0 ) {
char e[1024];
memset(e, 0, sizeof(e));
snprintf(e, sizeof(e)-1, "chflags: %s", strerror(errno));
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, e);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
#endif
return 0;
}
int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) {
char *tmpstr;
struct passwd *pw;
struct group *gr;
char time[128];
struct tm t;
const char *type;
/* no stat attributes for data from a buffer, it is just a file */
if(len){
if( xar_check_prop(x, "type") )
xar_prop_set(f, "type", "file");
return 0;
}
if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) {
xar_file_t tmpf;
const char *id = xar_attr_get(f, NULL, "id");
if( !id ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: No file id for file");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
tmpf = xar_link_lookup(x, XAR(x)->sbcache.st_dev, XAR(x)->sbcache.st_ino, f);
if( xar_check_prop(x, "type") ) {
xar_prop_set(f, "type", "hardlink");
if( tmpf ) {
const char *id;
id = xar_attr_get(tmpf, NULL, "id");
xar_attr_set(f, "type", "link", id);
} else {
xar_attr_set(f, "type", "link", "original");
}
}
} else {
type = filetype_name(XAR(x)->sbcache.st_mode & S_IFMT);
if( xar_check_prop(x, "type") )
xar_prop_set(f, "type", type);
}
/* Record major/minor device node numbers */
if( xar_check_prop(x, "device") && (S_ISBLK(XAR(x)->sbcache.st_mode) || S_ISCHR(XAR(x)->sbcache.st_mode))) {
uint32_t major, minor;
char tmpstr[12];
xar_devmake(XAR(x)->sbcache.st_rdev, &major, &minor);
memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%u", major);
xar_prop_set(f, "device/major", tmpstr);
memset(tmpstr, 0, sizeof(tmpstr));
snprintf(tmpstr, sizeof(tmpstr)-1, "%u", minor);
xar_prop_set(f, "device/minor", tmpstr);
}
if( S_ISLNK(XAR(x)->sbcache.st_mode) ) {
char link[4096];
struct stat lsb;
memset(link, 0, sizeof(link));
readlink(file, link, sizeof(link)-1);
xar_prop_set(f, "link", link);
if( stat(file, &lsb) != 0 ) {
xar_attr_set(f, "link", "type", "broken");
} else {
type = filetype_name(lsb.st_mode & S_IFMT);
xar_attr_set(f, "link", "type", type);
}
}
if( xar_check_prop(x, "inode") ) {
asprintf(&tmpstr, "%"INO_STRING, XAR(x)->sbcache.st_ino);
xar_prop_set(f, "inode", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "deviceno") ) {
asprintf(&tmpstr, "%"DEV_STRING, XAR(x)->sbcache.st_dev);
xar_prop_set(f, "deviceno", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "mode") ) {
asprintf(&tmpstr, "%04o", XAR(x)->sbcache.st_mode & (~S_IFMT));
xar_prop_set(f, "mode", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "uid") ) {
asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_uid);
xar_prop_set(f, "uid", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "user") ) {
pw = getpwuid(XAR(x)->sbcache.st_uid);
if( pw )
xar_prop_set(f, "user", pw->pw_name);
}
if( xar_check_prop(x, "gid") ) {
asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_gid);
xar_prop_set(f, "gid", tmpstr);
free(tmpstr);
}
if( xar_check_prop(x, "group") ) {
gr = getgrgid(XAR(x)->sbcache.st_gid);
if( gr )
xar_prop_set(f, "group", gr->gr_name);
}
if( xar_check_prop(x, "atime") ) {
gmtime_r(&XAR(x)->sbcache.st_atime, &t);
memset(time, 0, sizeof(time));
strftime(time, sizeof(time), "%FT%T", &t);
strcat(time, "Z");
xar_prop_set(f, "atime", time);
}
if( xar_check_prop(x, "mtime") ) {
gmtime_r(&XAR(x)->sbcache.st_mtime, &t);
memset(time, 0, sizeof(time));
strftime(time, sizeof(time), "%FT%T", &t);
strcat(time, "Z");
xar_prop_set(f, "mtime", time);
}
if( xar_check_prop(x, "ctime") ) {
gmtime_r(&XAR(x)->sbcache.st_ctime, &t);
memset(time, 0, sizeof(time));
strftime(time, sizeof(time), "%FT%T", &t);
strcat(time, "Z");
xar_prop_set(f, "ctime", time);
}
flags_archive(x, f, &(XAR(x)->sbcache));
aacls(x, f, file);
return 0;
}
int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
const char *opt;
int32_t m=0, mset=0;
uid_t u;
gid_t g;
const char *timestr;
struct tm t;
enum {ATIME=0, MTIME};
struct timeval tv[2];
char savesuid = 0;
/* when writing to a buffer, there are no permissions to set */
if ( len )
return 0;
/* in case we don't find anything useful in the archive */
u = geteuid();
g = getegid();
opt = xar_opt_get(x, XAR_OPT_OWNERSHIP);
if( opt && (strcmp(opt, XAR_OPT_VAL_SYMBOLIC) == 0) ) {
struct passwd *pw;
struct group *gr;
xar_prop_get(f, "user", &opt);
if( opt ) {
pw = getpwnam(opt);
if( pw ) {
u = pw->pw_uid;
}
}
xar_prop_get(f, "group", &opt);
if( opt ) {
gr = getgrnam(opt);
if( gr ) {
g = gr->gr_gid;
}
}
savesuid = 1;
}
if( opt && (strcmp(opt, XAR_OPT_VAL_NUMERIC) == 0) ) {
xar_prop_get(f, "uid", &opt);
if( opt ) {
long long tmp;
tmp = strtol(opt, NULL, 10);
if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) {
return -1;
}
u = (uid_t)tmp;
}
xar_prop_get(f, "gid", &opt);
if( opt ) {
long long tmp;
tmp = strtol(opt, NULL, 10);
if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) {
return -1;
}
g = (gid_t)tmp;
}
savesuid = 1;
}
opt = xar_opt_get(x, XAR_OPT_SAVESUID);
if( opt && (strcmp(opt, XAR_OPT_VAL_TRUE) == 0) ) {
savesuid = 1;
}
xar_prop_get(f, "mode", &opt);
if( opt ) {
long long tmp;
tmp = strtoll(opt, NULL, 8);
if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) {
return -1;
}
m = (mode_t)tmp;
if( !savesuid ) {
m &= ~S_ISUID;
m &= ~S_ISGID;
}
mset = 1;
}
xar_prop_get(f, "type", &opt);
if( opt && !mset ) {
mode_t u = umask(0);
umask(u);
if( strcmp(opt, "directory") == 0 ) {
m = (mode_t)(0777 & ~u);
} else {
m = (mode_t)(0666 & ~u);
}
mset = 1;
}
if( opt && (strcmp(opt, "symlink") == 0) ) {
#ifdef HAVE_LCHOWN
if( lchown(file, u, g) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not lchown symlink");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
m &= ~S_ISUID;
m &= ~S_ISGID;
}
#ifdef HAVE_LCHMOD
if( mset )
if( lchmod(file, m) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not lchmod symlink");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
#endif
#endif
} else {
if( chown(file, u, g) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not chown file");
xar_err_set_errno(x, errno);
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
m &= ~S_ISUID;
m &= ~S_ISGID;
}
if( mset )
if( chmod(file, m) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "perm: could not chmod file");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
}
eacls(x, f, file);
memset(tv, 0, sizeof(struct timeval) * 2);
xar_prop_get(f, "atime", &timestr);
if( timestr ) {
memset(&t, 0, sizeof(t));
strptime(timestr, "%FT%T", &t);
tv[ATIME].tv_sec = timegm(&t);
} else {
tv[ATIME].tv_sec = time(NULL);
}
xar_prop_get(f, "mtime", &timestr);
if( timestr ) {
memset(&t, 0, sizeof(t));
strptime(timestr, "%FT%T", &t);
tv[MTIME].tv_sec = timegm(&t);
} else {
tv[MTIME].tv_sec = time(NULL);
}
utimes(file, tv);
return 0;
}
int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
const char *opt;
int ret, fd;
mode_t modet = 0;
xar_prop_get(f, "type", &opt);
if(opt && ( (strcmp(opt, "character special") == 0) || (strcmp(opt, "block special") == 0)) ) {
// We do not extract device nodes anymore
return -1;
}
if(opt && (strcmp(opt, "directory") == 0)) {
ret = mkdir(file, 0700);
if( (ret != 0) && (errno != EEXIST)) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not create directory");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return ret;
}
if (errno == EEXIST) {
struct stat statdata;
if (lstat(file, &statdata) != 0 || (statdata.st_mode & S_IFDIR) == 0)
{
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not create directory because overwriting file is not a directory");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return EINVAL;
}
}
return 0;
}
if(opt && (strcmp(opt, "symlink") == 0)) {
xar_prop_get(f, "link", &opt);
if( opt ) {
unlink(file);
ret = symlink(opt, file);
if( ret != 0 ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not create symlink");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
}
return ret;
}
}
if(opt && (strcmp(opt, "hardlink") == 0)) {
xar_file_t tmpf;
opt = xar_attr_get(f, "type", "link");
if( !opt )
return 0;
if( strcmp(opt, "original") == 0 )
goto CREATEFILE;
tmpf = xmlHashLookup(XAR(x)->link_hash, BAD_CAST(opt));
if( !tmpf ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Encountered hardlink with no original");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
unlink(file);
if( link(XAR_FILE(tmpf)->fspath, file) != 0 ) {
if( errno == ENOENT ) {
xar_iter_t i;
const char *ptr;
i = xar_iter_new();
for(ptr = xar_prop_first(tmpf, i); ptr; ptr = xar_prop_next(i)) {
xar_iter_t a;
const char *val = NULL;
const char *akey, *aval;
if( strncmp("data", ptr, 4) != 0 )
continue;
if( xar_prop_get(tmpf, ptr, &val) )
continue;
xar_prop_set(f, ptr, val);
a = xar_iter_new();
for(akey = xar_attr_first(tmpf, ptr, a); akey; akey = xar_attr_next(a)) {
aval = xar_attr_get(tmpf, ptr, akey);
xar_attr_set(f, ptr, akey, aval);
}
xar_iter_free(a);
}
xar_iter_free(i);
xar_attr_set(f, "type", "link", "original");
return 0;
} else {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "stat: Could not link hardlink to original");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
}
return 0;
}
if(opt && (strcmp(opt, "fifo") == 0)) {
unlink(file);
if( mkfifo(file, 0) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "mkfifo: Could not create fifo");
xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
return 0;
}
/* skip sockets */
if(opt && (strcmp(opt, "socket") == 0)) {
return 0;
}
CREATEFILE:
if (!file)
return 0;
unlink(file);
fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0600);
if( fd > 0 )
close(fd);
return 0;
}

48
xar/lib/stat.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_STAT_H_
#define _XAR_STAT_H_
#include "xar.h"
int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len);
int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len);
int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len);
int32_t xar_flags_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len);
#endif /* _XAR_STAT_H_ */

149
xar/lib/strmode.h Normal file
View File

@ -0,0 +1,149 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef HAVE_STRMODE
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void
strmode(mode, p)
mode_t mode;
char *p;
{
/* print type */
switch (mode & S_IFMT) {
case S_IFDIR: /* directory */
*p++ = 'd';
break;
case S_IFCHR: /* character special */
*p++ = 'c';
break;
case S_IFBLK: /* block special */
*p++ = 'b';
break;
case S_IFREG: /* regular */
*p++ = '-';
break;
case S_IFLNK: /* symbolic link */
*p++ = 'l';
break;
case S_IFSOCK: /* socket */
*p++ = 's';
break;
#ifdef S_IFIFO
case S_IFIFO: /* fifo */
*p++ = 'p';
break;
#endif
#ifdef S_IFWHT
case S_IFWHT: /* whiteout */
*p++ = 'w';
break;
#endif
default: /* unknown */
*p++ = '?';
break;
}
/* usr */
if (mode & S_IRUSR)
*p++ = 'r';
else
*p++ = '-';
if (mode & S_IWUSR)
*p++ = 'w';
else
*p++ = '-';
switch (mode & (S_IXUSR | S_ISUID)) {
case 0:
*p++ = '-';
break;
case S_IXUSR:
*p++ = 'x';
break;
case S_ISUID:
*p++ = 'S';
break;
case S_IXUSR | S_ISUID:
*p++ = 's';
break;
}
/* group */
if (mode & S_IRGRP)
*p++ = 'r';
else
*p++ = '-';
if (mode & S_IWGRP)
*p++ = 'w';
else
*p++ = '-';
switch (mode & (S_IXGRP | S_ISGID)) {
case 0:
*p++ = '-';
break;
case S_IXGRP:
*p++ = 'x';
break;
case S_ISGID:
*p++ = 'S';
break;
case S_IXGRP | S_ISGID:
*p++ = 's';
break;
}
/* other */
if (mode & S_IROTH)
*p++ = 'r';
else
*p++ = '-';
if (mode & S_IWOTH)
*p++ = 'w';
else
*p++ = '-';
switch (mode & (S_IXOTH | S_ISVTX)) {
case 0:
*p++ = '-';
break;
case S_IXOTH:
*p++ = 'x';
break;
case S_ISVTX:
*p++ = 'T';
break;
case S_IXOTH | S_ISVTX:
*p++ = 't';
break;
}
*p++ = ' '; /* will be a '+' if ACL's implemented */
*p = '\0';
}
#endif /* HAVE_STRMODE */

218
xar/lib/subdoc.c Normal file
View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 04-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
#define _FILE_OFFSET_BITS 64
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libxml/xmlwriter.h>
#include <libxml/xmlreader.h>
#include "xar.h"
#include "subdoc.h"
#include "archive.h"
#include "filetree.h"
xar_subdoc_t xar_subdoc_new(xar_t x, const char *name) {
xar_subdoc_t ret;
if( xar_subdoc_find(x, name) )
return NULL;
ret = malloc(sizeof(struct __xar_subdoc_t));
if( ! ret )
return NULL;
memset(XAR_SUBDOC(ret), 0, sizeof(struct __xar_subdoc_t));
XAR_SUBDOC(ret)->name = strdup(name);
XAR_SUBDOC(ret)->next = XAR_SUBDOC(XAR(x)->subdocs);
XAR(x)->subdocs = ret;
XAR_SUBDOC(ret)->x = x;
return ret;
}
int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value){
return xar_prop_set((xar_file_t)s, key, value);
}
int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value) {
return xar_prop_get((xar_file_t)s, key, value);
}
int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value){
return xar_attr_set((xar_file_t)s, prop, key, value);
}
const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key) {
return xar_attr_get((xar_file_t)s, prop, key);
}
xar_subdoc_t xar_subdoc_first(xar_t x) {
return XAR(x)->subdocs;
}
xar_subdoc_t xar_subdoc_next(xar_subdoc_t s) {
return XAR_SUBDOC(s)->next;
}
const char *xar_subdoc_name(xar_subdoc_t s) {
return XAR_SUBDOC(s)->name;
}
xar_subdoc_t xar_subdoc_find(xar_t x, const char *name)
{
xar_subdoc_t i;
for(i = XAR(x)->subdocs; i; i = XAR_SUBDOC(i)->next) {
if( strcmp(name, XAR_SUBDOC(i)->name) == 0 )
return i;
}
return NULL;
}
int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **ret, unsigned int *size) {
xmlBufferPtr buf;
xmlTextWriterPtr writer;
buf = xmlBufferCreate();
if( !buf )
return -1;
writer = xmlNewTextWriterMemory(buf, 0);
if( !writer ) {
xmlBufferFree(buf);
return -1;
}
xmlTextWriterSetIndent(writer, 4);
xar_subdoc_serialize(s, writer, 0);
xmlTextWriterEndDocument(writer);
xmlFreeTextWriter(writer);
if( size != NULL )
*size = buf->use;
*ret = malloc(buf->size);
if( *ret == NULL ) {
xmlBufferFree(buf);
return -1;
}
assert(size != NULL);
memcpy(*ret, buf->content, *size);
xmlBufferFree(buf);
return 0;
}
int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *buf, unsigned int len) {
xmlTextReaderPtr reader;
reader = xmlReaderForMemory((const char *)buf, len, NULL, NULL, 0);
if( !reader )
return -1;
xar_subdoc_unserialize(s, reader);
xmlFreeTextReader(reader);
return 0;
}
/* xar_subdoc_serialize
* s: a subdoc structure allocated and initialized by xar_subdoc_new()
* writer: and xmlTextWriterPtr that has already been opend and initialized
* and is pointing to the place where the subdocument will be serialized.
* wrap: an integer describing whether the subdocument is to be wrapped
* for placement in the xml header of an archive, or if we are trying to
* reconstruct the original document. 1 for wrapping, 0 for original.
*/
void xar_subdoc_serialize(xar_subdoc_t s, xmlTextWriterPtr writer, int wrap) {
if( !s ) return;
if( wrap ) {
xmlTextWriterStartElementNS(writer, BAD_CAST(XAR_SUBDOC(s)->prefix), BAD_CAST("subdoc"), BAD_CAST(XAR_SUBDOC(s)->ns));
xmlTextWriterWriteAttribute(writer, BAD_CAST("subdoc_name"), BAD_CAST(XAR_SUBDOC(s)->name));
if( XAR_SUBDOC(s)->value )
xmlTextWriterWriteString(writer, BAD_CAST(XAR_SUBDOC(s)->value));
}
xar_prop_serialize(XAR_SUBDOC(s)->props, writer);
xmlTextWriterEndElement(writer);
}
void xar_subdoc_remove(xar_subdoc_t s) {
xar_prop_t p;
xar_subdoc_t tmp = xar_subdoc_first(XAR_SUBDOC(s)->x);
if( tmp == s ) {
XAR(XAR_SUBDOC(s)->x)->subdocs = XAR_SUBDOC(s)->next;
} else {
while(XAR_SUBDOC(tmp)->next) {
if( XAR_SUBDOC(tmp)->next == s ) {
XAR_SUBDOC(tmp)->next = XAR_SUBDOC(s)->next;
break;
}
tmp = xar_subdoc_next(tmp);
}
}
while(XAR_SUBDOC(s)->props) {
p = XAR_SUBDOC(s)->props;
XAR_SUBDOC(s)->props = XAR_PROP(XAR_PROP(p)->next);
xar_prop_free(p);
}
free((char *)XAR_SUBDOC(s)->blank1);
free((char *)XAR_SUBDOC(s)->name);
free((void *)s);
return;
}
void xar_subdoc_unserialize(xar_subdoc_t s, xmlTextReaderPtr reader) {
int type;
while( xmlTextReaderRead(reader) == 1 ) {
type = xmlTextReaderNodeType(reader);
if( type == XML_READER_TYPE_ELEMENT ) {
xar_prop_unserialize((xar_file_t)s, NULL, reader);
}
if( type == XML_READER_TYPE_TEXT ) {
const char *value;
value = (const char *)xmlTextReaderConstValue(reader);
free((char*)XAR_SUBDOC(s)->value);
XAR_SUBDOC(s)->value = strdup(value);
}
if( type == XML_READER_TYPE_END_ELEMENT ) {
break;
}
}
return;
}

61
xar/lib/subdoc.h Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
#ifndef _XAR_SUBDOC_H_
#define _XAR_SUBDOC_H_
#include "xar.h"
#include "filetree.h"
struct __xar_subdoc_t {
struct __xar_prop_t *props;
struct __xar_attr_t *attrs;
const char *prefix;
const char *ns;
const char *blank1; /* filler for xar_file_t compatibility */
const char *blank2; /* filler for xar_file_t compatibility */
const char blank3; /* filler for xar_file_t compatibility */
const char *name;
struct __xar_subdoc_t *next;
const char *value; /* a subdoc should very rarely have a value */
xar_t x;
};
#define XAR_SUBDOC(x) ((struct __xar_subdoc_t *)(x))
void xar_subdoc_unserialize(xar_subdoc_t s, xmlTextReaderPtr reader);
void xar_subdoc_serialize(xar_subdoc_t s, xmlTextWriterPtr writer, int wrap);
void xar_subdoc_free(xar_subdoc_t s);
xar_subdoc_t xar_subdoc_find(xar_t x, const char *name);
#endif /* _XAR_SUBDOC_H_ */

466
xar/lib/util.c Normal file
View File

@ -0,0 +1,466 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include "xar.h"
#include "archive.h"
#include "filetree.h"
// SC: This is function is a exact copy of dirname BUT instead of
// just using the same buffer over and over again, we allocate one.
// This means the result needs to be freed, but it also means the
// result will be correct.
char *xar_safe_dirname(const char *path)
{
char *dname = malloc(MAXPATHLEN);
size_t len;
const char *endp;
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
dname[0] = '.';
dname[1] = '\0';
return (dname);
}
/* Strip any trailing slashes */
endp = path + strlen(path) - 1;
while (endp > path && *endp == '/')
endp--;
/* Find the start of the dir */
while (endp > path && *endp != '/')
endp--;
/* Either the dir is "/" or there are no slashes */
if (endp == path) {
dname[0] = *endp == '/' ? '/' : '.';
dname[1] = '\0';
return (dname);
} else {
/* Move forward past the separating slashes */
do {
endp--;
} while (endp > path && *endp == '/');
}
len = endp - path + 1;
if (len >= MAXPATHLEN) {
errno = ENAMETOOLONG;
free(dname);
return (NULL);
}
memcpy(dname, path, len);
dname[len] = '\0';
return (dname);
}
uint64_t xar_ntoh64(uint64_t num) {
int t = 1234;
union conv {
uint64_t i64;
uint32_t i32[2];
} *in, out;
if( ntohl(t) == t ) {
out.i64 = num;
return out.i64;
}
in = (union conv *)&num;
out.i32[1] = ntohl(in->i32[0]);
out.i32[0] = ntohl(in->i32[1]);
return(out.i64);
}
uint32_t xar_swap32(uint32_t num) {
uint8_t *one, *two;
uint32_t ret;
two = (uint8_t *)&ret;
one = (uint8_t *)&num;
two[3] = one[0];
two[2] = one[1];
two[1] = one[2];
two[0] = one[3];
return ret;
}
/* xar_get_path
* Summary: returns the archive path of the file f.
* Caller needs to free the return value.
*/
char *xar_get_path(xar_file_t f) {
char *ret, *tmp;
const char *name;
xar_file_t i;
xar_prop_get(f, "name", &name);
if( name == NULL ) {
return NULL;
}
ret = strdup(name);
for(i = XAR_FILE(f)->parent; i; i = XAR_FILE(i)->parent) {
const char *name;
xar_prop_get(i, "name", &name);
tmp = ret;
asprintf(&ret, "%s/%s", name, tmp);
free(tmp);
}
return ret;
}
off_t xar_get_heap_offset(xar_t x) {
return XAR(x)->toc_count + sizeof(xar_header_t);
}
/* xar_read_fd
* Summary: Reads from a file descriptor a certain number of bytes to a specific
* buffer. This simple wrapper just handles certain retryable error situations.
* Returns -1 when it fails fatally; the number of bytes read otherwise.
*/
ssize_t xar_read_fd( int fd, void * buffer, size_t nbyte ) {
ssize_t rb;
ssize_t total = 0;
while ( total < nbyte ) {
rb = read(fd, ((char *)buffer)+total, nbyte-total);
if( rb == 0 ) {
return total;
} else if( rb < 0 ) {
if( (errno == EINTR) || (errno == EAGAIN) )
continue;
return rb;
}
total += rb;
}
return total;
}
/* xar_pread_fd
* Summary: Does the same as xar_read_fd, but uses pread(2) instead of read(2).
*/
ssize_t xar_pread_fd(int fd, void * buffer, size_t nbyte, off_t offset) {
ssize_t rb;
ssize_t total = 0;
while ( total < nbyte ) {
rb = pread(fd, ((char *)buffer)+total, nbyte-total, offset+total);
if( rb == 0 ) {
return total;
} else if( rb < 0 ) {
if( (errno == EINTR) || (errno == EAGAIN) )
continue;
return rb;
}
total += rb;
}
return total;
}
/* xar_write_fd
* Summary: Writes from a buffer to a file descriptor. Like xar_read_fd it
* also just handles certain retryable error situations.
* Returns -1 when it fails fatally; the number of bytes written otherwise.
*/
ssize_t xar_write_fd( int fd, void * buffer, size_t nbyte ) {
ssize_t rb;
ssize_t total = 0;
while ( total < nbyte ) {
rb = write(fd, ((char *)buffer)+total, nbyte-total);
if( rb == 0 ) {
return total;
} else if( rb < 0 ) {
if( (errno == EINTR) || (errno == EAGAIN) )
continue;
return rb;
}
total += rb;
}
return total;
}
/* xar_pwrite_fd
* Summary: Does the same as xar_write_fd, but uses pwrite(2) instead of write(2).
*/
ssize_t xar_pwrite_fd( int fd, void * buffer, size_t nbyte, off_t offset ) {
ssize_t rb;
size_t total = 0;
while( total < nbyte ) {
rb = pwrite(fd, ((char *)buffer)+total, nbyte-total, offset+total);
if( rb == 0 ) {
return total;
} else if( rb < 0 ) {
if( (errno == EINTR) || (errno == EAGAIN) )
continue;
return rb;
}
total += rb;
}
return total;
}
dev_t xar_makedev(uint32_t major, uint32_t minor)
{
#ifdef makedev
return makedev(major, minor);
#else
return (major << 8) | minor;
#endif
}
void xar_devmake(dev_t dev, uint32_t *out_major, uint32_t *out_minor)
{
#ifdef major
*out_major = major(dev);
#else
*out_major = (dev >> 8) & 0xFF;
#endif
#ifdef minor
*out_minor = minor(dev);
#else
*out_minor = dev & 0xFF;
#endif
return;
}
char* xar_path_nextcomponent(char** path_to_advance) {
char* component_start = *path_to_advance;
unsigned int component_length = 1;
char* out_component = NULL;
if (**path_to_advance == '\0') // If we're trying to look at the end of the path, punt
return NULL;
for (; **path_to_advance && (**path_to_advance != '/'); ++(*path_to_advance), ++component_length) {
if (**path_to_advance == '\\') { // Escape ignores next char
++(*path_to_advance);
++component_length;
continue;
}
}
if (**path_to_advance == '/') {
++(*path_to_advance);
}
out_component = (char*)malloc(component_length);
strncpy(out_component, component_start, component_length);
out_component[component_length-1] = 0;
return out_component;
}
int xar_path_issane(char* path) {
char* path_walker = path;
char* component = NULL;
int path_depth = 0;
if (path == NULL) {
return 0;
}
// Ban 0 length / absolute paths.
if (strlen(path) == 0 || path[0] == '/')
return 0;
while ((component = xar_path_nextcomponent(&path_walker))) {
if (strlen(component) == 0 || strcmp(component, ".") == 0) { // Since // is legal, and '.' is legal it's possible to have empty path elements. Ignore them
free(component);
continue;
}
if (strcmp(component, ".."))
++path_depth;
else
--path_depth;
free(component);
if (path_depth < 0) // We've escaped our root, this path is not sane.
return 0;
}
return 1;
}
#ifndef HAVE_STRMODE
#include "strmode.h"
#endif
char *xar_get_type(xar_t x, xar_file_t f) {
const char *type = NULL;
xar_prop_get(f, "type", &type);
if( type == NULL )
type = "unknown";
return strdup(type);
}
char *xar_get_size(xar_t x, xar_file_t f) {
const char *size = NULL;
const char *type = NULL;
xar_prop_get(f, "type", &type);
if( type != NULL ) {
if( strcmp(type, "hardlink") == 0 ) {
const char *link = NULL;
link = xar_attr_get(f, "type", "link");
if( link ) {
if( strcmp(link, "original") != 0 ) {
xar_iter_t i;
i = xar_iter_new();
if( i ) {
xar_file_t tmpf;
for(tmpf = xar_file_first(x, i); tmpf; tmpf = xar_file_next(i)) {
const char *id;
id = xar_attr_get(tmpf, NULL, "id");
if( !id ) continue;
if( strcmp(id, link) == 0 ) {
f = tmpf;
break;
}
}
}
xar_iter_free(i);
}
}
}
}
xar_prop_get(f, "data/size", &size);
if( size == NULL )
size = "0";
return strdup(size);
}
char *xar_get_mode(xar_t x, xar_file_t f) {
const char *mode = NULL;
const char *type = NULL;
char *ret;
mode_t m;
xar_prop_get(f, "mode", &mode);
if( mode == NULL )
return strdup("??????????");
errno = 0;
m = strtoll(mode, 0, 8);
if( errno )
return strdup("??????????");
xar_prop_get(f, "type", &type);
if( type == NULL )
return strdup("??????????");
if( strcmp(type, "file") == 0 )
m |= S_IFREG;
else if( strcmp(type, "hardlink") == 0 )
m |= S_IFREG;
else if( strcmp(type, "directory") == 0 )
m |= S_IFDIR;
else if( strcmp(type, "symlink") == 0 )
m |= S_IFLNK;
else if( strcmp(type, "fifo") == 0 )
m |= S_IFIFO;
else if( strcmp(type, "character special") == 0 )
m |= S_IFCHR;
else if( strcmp(type, "block special") == 0 )
m |= S_IFBLK;
else if( strcmp(type, "socket") == 0 )
m |= S_IFSOCK;
#ifdef S_IFWHT
else if( strcmp(type, "whiteout") == 0 )
m |= S_IFWHT;
#endif
ret = calloc(12,1);
strmode(m, ret);
return ret;
}
char *xar_get_owner(xar_t x, xar_file_t f) {
const char *user = NULL;
xar_prop_get(f, "user", &user);
if( !user )
return strdup("unknown");
return strdup(user);
}
char *xar_get_group(xar_t x, xar_file_t f) {
const char *group = NULL;
xar_prop_get(f, "group", &group);
if( !group )
return strdup("unknown");
return strdup(group);
}
char *xar_get_mtime(xar_t x, xar_file_t f) {
const char *mtime = NULL;
char *tmp;
struct tm tm;
xar_prop_get(f, "mtime", &mtime);
if( !mtime )
mtime = "1970-01-01T00:00:00Z";
strptime(mtime, "%FT%T", &tm);
tmp = calloc(128,1);
strftime(tmp, 127, "%F %T", &tm);
return tmp;
}

68
xar/lib/util.h Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
* Steven Cento <cento@apple.com>
*/
#ifndef _XAR_UTIL_H_
#define _XAR_UTIL_H_
#include <stdint.h>
#include "xar.h"
uint64_t xar_ntoh64(uint64_t num);
uint32_t xar_swap32(uint32_t num);
char *xar_get_path(xar_file_t f);
off_t xar_get_heap_offset(xar_t x);
ssize_t xar_read_fd(int fd, void * buffer, size_t nbyte);
ssize_t xar_pread_fd(int fd, void * buffer, size_t nbyte, off_t offset);
ssize_t xar_write_fd(int fd, void * buffer, size_t nbyte);
ssize_t xar_pwrite_fd( int fd, void * buffer, size_t nbyte, off_t offset );
dev_t xar_makedev(uint32_t major, uint32_t minor);
void xar_devmake(dev_t dev, uint32_t *major, uint32_t *minor);
char* xar_safe_dirname(const char* path);
// This is used to check to see if a given path escapes from
// the extraction root.
int xar_path_issane(char* path);
// Returns a string containing the name of the next path component in path_to_advance.
// Path to advance also gets moved forward to the start of the next component in the path.
// The returned string must be released by the caller.
char* xar_path_nextcomponent(char** path_to_advance);
#endif /* _XAR_UTIL_H_ */

263
xar/lib/zxar.c Normal file
View File

@ -0,0 +1,263 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#include "config.h"
#ifndef HAVE_ASPRINTF
#include "asprintf.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <zlib.h>
#include <errno.h>
#include "xar.h"
#include "filetree.h"
#include "io.h"
struct _gzip_context{
uint8_t gzipcompressed;
uint64_t count;
z_stream z;
};
#define GZIP_CONTEXT(x) ((struct _gzip_context *)(*x))
int xar_gzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
if( !context || !GZIP_CONTEXT(context) )
return 0;
if( GZIP_CONTEXT(context)->gzipcompressed){
inflateEnd(&GZIP_CONTEXT(context)->z);
}
/* free the context */
free(GZIP_CONTEXT(context));
*context = NULL;
return 0;
}
int xar_gzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
const char *opt;
void *out = NULL;
size_t outlen, offset = 0;
int r;
xar_prop_t tmpp;
/* on first run, we init the context and check the compression type */
if( !GZIP_CONTEXT(context) ) {
*context = calloc(1,sizeof(struct _gzip_context));
opt = NULL;
tmpp = xar_prop_pget(p, "encoding");
if( tmpp )
opt = xar_attr_pget(f, tmpp, "style");
if( !opt ) return 0;
if( strcmp(opt, "application/x-gzip") != 0 ) return 0;
inflateInit(&GZIP_CONTEXT(context)->z);
GZIP_CONTEXT(context)->gzipcompressed = 1;
}else if( !GZIP_CONTEXT(context)->gzipcompressed ){
/* once the context has been initialized, then we have already
checked the compression type, so we need only check if we
actually are compressed */
return 0;
}
outlen = *inlen;
GZIP_CONTEXT(context)->z.next_in = *in;
GZIP_CONTEXT(context)->z.avail_in = *inlen;
GZIP_CONTEXT(context)->z.next_out = out;
GZIP_CONTEXT(context)->z.avail_out = 0;
while( GZIP_CONTEXT(context)->z.avail_in != 0 ) {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
GZIP_CONTEXT(context)->z.next_out = ((unsigned char *)out) + offset;
GZIP_CONTEXT(context)->z.avail_out = outlen - offset;
size_t start_avail_in = GZIP_CONTEXT(context)->z.avail_in;
size_t start_avail_out = GZIP_CONTEXT(context)->z.avail_out;
r = inflate(&(GZIP_CONTEXT(context)->z), Z_NO_FLUSH);
if( (r != Z_OK) && (r != Z_STREAM_END) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error decompressing file");
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION);
return -1;
}
offset += outlen - offset - GZIP_CONTEXT(context)->z.avail_out;
}
free(*in);
*in = out;
*inlen = offset;
return 0;
}
int xar_gzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) {
xar_prop_t tmpp;
if( GZIP_CONTEXT(context)->gzipcompressed){
deflateEnd(&GZIP_CONTEXT(context)->z);
if( GZIP_CONTEXT(context)->count ) {
tmpp = xar_prop_pset(f, p, "encoding", NULL);
if( tmpp )
xar_attr_pset(f, tmpp, "style", "application/x-gzip");
}
}
/* free the context */
free(GZIP_CONTEXT(context));
*context = NULL;
return 0;
}
int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) {
void *out = NULL;
size_t outlen, offset = 0;
int r;
const char *opt;
/* on first run, we init the context and check the compression type */
if( !GZIP_CONTEXT(context) ) {
int level = Z_BEST_COMPRESSION;
*context = calloc(1,sizeof(struct _gzip_context));
opt = xar_opt_get(x, XAR_OPT_COMPRESSION);
if( !opt )
return 0;
if( strcmp(opt, XAR_OPT_VAL_GZIP) != 0 )
return 0;
opt = xar_opt_get(x, XAR_OPT_COMPRESSIONARG);
if( opt ) {
int tmp;
errno = 0;
tmp = strtol(opt, NULL, 10);
if( errno == 0 ) {
if( (level >= 0) && (level <= 9) )
level = tmp;
}
}
deflateInit(&GZIP_CONTEXT(context)->z, level);
GZIP_CONTEXT(context)->gzipcompressed = 1;
if( *inlen == 0 )
return 0;
}else if( !GZIP_CONTEXT(context)->gzipcompressed ){
/* once the context has been initialized, then we have already
checked the compression type, so we need only check if we
actually are compressed */
return 0;
}
outlen = *inlen/2;
if(outlen == 0) outlen = 1024;
GZIP_CONTEXT(context)->z.next_in = *in;
GZIP_CONTEXT(context)->z.avail_in = *inlen;
GZIP_CONTEXT(context)->z.next_out = out;
GZIP_CONTEXT(context)->z.avail_out = 0;
if( *inlen != 0 ) {
do {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
GZIP_CONTEXT(context)->z.next_out = ((unsigned char *)out) + offset;
GZIP_CONTEXT(context)->z.avail_out = outlen - offset;
r = deflate(&GZIP_CONTEXT(context)->z, Z_NO_FLUSH);
offset = outlen - GZIP_CONTEXT(context)->z.avail_out;
} while( r == Z_OK && GZIP_CONTEXT(context)->z.avail_in != 0 );
} else {
do {
size_t newlen = outlen * 2;
if (newlen > outlen)
outlen = newlen;
else
abort(); /* Someone has somehow malloced over 2^64 bits of ram. */
out = realloc(out, outlen);
if( out == NULL ) abort();
GZIP_CONTEXT(context)->z.next_out = ((unsigned char *)out) + offset;
GZIP_CONTEXT(context)->z.avail_out = outlen - offset;
r = deflate(&GZIP_CONTEXT(context)->z, Z_FINISH);
offset = outlen - GZIP_CONTEXT(context)->z.avail_out;
} while( r == Z_OK && r != Z_STREAM_END /* no-op */);
}
if( (r != Z_OK && r != Z_STREAM_END) ) {
xar_err_new(x);
xar_err_set_file(x, f);
xar_err_set_string(x, "Error compressing file");
xar_err_set_errno(x, r);
xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
return -1;
}
free(*in);
*in = out;
GZIP_CONTEXT(context)->count += *inlen;
*inlen = offset;
return 0;
}

46
xar/lib/zxar.h Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2005-2007 Rob Braun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Rob Braun nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 03-Apr-2005
* DRI: Rob Braun <bbraun@synack.net>
*/
/*
* Portions Copyright 2006, Apple Computer, Inc.
* Christopher Ryan <ryanc@apple.com>
*/
#ifndef _XAR_ZLIB_H_
#define _XAR_ZLIB_H_
int xar_gzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int xar_gzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context);
int xar_gzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context);
#endif /* _XAR_ZLIB_H_ */

4
xar/src/.cvsignore Normal file
View File

@ -0,0 +1,4 @@
Makefile.inc
ixar
xar
*.d

65
xar/src/Makefile.inc Normal file
View File

@ -0,0 +1,65 @@
#
# Include generated dependency files.
#
XAR_SRCS := xar.c
XAR_SRCS := $(patsubst %, src/%, $(XAR_SRCS))
-include $(XAR_SRCS:%.c=%.d)
src_all : src/xar src/ixar
src_install : src/ixar
.././install-sh -c -d $(DESTDIR)$(BINDIR)
.././install-sh -c -m 0755 $< $(DESTDIR)$(BINDIR)/xar
.././install-sh -c -d $(DESTDIR)$(MANDIR)/man1
.././install-sh -c -m 0644 src/xar.1 $(DESTDIR)$(MANDIR)/man1
src_uninstall :
rm -f $(DESTDIR)/$(BINDIR)/xar
rm -f $(DESTDIR)/$(MANDIR)/man1/xar.1
src_clean :
rm -f src/xar
rm -f src/ixar
rm -f $(XAR_SRCS:%.c=%.o)
rm -f $(XAR_SRCS:%.c=%.d)
src_distclean :
ifeq (yes, yes)
LIBRXAR := $(LIBRXAR_S)
endif
ifeq (yes, yes)
LIBRXAR := $(LIBXAR_A)
endif
# xar links against librxar, so that it can be run without first installing
# libxar.
src/% : src/%.o $(LIBRXAR)
@mkdir -p $(@D)
ifneq ($(words "" ), 1)
$(CC) $(CFLAGS) -o $@ $< /Users/ariel/LinuxHome/code/darling/src/xar/xar/lib $(LDFLAGS) $(LIBRXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
else
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBRXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
endif
ifeq (yes, yes)
LIBXAR := $(LIBXAR_A)
endif
ifeq (yes, yes)
LIBXAR := $(LIBXAR_S)
endif
# ixar is the version of the xar binary that gets installed.
src/i% : src/%.o $(LIBXAR)
@mkdir -p $(@D)
ifneq ($(words "" ), 1)
$(CC) $(CFLAGS) -o $@ $< $(LIBDIR) $(LDFLAGS) $(LIBXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
else
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm
endif
src/%.o : src/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"

65
xar/src/Makefile.inc.in Normal file
View File

@ -0,0 +1,65 @@
#
# Include generated dependency files.
#
XAR_SRCS := xar.c
XAR_SRCS := $(patsubst %, @srcroot@src/%, $(XAR_SRCS))
-include $(XAR_SRCS:@srcroot@%.c=@objroot@%.d)
src_all : @objroot@src/xar @objroot@src/ixar
src_install : @objroot@src/ixar
@INSTALL@ -d $(DESTDIR)$(BINDIR)
@INSTALL@ -m 0755 $< $(DESTDIR)$(BINDIR)/xar
@INSTALL@ -d $(DESTDIR)$(MANDIR)/man1
@INSTALL@ -m 0644 @srcroot@src/xar.1 $(DESTDIR)$(MANDIR)/man1
src_uninstall :
rm -f $(DESTDIR)/$(BINDIR)/xar
rm -f $(DESTDIR)/$(MANDIR)/man1/xar.1
src_clean :
rm -f @objroot@src/xar
rm -f @objroot@src/ixar
rm -f $(XAR_SRCS:@srcroot@%.c=@objroot@%.o)
rm -f $(XAR_SRCS:@srcroot@%.c=@objroot@%.d)
src_distclean :
ifeq (yes, @shared@)
LIBRXAR := $(LIBRXAR_S)
endif
ifeq (yes, @static@)
LIBRXAR := $(LIBXAR_A)
endif
# xar links against librxar, so that it can be run without first installing
# libxar.
@objroot@src/% : @objroot@src/%.o $(LIBRXAR)
@mkdir -p $(@D)
ifneq ($(words "" @RPATH@), 1)
$(CC) $(CFLAGS) -o $@ $< @RPATH@@abs_objroot@lib $(LDFLAGS) $(LIBRXAR) @LIBS@
else
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBRXAR) @LIBS@
endif
ifeq (yes, @static@)
LIBXAR := $(LIBXAR_A)
endif
ifeq (yes, @shared@)
LIBXAR := $(LIBXAR_S)
endif
# ixar is the version of the xar binary that gets installed.
@objroot@src/i% : @objroot@src/%.o $(LIBXAR)
@mkdir -p $(@D)
ifneq ($(words "" @RPATH@), 1)
$(CC) $(CFLAGS) -o $@ $< @RPATH@$(LIBDIR) $(LDFLAGS) $(LIBXAR) @LIBS@
else
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBXAR) @LIBS@
endif
@objroot@src/%.o : @srcroot@src/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"

158
xar/src/xar.1 Normal file
View File

@ -0,0 +1,158 @@
.TH XAR "1" "June 4, 2015" "version 1.8" "User Commands"
.SH NAME
xar \- eXtensible ARchiver
.SH SYNOPSIS
.B xar
\-[\fIctx\fR][\fIv\fR] ...
.SH DESCRIPTION
The XAR project aims to provide an easily extensible archive format. Important
design decisions include an easily extensible XML table of contents (TOC) for
random access to archived files, storing the TOC at the beginning of the
archive to allow for efficient handling of streamed archives, the ability to
handle files of arbitrarily large sizes, the ability to choose independent
encodings for individual files in the archive, the ability to store checksums
for individual files in both compressed and uncompressed form, and the ability
to query the table of content's rich meta-data.
.SH FUNCTIONS
.TP
.B One of the following options must be used:
.TP
\-c
Creates an archive
.TP
\-t
Lists the contents of an archive
.TP
\-x
Extracts an archive
.TP
.B NOTE: all of the above require the use of the -f option (filename) as this release of xar doesn't correctly handle pipes or sockets.
.TP
\-f
The filename to use for creation, listing or extraction. With extraction, this can be a POSIX regular expression.
.SH OPTIONS
.TP
\-\-compression
Specifies the compression type to use.
Valid values: none, gzip, bzip2, lzma (on some systems). Default value: gzip
.TP
\-C <path>
On extract, xar will chdir to the specified path before extracting the archive.
.TP
\-a
Synonym for \-\-compression=lzma
.TP
\-j
Synonym for \-\-compression=bzip2
.TP
\-z
Synonym for \-\-compression=gzip
.TP
\-\-compression-args=<arguments>
Specifies arguments to the compression engine selected.
gzip, bzip2, and lzma all take a single integer argument between 0 and 9 specifying the compression level to use.
.TP
\-\-dump\-toc=<filename>
Has xar dump the xml header into the specified file. "-" can be specified to mean stdout.
.TP
\-\-dump\-toc\-cksum
Dumps the ToC checksum to stdout along with the algorithm of the ToC.
.TP
\-\-dump\-header
Has xar print out the xar binary header information to stdout.
.TP
\-\-extract\-subdoc=<name>
Extracts the specified subdocument to a document in cwd named <name>.xml
.TP
\-\-list\-subdocs
List the subdocuments in the xml header
.TP
\-\-toc\-cksum
Specifies the hashing algorithm to use for xml header verification.
Valid values: md5 (on some systems), sha1, sha256, and sha512. Default value: sha1
.TP
\-\-file\-cksum
Specifies the hashing algorithm to use for file content verification.
Valid values: md5 (on some systems), sha1, sha256, and sha512. Default value: sha1
.TP
\-l
On archival, stay on the local device.
.TP
\-P
On extract, set ownership based on uid/gid. If the uid/gid can be set
on the extracted file, setuid/setgid bits will also be preserved.
.TP
\-p
On extract, set ownership based on symbolic names, if possible.
If the uid/gid can be set on the extracted file, setuid/setgid bits
will also be preserved.
.TP
\-s <filename>
On extract, specifies the file to extract subdocuments to.
On archival, specifies an xml file to add as a subdocument.
.TP
\-v
Verbose output
.TP
\-\-exclude
Specifies a POSIX regular expression of files to exclude from adding to
the archive during creation or from being extracted during extraction.
This option can be specified multiple times.
.TP
\-\-rsize
Specifies a size (in bytes) for the internal libxar read buffer while performing I/O.
.TP
\-\-coalesce-heap
When multiple files in the archive are identical, only store one copy of the data in the heap. This creates smaller archives, but the archives created are not streamable.
.TP
\-\-link-same
When the data section of multiple files are identical, hardlink them within the archive.
.TP
\-\-no-compress
Specifies a POSIX regular expression of files to archive, but not compress. The archived files will be copied raw into the archive. This can be used to exclude already gzipped files from being gzipped during the archival process.
.TP
\-\-prop-include
Specifies a file property to be included in the archive. When this option is specified, only the specified options will be included. Anything not specifically included with this option will be omitted. This option can be used multiple times.
.TP
\-\-prop-exclude
Specifies a file property to be excluded from the archive. When this option is specified, all file properties will be included except the specified properties. This option can be used multiple times.
.TP
\-\-distribution
Creates an archive to only contain file properties safe for file distribution. Currently, only name, type, mode, and data are preserved with this option.
.TP
\-\-keep-existing
Does not overwrite existing files during extraction. Keeps any previously existing files while extracting.
.TP
\-k
Synonym for \-\-keep-existing.
.TP
\-\-keep-setuid
When extracting without -p or -P options, xar will extract files as the
uid/gid of the extracting process. In this situation, xar will strip
setuid/setgid bits from the extracted files for security reasons.
\-\-keep-setuid will preserve the setuid/setgid bits even though the
uid/gid of the extracted file is not the same as the archived file.
.SH EXAMPLES
.TP
xar -cf sample.xar /home/uid
Create a xar archive of all files in /home/uid
.TP
xar -tf sample.xar
List the contents of the xar archive sample.xar
.TP
xar -xf sample.xar
Extract the contents of sample.xar to the current working directory
.SH BUGS
.TP
Doesn't currently work with pipes or streams. Might be fixed in a future release.
.TP
Probably one or two more somewhere in there. If you find one please report it to http://code.google.com/p/xar/
.SH AUTHORS
Rob Braun <bbraun AT synack DOT net>
.br
Landon Fuller <landonf AT bikemonkey DOT org>
.br
David Leimbach
.br
Kevin Van Vechten

1240
xar/src/xar.c Normal file

File diff suppressed because it is too large Load Diff

139
xar/test/attr.py Normal file
View File

@ -0,0 +1,139 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import os.path
import shutil
import subprocess
import xattr
import util
# Notes:
# * Due to internal buffer sizing, "large" should be at least 4096 bytes for
# uncompressed archives and archives with individual file compression, and
# and at least 32768 bytes for archives with compressed heaps.
# * For large files, we intentionally use a non-base-2 file size to ensure we
# catch file extraction bugs for files with a size not equal to the internal
# read buffer size (which is base-2).
# * For large extended attributes, we do the same thing.
#
# Utility Functions
#
class MissingExtendedAttributeError(AssertionError):
pass
def _random_big_data(bytes=65536, path="/dev/random"):
"""
Returns a random string with the number of bytes requested. Due to xar
implementation details, this should be greater than 4096 (32768 for
compressed heap testing).
"""
with open(path, "r") as f:
return f.read(bytes)
def _test_xattr_on_file_with_contents(filename, file_contents, xattrs=[], xar_create_flags=[], xar_extract_flags=[]):
try:
# Write file out
with open(filename, "w") as f:
f.write(file_contents)
for (key, value) in xattrs:
xattr.setxattr(f, key, value)
# Store it into a xarchive
archive_name = "{f}.xar".format(f=filename)
with util.archive_created(archive_name, filename, *xar_create_flags) as path:
# Extract xarchive
with util.directory_created("extracted") as directory:
# Validate resulting xattrs
subprocess.check_call(["xar", "-x", "-C", directory, "-f", path] + xar_extract_flags)
for (key, value) in xattrs:
try:
assert xattr.getxattr(os.path.join(directory, filename), key) == value, "extended attribute \"{n}\" has incorrect contents after extraction".format(n=key)
except KeyError:
raise MissingExtendedAttributeError("extended attribute \"{n}\" missing after extraction".format(n=key))
# Validate file contents
with open(os.path.join(directory, filename), "r") as f:
if f.read() != file_contents:
raise MissingExtendedAttributeError("archived file \"{f}\" has has incorrect contents after extraction".format(f=filename))
finally:
os.unlink(filename)
#
# Test Cases
#
# Note: xar currently drops empty extended attributes (and any xar_prop_t with empty contents, actually). The empty
# tests are commented out awaiting a day when this might be different.
# def empty_xattr_empty_file(filename):
# _test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "")])
def small_xattr_empty_file(filename):
_test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "1234")])
def large_xattr_empty_file(filename):
_test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", _random_big_data(5000))])
# def empty_xattr_small_file(filename):
# _test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", "")])
def small_xattr_small_file(filename):
_test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", "1234")])
def large_xattr_small_file(filename):
_test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", _random_big_data(4567))])
# def empty_xattr_large_file(filename):
# _test_xattr_on_file_with_contents(filename, _random_big_data(10000000), xattrs=[("foo", "")])
def small_xattr_large_file(filename):
_test_xattr_on_file_with_contents(filename, _random_big_data(5000000), xattrs=[("foo", "1234")])
def large_xattr_large_file(filename):
_test_xattr_on_file_with_contents(filename, _random_big_data(9876543), xattrs=[("foo", _random_big_data(6543))])
def multiple_xattrs(filename):
_test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "bar"), ("baz", "1234"), ("quux", "more")]) # ("empty", "")
def distribution_create(filename):
try:
_test_xattr_on_file_with_contents(filename, "dummy", xattrs=[("foo", "bar")], xar_create_flags=["--distribution"])
except MissingExtendedAttributeError:
pass
else:
raise AssertionError("no error encountered")
# Note: xar currently has no way to exclude a property on extraction. This test is commented out awaiting the day
# when it can.
# def distribution_extract(filename):
# try:
# _test_xattr_on_file_with_contents(filename, "dummy", xattrs=[("foo", "bar")], xar_extract_flags=["--distribution"])
# except MissingExtendedAttributeError:
# pass
# else:
# raise AssertionError("no error encountered")
TEST_CASES = (small_xattr_empty_file, large_xattr_empty_file,
small_xattr_small_file, large_xattr_small_file,
small_xattr_large_file, large_xattr_large_file,
multiple_xattrs, distribution_create)
if __name__ == "__main__":
for case in TEST_CASES:
try:
case(case.func_name)
print("PASSED: {f}".format(f=case.func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
import sys, os
print("FAILED: {f}".format(f=case.func_name))
sys.excepthook(*sys.exc_info())
print("")

79
xar/test/buffer.c Normal file
View File

@ -0,0 +1,79 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
#include <xar/xar.h>
int32_t err_callback(int32_t sev, int32_t err, xar_errctx_t ctx, void *usrctx)
{
printf("error callback invoked\n");
return 0;
}
int main(int argc, char *argv[])
{
int fd;
unsigned char *buffer;
struct stat sb;
ssize_t red;
xar_t x;
xar_file_t f, f2;
if( argc < 2 ) {
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
exit(1);
}
fd = open(argv[1], O_RDONLY);
if( fd < 0 ) {
fprintf(stderr, "Unable to open file %s\n", argv[1]);
exit(2);
}
if( fstat(fd, &sb) < 0 ) {
fprintf(stderr, "Unable to stat file %s\n", argv[1]);
exit(3);
}
buffer = malloc(sb.st_size);
if( buffer == NULL ) {
fprintf(stderr, "Unable to allocate memory\n");
exit(4);
}
red = read(fd, buffer, sb.st_size);
if( red <= 0 ) {
fprintf(stderr, "Error reading from file\n");
exit(5);
}
if( red < sb.st_size )
fprintf(stderr, "Incomplete read\n");
x = xar_open("/tmp/test.xar", WRITE);
if( x == NULL ) {
fprintf(stderr, "Error creating xarchive\n");
exit(6);
}
xar_register_errhandler(x, err_callback, NULL);
memset(&sb, 0, sizeof(sb));
sb.st_mode = S_IFDIR | S_IRWXU;
f = xar_add_folder(x, NULL, "mydir", &sb);
if( !f ) {
fprintf(stderr, "Error adding parent to archive\n");
exit(7);
}
f2 = xar_add_frombuffer(x, f, "secondfile", buffer, red);
if( !f ) {
fprintf(stderr, "Error adding child to archive\n");
exit(8);
}
xar_close(x);
close(fd);
exit(0);
}

225
xar/test/checksums.py Normal file
View File

@ -0,0 +1,225 @@
#!/usr/bin/env python
from __future__ import print_function
import hashlib
import os
import os.path
import re
import shutil
import struct
import subprocess
import util
#
# Utility Functions
#
def _get_numeric_value_from_header(archive_name, key):
"""
Dumps the header of the specified xar archive and extracts the header
size from the output, in bytes.
"""
header = subprocess.check_output(["xar", "--dump-header", "-f", archive_name])
for line in header.splitlines():
matchdata = re.match("^(.+):\s+(.+)$", line) # magic: 0x78617221 (OK)
assert matchdata, "unexpected output from `xar --dump-header`:\n{h}".format(h=header)
if matchdata.groups()[0] == key:
return int(matchdata.groups()[1])
raise AssertionError("no \"{k}\" found for archive \"{n}\":\n{h}".format(k=key, n=archive_name, h=header))
def _get_header_size(archive_name):
return _get_numeric_value_from_header(archive_name, "size")
def _get_toc_size(archive_name):
return _get_numeric_value_from_header(archive_name, "Compressed TOC length")
def _clobber_bytes_at(clobber_range, path):
with open(path, "r+") as f:
f.seek(clobber_range[0])
with open("/dev/random", "r") as r:
random_bytes = r.read(len(clobber_range))
f.write(random_bytes)
def _verify_extraction_failed(filename):
with util.directory_created("extracted") as directory:
try:
with open("/dev/null", "w") as n:
returncode = subprocess.call(["xar", "-x", "-C", directory, "-f", filename], stdout=n, stderr=n)
assert returncode != 0, "xar reported success extracting an archive with a broken TOC"
finally:
if os.path.exists(directory):
shutil.rmtree(directory)
def _hex_digest_string(raw_digest):
unpack_string = "B" * len(raw_digest)
format_string = "%02x" * len(raw_digest)
return format_string % struct.unpack(unpack_string, raw_digest)
def _verify_header_checksum(filename, algorithm):
header_size = _get_header_size(filename)
toc_length = _get_toc_size(filename)
with open(filename, "r") as f:
f.seek(header_size)
h = hashlib.new(algorithm, f.read(toc_length))
computed_digest = h.digest()
# We intentionally ignore the TOC-specified offset. We should build a variant of this that uses the TOC
# offset so we check both.
stored_digest = f.read(len(computed_digest))
assert computed_digest == stored_digest, "Digests don't match: expected value {d1} != stored value {d2}".format(d1=_hex_digest_string(computed_digest), d2=_hex_digest_string(stored_digest))
#
# Test Cases
#
def default_toc_checksum_validity(filename):
with util.archive_created(filename, "/bin") as path:
_verify_header_checksum(path, "sha1")
def sha1_toc_checksum_validity(filename):
with util.archive_created(filename, "/bin", "--toc-cksum", "sha1") as path:
_verify_header_checksum(path, "sha1")
def sha256_toc_checksum_validity(filename):
with util.archive_created(filename, "/bin", "--toc-cksum", "sha256") as path:
_verify_header_checksum(path, "sha256")
def sha512_toc_checksum_validity(filename):
with util.archive_created(filename, "/bin", "--toc-cksum", "sha512") as path:
_verify_header_checksum(path, "sha512")
def broken_toc_default_checksum(filename):
with util.archive_created(filename, "/bin") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
# Try to extract it
_verify_extraction_failed(filename)
def broken_toc_sha1_checksum(filename):
with util.archive_created(filename, "/bin", "--toc-cksum", "sha1") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
# Try to extract it
_verify_extraction_failed(filename)
def broken_toc_sha256_checksum(filename):
with util.archive_created(filename, "/bin", "--toc-cksum", "sha256") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
# Try to extract it
_verify_extraction_failed(filename)
def broken_toc_sha512_checksum(filename):
with util.archive_created(filename, "/bin", "--toc-cksum", "sha512") as path:
# Mess up the archive
toc_start = _get_header_size(path)
_clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea.
# Try to extract it
_verify_extraction_failed(filename)
def broken_heap_default_checksum(filename):
with util.archive_created(filename, "/bin") as path:
# Mess up the archive
toc_start = _get_header_size(path)
toc_size = _get_toc_size(path)
# Why 32? That's the size of the default sha256 checksum, which is stored before the heap.
_clobber_bytes_at(range(toc_start + toc_size + 32, toc_start + toc_size + 32 + 100), path)
# Try to extract it
_verify_extraction_failed(filename)
def default_checksum_algorithm(filename):
with util.archive_created(filename, "/bin") as path:
header = subprocess.check_output(["xar", "--dump-header", "-f", path])
found = False
for line in header.splitlines():
matchdata = re.match("^Checksum algorithm:\s+(\d+)\s+\\((\w+)\\)$", line)
if not matchdata:
continue
found = True
algorithm = matchdata.groups()[1]
assert algorithm == "SHA1", "unexpected checksum algorithm default: received {a}, expected SHA1".format(a=algorithm)
assert found, "unexpected output from `xar --dump-header`:\n{h}".format(h=header)
# Apparently, xar doesn't currently fail when given an invalid checksum algorithm. Something to fix later.
#
# def invalid_checksum_algorithm(filename):
# try:
# with util.archive_created(filename, "/bin", "--toc-cksum", "invalid-algorithm") as path:
# raise AssertionError("xar succeeded when it should have failed")
# except subprocess.CalledProcessError:
# pass
# It does fail for md5 explicitly, however
def md5_toc_checksum_failure(filename):
try:
with open("/dev/null", "a") as devnull:
with util.archive_created(filename, "/bin", "--toc-cksum", "md5", stderr=devnull) as path:
raise AssertionError("xar succeeded when it should have failed")
except subprocess.CalledProcessError:
pass
def md5_file_checksum_failure(filename):
try:
with open("/dev/null", "a") as devnull:
with util.archive_created(filename, "/bin", "--file-cksum", "md5", stderr=devnull) as path:
raise AssertionError("xar succeeded when it should have failed")
except subprocess.CalledProcessError:
pass
def _verify_checksum_algorithm(filename, algorithm):
additional_args = []
if algorithm:
additional_args = ["--file-cksum", algorithm]
else:
algorithm = "sha1"
with util.archive_created(filename, "/bin", *additional_args) as path:
toc = subprocess.check_output(["xar", "--dump-toc=-", "-f", path])
found = False
for line in toc.splitlines():
if '<unarchived-checksum style="{a}">'.format(a=algorithm) in line or '<archived-checksum style="{a}">'.format(a=algorithm) in line:
break
else:
raise AssertionError("unexpected output from `xar --dump-toc=-`:\n{t}".format(t=toc))
def default_file_checksum_algorithm(filename):
_verify_checksum_algorithm(filename, None)
def sha1_file_checksum_algorithm(filename):
_verify_checksum_algorithm(filename, "sha1")
def sha256_file_checksum_algorithm(filename):
_verify_checksum_algorithm(filename, "sha256")
def sha512_file_checksum_algorithm(filename):
_verify_checksum_algorithm(filename, "sha512")
TEST_CASES = (default_toc_checksum_validity, sha1_toc_checksum_validity, sha256_toc_checksum_validity, sha512_toc_checksum_validity,
broken_toc_default_checksum, broken_toc_sha1_checksum, broken_toc_sha256_checksum, broken_toc_sha512_checksum,
broken_heap_default_checksum, default_checksum_algorithm,
default_file_checksum_algorithm, sha1_file_checksum_algorithm, sha256_file_checksum_algorithm, sha512_file_checksum_algorithm,
md5_toc_checksum_failure, md5_file_checksum_failure,)
if __name__ == "__main__":
for case in TEST_CASES:
try:
case("{f}.xar".format(f=case.func_name))
print("PASSED: {f}".format(f=case.func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
import sys, os
print("FAILED: {f}".format(f=case.func_name))
sys.excepthook(*sys.exc_info())
print("")

74
xar/test/compression.py Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python
from __future__ import print_function
import cStringIO
import os
import os.path
import subprocess
import tempfile
import util
#
# Utility Functions
#
def _check_compression(filename, *args, **kwargs):
with util.archive_created(filename, "/bin", *args, **kwargs) as path:
with util.directory_created("extracted") as directory:
subprocess.check_call(["xar", "-x", "-f", path, "-C", directory])
util.assert_identical_directories("/bin", os.path.join(directory, "bin"))
#
# Test Cases
#
def no_compression(filename):
_check_compression(filename, "--compression=none")
def default_compression(filename):
_check_compression(filename)
def gzip_compression_long(filename):
util.skip_if_no_compression_support("gzip")
_check_compression(filename, "--compression=gzip")
def gzip_compression_short(filename):
util.skip_if_no_compression_support("gzip")
_check_compression(filename, "-z")
def bzip2_compression_long(filename):
util.skip_if_no_compression_support("bzip2")
_check_compression(filename, "--compression=bzip2")
def bzip2_compression_short(filename):
util.skip_if_no_compression_support("bzip2")
_check_compression(filename, "-j")
def lzma_compression_long(filename):
util.skip_if_no_compression_support("lzma")
_check_compression(filename, "--compression=lzma")
def lzma_compression_short(filename):
util.skip_if_no_compression_support("lzma")
_check_compression(filename, "-a")
TEST_CASES = (no_compression, default_compression,
gzip_compression_long, bzip2_compression_long, lzma_compression_long,
gzip_compression_short, bzip2_compression_short, lzma_compression_short)
if __name__ == "__main__":
for case in TEST_CASES:
try:
case("{f}.xar".format(f=case.func_name))
print("PASSED: {f}".format(f=case.func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
import sys, os
print("FAILED: {f}".format(f=case.func_name))
sys.excepthook(*sys.exc_info())
print("")
except util.TestCaseSkipError, e:
print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message))

103
xar/test/data.py Normal file
View File

@ -0,0 +1,103 @@
#!/usr/bin/env python
from __future__ import print_function
import contextlib
import os
import os.path
import subprocess
import util
#
# Utility Functions
#
@contextlib.contextmanager
def _data_test(filename, *args, **kwargs):
with util.directory_created("data_scratch") as directory:
yield directory
# Files are now created
with util.archive_created("data.xar", "./data_scratch", *args, **kwargs) as path:
_process_toc(path)
with util.directory_created("data_extracted") as extracted:
subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted])
util.assert_identical_directories(directory, os.path.join(extracted, "data_scratch"))
def _process_toc(archive_path):
subprocess.check_call(["xar", "-f", archive_path, "--dump-toc=data_toc.xml"])
try:
result = subprocess.check_output(["xsltproc", "-o", "-", os.path.realpath(os.path.join(__file__, "..", "data.xsl")), "data_toc.xml"])
assert result == "", "expected no data offset, but instead found:{o}".format(o=result)
finally:
os.unlink("data_toc.xml")
def _zero_length(filename, *args, **kwargs):
with _data_test(filename, *args, **kwargs) as directory:
util.touch(os.path.join(directory, "empty"))
#
# Test Cases
#
def zero_length_default_compression(filename):
_zero_length(filename)
def zero_length_no_compression(filename):
_zero_length(filename, "--compression=none")
def zero_length_gzip_compression(filename):
util.skip_if_no_compression_support("gzip")
_zero_length(filename, "--compression=gzip")
def zero_length_bzip2_compression(filename):
util.skip_if_no_compression_support("bzip2")
_zero_length(filename, "--compression=bzip2")
def zero_length_lzma_compression(filename):
util.skip_if_no_compression_support("lzma")
_zero_length(filename, "--compression=lzma")
def _mixed_length(filename, *args, **kwargs):
with _data_test(filename, *args, **kwargs) as directory:
util.touch(os.path.join(directory, "mixed_empty"))
with open(os.path.join(directory, "mixed_small"), "w") as f:
f.write("1234")
def mixed_length_no_compression(filename):
_mixed_length(filename, "--compression=none")
def mixed_length_default_compression(filename):
_mixed_length(filename)
def mixed_length_gzip_compression(filename):
util.skip_if_no_compression_support("gzip")
_mixed_length(filename, "--compression=gzip")
def mixed_length_bzip2_compression(filename):
util.skip_if_no_compression_support("bzip2")
_mixed_length(filename, "--compression=bzip2")
def mixed_length_lzma_compression(filename):
util.skip_if_no_compression_support("lzma")
_mixed_length(filename, "--compression=lzma")
TEST_CASES = (zero_length_default_compression, zero_length_no_compression,
zero_length_gzip_compression, zero_length_bzip2_compression, zero_length_lzma_compression,
mixed_length_no_compression, mixed_length_default_compression,
mixed_length_gzip_compression, mixed_length_bzip2_compression, mixed_length_lzma_compression)
if __name__ == "__main__":
for case in TEST_CASES:
try:
case("{f}.xar".format(f=case.func_name))
print("PASSED: {f}".format(f=case.func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
import sys, os
print("FAILED: {f}".format(f=case.func_name))
sys.excepthook(*sys.exc_info())
print("")
except util.TestCaseSkipError, e:
print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message))

8
xar/test/data.xsl Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="xar/toc/file/data/offset"/>
</xsl:template>
</xsl:stylesheet>

69
xar/test/hardlink.py Normal file
View File

@ -0,0 +1,69 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import os.path
import subprocess
import util
#
# Utility Functions
#
def _assert_same_inodes(path1, path2):
assert os.path.exists(path1), "missing hard-linked-file {p}".format(p=path1)
assert os.path.exists(path1), "missing hard-linked-file {p}".format(p=path2)
stat1 = os.lstat(path1)
stat2 = os.lstat(path2)
assert stat1.st_ino == stat2.st_ino, "inodes do not match for hard-linked files \"{p1}\" and \"{p2}\"".format(p1=path1, p2=path2)
#
# Test Cases
#
def hard_link_in_directory(filename):
with util.directory_created("hardlink_scratch") as directory:
util.touch(os.path.join(directory, "a"))
os.link(os.path.join(directory, "a"), os.path.join(directory, "b"))
with util.archive_created("hardlink_archive.xar", "hardlink_scratch") as path:
with util.directory_created("hardlink_extracted") as extracted:
subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path])
_assert_same_inodes(os.path.join(extracted, "hardlink_scratch", "a"), os.path.join(extracted, "hardlink_scratch", "b"))
def hard_link_in_cwd(filename):
with util.directory_created("hardlink_scratch") as directory:
with util.chdir(directory):
util.touch("a")
os.link("a", "b")
with util.archive_created(os.path.join("..", "hardlink_archive.xar"), ".") as path:
with util.directory_created(os.path.join("..", "hardlink_extracted")) as extracted:
subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path])
_assert_same_inodes(os.path.join(extracted, "a"), os.path.join(extracted, "b"))
def hard_link_identical_files(filename):
with util.directory_created("hardlink_scratch") as directory:
with open(os.path.join(directory, "a"), "w") as f:
f.write("1234samecontent")
with open(os.path.join(directory, "b"), "w") as f:
f.write("1234samecontent")
with util.archive_created("hardlink_archive.xar", "hardlink_scratch", "--link-same") as path:
with util.directory_created("hardlink_extracted") as extracted:
subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path])
_assert_same_inodes(os.path.join(extracted, "hardlink_scratch", "a"), os.path.join(extracted, "hardlink_scratch", "b"))
TEST_CASES = (hard_link_in_directory, hard_link_in_cwd, hard_link_identical_files)
if __name__ == "__main__":
for case in TEST_CASES:
try:
case("{f}.xar".format(f=case.func_name))
print("PASSED: {f}".format(f=case.func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
import sys, os
print("FAILED: {f}".format(f=case.func_name))
sys.excepthook(*sys.exc_info())
print("")

78
xar/test/heap.py Normal file
View File

@ -0,0 +1,78 @@
#!/usr/bin/env python
from __future__ import print_function
import glob
import os
import os.path
import re
import shutil
import subprocess
import util
#
# Utility Functions
#
def _file_offsets_for_archive(path, xsl_path):
subprocess.check_call(["xar", "--dump-toc=heap_toc.xml", "-f", path])
try:
offsets = subprocess.check_output(["xsltproc", xsl_path, "heap_toc.xml"])
matches = [re.match("^(.+)\s([^\s]+)$", offset) for offset in offsets.splitlines()]
offsets = [(match.groups()[0], int(match.groups()[1])) for match in matches]
return offsets
finally:
os.unlink("heap_toc.xml")
#
# Test Cases
#
XSL_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "heap1.xsl")
def normal_heap(filename):
with util.directory_created("scratch") as directory:
shutil.copy("/bin/ls", os.path.join(directory, "ls"))
shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo"))
with util.chdir(directory):
with util.archive_created(os.path.join("..", "heap.xar"), ".") as path:
# Verify file offsets are as we expect
offsets = _file_offsets_for_archive(path, XSL_PATH)
(f1, o1) = offsets[0]
(f2, o2) = offsets[1]
assert o1 < o2, "offset for first file \"{f1}\" ({o1}) greater than or equal to offset for last file \"{f2}\" ({o2})".format(f1=f1, o1=o1, f2=f2, o2=o2)
# Make sure extraction goes all right
with util.directory_created("extracted") as extracted:
subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted])
def coalesce_heap(filename):
with util.directory_created("scratch") as directory:
shutil.copy("/bin/ls", os.path.join(directory, "ls"))
shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo"))
with util.chdir(directory):
with util.archive_created(os.path.join("..", "heap.xar"), ".", "--coalesce-heap") as path:
# Verify file offsets are as we expect
offsets = _file_offsets_for_archive(path, XSL_PATH)
(f1, o1) = offsets[0]
(f2, o2) = offsets[1]
# Make sure extraction goes all right
with util.directory_created("extracted") as extracted:
subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted])
TEST_CASES = (normal_heap, coalesce_heap)
if __name__ == "__main__":
for case in TEST_CASES:
try:
case("{f}.xar".format(f=case.func_name))
print("PASSED: {f}".format(f=case.func_name))
except (AssertionError, IOError, subprocess.CalledProcessError):
import sys, os
print("FAILED: {f}".format(f=case.func_name))
sys.excepthook(*sys.exc_info())
print("")

Some files were not shown because too many files have changed in this diff Show More