[MKISOFS]
authorColin Finck <colin@reactos.org>
Wed, 11 Jan 2017 11:56:36 +0000 (11:56 +0000)
committerColin Finck <colin@reactos.org>
Wed, 11 Jan 2017 11:56:36 +0000 (11:56 +0000)
Update mkisofs to schily-2016-12-14 giving us the following features:
- Support for -duplicates-once to store duplicate files in the tree only once in the filesystem (see also CORE-9266)
  I've enabled this for the hybridcd target where it actually saves us 25 MB.
- Proper System-ID "Win32/MinGW" and "Win32/MSVC" under Windows hosts depending on the compiler

CORE-12578

svn path=/trunk/; revision=73520

22 files changed:
reactos/boot/CMakeLists.txt
reactos/sdk/tools/mkisofs/CMakeLists.txt
reactos/sdk/tools/mkisofs/reactos/xconfig.h
reactos/sdk/tools/mkisofs/schilytools/include/schily/assert.h [new file with mode: 0644]
reactos/sdk/tools/mkisofs/schilytools/include/schily/schily.h
reactos/sdk/tools/mkisofs/schilytools/include/schily/sha3.h [new file with mode: 0644]
reactos/sdk/tools/mkisofs/schilytools/include/schily/stdio.h
reactos/sdk/tools/mkisofs/schilytools/libmdigest/byte_order.h [new file with mode: 0644]
reactos/sdk/tools/mkisofs/schilytools/libmdigest/sha3.c [new file with mode: 0644]
reactos/sdk/tools/mkisofs/schilytools/libschily/stdio/fgetline.c
reactos/sdk/tools/mkisofs/schilytools/libschily/stdio/schilyio.h
reactos/sdk/tools/mkisofs/schilytools/mkisofs/boot.c
reactos/sdk/tools/mkisofs/schilytools/mkisofs/defaults.h
reactos/sdk/tools/mkisofs/schilytools/mkisofs/hash.c
reactos/sdk/tools/mkisofs/schilytools/mkisofs/inode.c
reactos/sdk/tools/mkisofs/schilytools/mkisofs/match.c
reactos/sdk/tools/mkisofs/schilytools/mkisofs/match.h
reactos/sdk/tools/mkisofs/schilytools/mkisofs/mkisofs.c
reactos/sdk/tools/mkisofs/schilytools/mkisofs/mkisofs.h
reactos/sdk/tools/mkisofs/schilytools/mkisofs/scsi.h
reactos/sdk/tools/mkisofs/schilytools/mkisofs/tree.c
reactos/sdk/tools/mkisofs/schilytools/mkisofs/write.c

index 116bf70..56d16fa 100644 (file)
@@ -221,7 +221,7 @@ if(USE_MKISOFS)
             -publisher ${ISO_MANUFACTURER} -preparer ${ISO_MANUFACTURER} -volid ${ISO_VOLNAME} -volset ${ISO_VOLNAME}
             -eltorito-boot loader/isoboot.bin -no-emul-boot -boot-load-size 4 -eltorito-alt-boot -eltorito-platform efi -eltorito-boot loader/efisys.bin -no-emul-boot -hide boot.catalog
             -sort ${CMAKE_CURRENT_BINARY_DIR}/bootfiles.sort
-            -no-cache-inodes -graft-points -path-list ${CMAKE_CURRENT_BINARY_DIR}/hybridcd.lst
+            -duplicates-once -no-cache-inodes -graft-points -path-list ${CMAKE_CURRENT_BINARY_DIR}/hybridcd.lst
         DEPENDS native-mkisofs bootcd livecd
         VERBATIM)
 else()
index 5b0db18..37d85bc 100644 (file)
@@ -1,5 +1,6 @@
 
 add_definitions(
+    -DDUPLICATES_ONCE
     -DINS_BASE="\\".\\""
     -DSCHILY_BUILD
     -DSORTING)
@@ -15,6 +16,9 @@ include_directories(
 #
 # Reference: http://opensource.stackexchange.com/questions/2094
 
+add_library(libmdigest
+    schilytools/libmdigest/sha3.c)
+
 add_library(libschily
     schilytools/libschily/stdio/cvmod.c
     schilytools/libschily/stdio/dat.c
@@ -74,7 +78,7 @@ add_host_tool(mkisofs
     schilytools/mkisofs/stream.c
     schilytools/mkisofs/tree.c
     schilytools/mkisofs/write.c)
-target_link_libraries(mkisofs libschily libsiconv)
+target_link_libraries(mkisofs libmdigest libschily libsiconv)
 
 if(MSVC)
     # mkisofs uses K&R-style function definitions to support very old compilers.
index e250382..3fdd3a8 100644 (file)
@@ -18,6 +18,7 @@
  * Header Files
  */
 #define PROTOTYPES 1
+#define HAVE_ASSERT_H 1
 #define HAVE_STDARG_H 1
 #define HAVE_STDLIB_H 1
 #define HAVE_STDDEF_H 1
diff --git a/reactos/sdk/tools/mkisofs/schilytools/include/schily/assert.h b/reactos/sdk/tools/mkisofs/schilytools/include/schily/assert.h
new file mode 100644 (file)
index 0000000..5500ec9
--- /dev/null
@@ -0,0 +1,47 @@
+/* @(#)assert.h        1.1 09/08/07 Copyright 2009 J. Schilling */
+/*
+ *     Abstraction code for assert.h
+ *
+ *     Copyright (c) 2009 J. Schilling
+ */
+/*
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * See the file CDDL.Schily.txt in this distribution for details.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file CDDL.Schily.txt from this distribution.
+ */
+
+#ifndef        _SCHILY_ASSERT_H
+#define        _SCHILY_ASSERT_H
+
+#ifndef _SCHILY_MCONFIG_H
+#include <schily/mconfig.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+#ifndef        _INCL_ASSERT_H
+#define        _INCL_ASSERT_H
+#include <assert.h>
+#endif
+#else  /* !HAVE_ASSERT_H */
+
+#undef assert
+
+#ifdef NDEBUG
+#define        assert(ignore)  ((void) 0)
+#else
+#if    defined(__STDC__)
+#define        assert(exp) (void)((exp) || (__assert(#exp, __FILE__, __LINE__), 0))
+#else
+#define        assert(exp) (void)((exp) || (__assert("exp", __FILE__, __LINE__), 0))
+#endif
+#endif
+
+#endif /* !HAVE_ASSERT_H */
+
+#endif /* _SCHILY_ASSERT_H */
index 4aca72d..74a88e8 100644 (file)
@@ -1,4 +1,4 @@
-/* @(#)schily.h        1.120 16/09/28 Copyright 1985-2016 J. Schilling */
+/* @(#)schily.h        1.121 16/11/04 Copyright 1985-2016 J. Schilling */
 /*
  *     Definitions for libschily
  *
@@ -416,6 +416,7 @@ extern      int     printf __PR((const char *, ...)) __printflike__(1, 2);
 #endif
 #ifdef FOUND_SIZE_T
 extern char    *movebytes __PR((const void *, void *, ssize_t));
+extern char    *movecbytes __PR((const void *, void *, int, size_t));
 #endif
 
 extern void    save_args __PR((int, char **));
diff --git a/reactos/sdk/tools/mkisofs/schilytools/include/schily/sha3.h b/reactos/sdk/tools/mkisofs/schilytools/include/schily/sha3.h
new file mode 100644 (file)
index 0000000..5ee3e05
--- /dev/null
@@ -0,0 +1,90 @@
+/* @(#)sha3.h  1.6 16/10/26 2015-2016 J. Schilling */
+/* sha3.h */
+/*
+ * SHA3 hash code taken from
+ * https://github.com/rhash/RHash/tree/master/librhash
+ *
+ * Portions Copyright (c) 2015-2016 J. Schilling
+ */
+#ifndef        _SCHILY_SHA3_H
+#define        _SCHILY_SHA3_H
+
+#ifndef        _SCHILY_MCONFIG_H
+#include <schily/mconfig.h>
+#endif
+#include <schily/types.h>
+#include <schily/stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_LONGLONG
+
+#define        sha3_224_hash_size      28
+#define        sha3_256_hash_size      32
+#define        sha3_384_hash_size      48
+#define        sha3_512_hash_size      64
+#define        sha3_max_permutation_size 25
+#define        sha3_max_rate_in_qwords 24
+
+#define        SHA3_224_DIGEST_LENGTH          sha3_224_hash_size
+#define        SHA3_224_DIGEST_STRING_LENGTH   (SHA3_224_DIGEST_LENGTH * 2 + 1)
+#define        SHA3_256_DIGEST_LENGTH          sha3_256_hash_size
+#define        SHA3_256_DIGEST_STRING_LENGTH   (SHA3_256_DIGEST_LENGTH * 2 + 1)
+#define        SHA3_384_DIGEST_LENGTH          sha3_384_hash_size
+#define        SHA3_384_DIGEST_STRING_LENGTH   (SHA3_384_DIGEST_LENGTH * 2 + 1)
+#define        SHA3_512_DIGEST_LENGTH          sha3_512_hash_size
+#define        SHA3_512_DIGEST_STRING_LENGTH   (SHA3_512_DIGEST_LENGTH * 2 + 1)
+
+/*
+ * SHA3 Algorithm context.
+ */
+typedef struct sha3_ctx
+{
+       /* 1600 bits algorithm hashing state */
+       UInt64_t hash[sha3_max_permutation_size];
+       /* 1536-bit buffer for leftovers */
+       UInt64_t message[sha3_max_rate_in_qwords];
+       /* count of bytes in the message[] buffer */
+       unsigned rest;
+       /* size of a message block processed at once */
+       unsigned block_size;
+} sha3_ctx, SHA3_CTX;
+
+/* methods for calculating the hash function */
+
+void rhash_sha3_224_init __PR((sha3_ctx *ctx));
+void rhash_sha3_256_init __PR((sha3_ctx *ctx));
+void rhash_sha3_384_init __PR((sha3_ctx *ctx));
+void rhash_sha3_512_init __PR((sha3_ctx *ctx));
+void rhash_sha3_update __PR((sha3_ctx *ctx,
+                               const unsigned char *msg,
+                               size_t size));
+void rhash_sha3_final __PR((sha3_ctx *ctx, unsigned char *result));
+
+void SHA3_224_Init     __PR((SHA3_CTX *ctx));
+void SHA3_256_Init     __PR((SHA3_CTX *ctx));
+void SHA3_384_Init     __PR((SHA3_CTX *ctx));
+void SHA3_512_Init     __PR((SHA3_CTX *ctx));
+void SHA3_Update       __PR((SHA3_CTX *ctx,
+                               const unsigned char *msg,
+                               size_t size));
+void SHA3_Final                __PR((unsigned char *result, SHA3_CTX *ctx));
+
+#ifdef USE_KECCAK
+#define        rhash_keccak_224_init   rhash_sha3_224_init
+#define        rhash_keccak_256_init   rhash_sha3_256_init
+#define        rhash_keccak_384_init   rhash_sha3_384_init
+#define        rhash_keccak_512_init   rhash_sha3_512_init
+#define        rhash_keccak_update     rhash_sha3_update
+void rhash_keccak_final        __PR((sha3_ctx *ctx, unsigned char *result));
+#endif
+
+#endif /* HAVE_LONGLONG */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCHILY_SHA3_H */
index cb1b6a6..012f7f4 100644 (file)
@@ -1,4 +1,4 @@
-/* @(#)stdio.h 1.12 16/09/11 Copyright 2009-2016 J. Schilling */
+/* @(#)stdio.h 1.14 16/11/06 Copyright 2009-2016 J. Schilling */
 /*
  *     Abstraction from stdio.h
  *
@@ -91,6 +91,9 @@ extern "C" {
  * If you believe you can do this on onther platforms, send a note.
  */
 #if    defined(__SVR4) && defined(__sun) && defined(_LP64)
+#ifndef        _SCHILY_TYPES_H
+#include <schily/types.h>      /* Needed for ssize_t */
+#endif
 
 /*
  * This is how the 64 bit FILE * begins on Solaris.
@@ -102,6 +105,12 @@ struct SCHILY__FILE_TAG {
        ssize_t         _cnt;   /* number of available characters in buffer */
 };
 
+#define        __getc_unlocked(p)      (--(p)->_cnt < 0 \
+                                       ? __filbuf((FILE *)p) \
+                                       : (int)*(p)->_ptr++)
+
+#define        getc_unlocked(p)        __getc_unlocked((struct SCHILY__FILE_TAG *)p)
+
 #define        __putc_unlocked(x, p)   (--(p)->_cnt < 0 \
                                        ? __flsbuf((x), (FILE *)(p)) \
                                        : (int)(*(p)->_ptr++ = \
@@ -109,9 +118,12 @@ struct SCHILY__FILE_TAG {
 
 #define        putc_unlocked(x, p)     __putc_unlocked(x, (struct SCHILY__FILE_TAG *)p)
 
+extern int     __filbuf __PR((FILE *));
 extern int     __flsbuf __PR((int, FILE *));
 
-#endif /* defined(__SVR4) && defined(__sun) && defined(_LP64) */
+#else  /* !defined(__SVR4) && defined(__sun) && defined(_LP64) */
+#undef FAST_GETC_PUTC
+#endif /* !defined(__SVR4) && defined(__sun) && defined(_LP64) */
 #endif /* FAST_GETC_PUTC */
 
 #ifdef __cplusplus
diff --git a/reactos/sdk/tools/mkisofs/schilytools/libmdigest/byte_order.h b/reactos/sdk/tools/mkisofs/schilytools/libmdigest/byte_order.h
new file mode 100644 (file)
index 0000000..66c76b5
--- /dev/null
@@ -0,0 +1,212 @@
+/* @(#)byte_order.h    1.3 15/11/22 2015 J. Schilling */
+/* byte_order.h */
+/*
+ * SHA3 hash code taken from
+ * https://github.com/rhash/RHash/tree/master/librhash
+ *
+ * Portions Copyright (c) 2015 J. Schilling
+ */
+#ifndef BYTE_ORDER_H
+#define        BYTE_ORDER_H
+#include <schily/stdlib.h>
+#include <schily/types.h>
+#include <schily/stdint.h>
+
+#ifdef IN_RHASH
+#include "config.h"
+#endif
+
+#ifdef __GLIBC__
+# include <endian.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_C_BIGENDIAN
+
+/*
+ * Use the Schily autoconf results.
+ */
+#ifdef WORDS_BIGENDIAN
+#define        CPU_BIG_ENDIAN
+#else
+#define        CPU_LITTLE_ENDIAN
+#endif
+
+#else  /* HAVE_C_BIGENDIAN */
+
+/* if x86 compatible cpu */
+#if defined(i386) || defined(__i386__) || defined(__i486__) || \
+       defined(__i586__) || defined(__i686__) || defined(__pentium__) || \
+       defined(__pentiumpro__) || defined(__pentium4__) || \
+       defined(__nocona__) || defined(prescott) || defined(__core2__) || \
+       defined(__k6__) || defined(__k8__) || defined(__athlon__) || \
+       defined(__amd64) || defined(__amd64__) || \
+       defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \
+       defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64)
+/* detect if x86-64 instruction set is supported */
+# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
+       defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+#define        CPU_X64
+#else
+#define        CPU_IA32
+#endif
+#endif
+
+
+/* detect CPU endianness */
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+               __BYTE_ORDER == __LITTLE_ENDIAN) || \
+       defined(CPU_IA32) || defined(CPU_X64) || \
+       defined(__ia64) || defined(__ia64__) || defined(__alpha__) || defined(_M_ALPHA) || \
+       defined(vax) || defined(MIPSEL) || defined(_ARM_)
+#define        CPU_LITTLE_ENDIAN
+#define        IS_BIG_ENDIAN 0
+#define        IS_LITTLE_ENDIAN 1
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+               __BYTE_ORDER == __BIG_ENDIAN) || \
+       defined(__sparc) || defined(__sparc__) || defined(sparc) || \
+       defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \
+       defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \
+       defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \
+       defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \
+       defined(__s390__) || defined(__s390x__) || defined(sel)
+#define        CPU_BIG_ENDIAN
+#define        IS_BIG_ENDIAN 1
+#define        IS_LITTLE_ENDIAN 0
+#else
+       error "Can't detect CPU architechture"
+#endif
+
+#endif /* HAVE_C_BIGENDIAN */
+
+#define        IS_ALIGNED_32(p) (0 == (3 & ((const char *)(p) - (const char *)0)))
+#define        IS_ALIGNED_64(p) (0 == (7 & ((const char *)(p) - (const char *)0)))
+
+#if defined(_MSC_VER)
+#define        ALIGN_ATTR(n) __declspec(align(n))
+#elif defined(__GNUC__)
+#define        ALIGN_ATTR(n) __attribute__((aligned(n)))
+#else
+#define        ALIGN_ATTR(n) /* nothing */
+#endif
+
+
+#ifdef PROTOTYPES
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define        I64(x) x##ui64
+#define        UI64(x) x##ui64
+#else
+#define        I64(x) x##LL
+#define        UI64(x) x##ULL
+#endif
+#else  /* !PROTOTYPES */
+#ifdef __hpux
+#define        I64(x) x/**/LL
+#define        UI64(x) x/**/ULL
+#else
+#define        I64(x) ((long long)(x))
+#define        UI64(x) ((unsigned long long)(x))
+#endif
+#endif /* !PROTOTYPES */
+
+/* convert a hash flag to index */
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */
+#define        rhash_ctz(x) __builtin_ctz(x)
+#else
+unsigned rhash_ctz __PR((unsigned)); /* define as function */
+#endif
+
+void rhash_swap_copy_str_to_u32        __PR((void* to, int idx, const void* from, size_t length));
+void rhash_swap_copy_str_to_u64 __PR((void* to, int idx, const void* from, size_t length));
+void rhash_swap_copy_u64_to_str __PR((void* to, const void* from, size_t length));
+void rhash_u32_mem_swap __PR((unsigned *p, int length_in_u32));
+
+/* define bswap_32 */
+#if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__)
+/* for intel x86 CPU */
+static inline UInt32_t bswap_32(UInt32_t x) {
+       __asm("bswap\t%0" : "=r" (x) : "0" (x));
+       return (x);
+}
+#elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
+/* for GCC >= 4.3 */
+# define bswap_32(x) __builtin_bswap32(x)
+#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
+# define bswap_32(x) _byteswap_ulong((unsigned long)x)
+#elif !defined(__STRICT_ANSI__)
+/* general bswap_32 definition */
+static inline UInt32_t bswap_32 __PR((UInt32_t x));
+static inline UInt32_t bswap_32(x)
+       UInt32_t        x;
+{
+       x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF);
+       return ((x >> 16) | (x << 16));
+}
+#else
+#define        bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
+       (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
+#endif /* bswap_32 */
+
+#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
+# define bswap_64(x) __builtin_bswap64(x)
+#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
+# define bswap_64(x) _byteswap_uint64((__int64)x)
+#elif !defined(__STRICT_ANSI__)
+static inline UInt64_t bswap_64 __PR((UInt64_t x));
+static inline UInt64_t bswap_64(x)
+       UInt64_t        x;
+{
+       union {
+               UInt64_t ll;
+               UInt32_t l[2];
+       } w, r;
+       w.ll = x;
+       r.l[0] = bswap_32(w.l[1]);
+       r.l[1] = bswap_32(w.l[0]);
+       return (r.ll);
+}
+#else
+       error "bswap_64 unsupported"
+#endif
+
+#ifdef CPU_BIG_ENDIAN
+# define be2me_32(x) (x)
+# define be2me_64(x) (x)
+# define le2me_32(x) bswap_32(x)
+# define le2me_64(x) bswap_64(x)
+
+# define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
+# define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
+# define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
+# define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
+# define me64_to_be_str(to, from, length) memcpy((to), (from), (length))
+# define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
+
+#else /* CPU_BIG_ENDIAN */
+# define be2me_32(x) bswap_32(x)
+# define be2me_64(x) bswap_64(x)
+# define le2me_32(x) (x)
+# define le2me_64(x) (x)
+
+# define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
+# define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
+# define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
+# define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
+# define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
+# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
+#endif /* CPU_BIG_ENDIAN */
+
+/* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */
+#define        ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
+#define        ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
+#define        ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
+#define        ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* BYTE_ORDER_H */
diff --git a/reactos/sdk/tools/mkisofs/schilytools/libmdigest/sha3.c b/reactos/sdk/tools/mkisofs/schilytools/libmdigest/sha3.c
new file mode 100644 (file)
index 0000000..83ec9ae
--- /dev/null
@@ -0,0 +1,507 @@
+/* @(#)sha3.c  1.4 15/12/27 2015 J. Schilling */
+#include <schily/mconfig.h>
+#ifndef lint
+static UConst char sccsid[] =
+       "@(#)sha3.c     1.4 15/12/27 2015 J. Schilling";
+#endif
+/*
+ * SHA3 hash code taken from
+ * https://github.com/rhash/RHash/tree/master/librhash
+ *
+ * Portions Copyright (c) 2015 J. Schilling
+ */
+
+/*
+ * sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
+ * based on the
+ * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
+ * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
+ *
+ * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
+ *
+ * Permission is hereby granted,  free of charge,  to any person  obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction,  including without limitation
+ * the rights to  use, copy, modify,  merge, publish, distribute, sublicense,
+ * and/or sell copies  of  the Software,  and to permit  persons  to whom the
+ * Software is furnished to do so.
+ *
+ * This program  is  distributed  in  the  hope  that it will be useful,  but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  Use this program  at  your own risk!
+ */
+
+#include <schily/assert.h>
+#include <schily/string.h>
+#include "byte_order.h"
+#include <schily/sha3.h>
+
+#ifdef HAVE_LONGLONG
+
+#if !defined(HAVE_MEMCPY) || !defined(HAVE_MEMSET)
+#include <schily/schily.h>
+#endif
+#if !defined(HAVE_MEMCPY) && !defined(memcpy)
+#define        memcpy(s1, s2, n)       movebytes(s2, s1, n)
+#endif
+#if !defined(HAVE_MEMSET) && !defined(memset)
+#define        memset(s, c, n)         fillbytes(s, n, c)
+#endif
+
+static void rhash_keccak_init  __PR((sha3_ctx *ctx, unsigned bits));
+static void keccak_theta       __PR((UInt64_t *A));
+static void keccak_pi          __PR((UInt64_t *A));
+static void keccak_chi         __PR((UInt64_t *A));
+static void rhash_sha3_permutation __PR((UInt64_t *state));
+static void rhash_sha3_process_block __PR((UInt64_t hash[25],
+                                       const UInt64_t *block,
+                                       size_t block_size));
+
+/*
+ * The Cygwin compile environment incorrectly implements #pragma weak.
+ * The weak symbols are only defined as local symbols making it impossible
+ * to use them from outside the scope of this source file.
+ * A platform that allows linking with global symbols has HAVE_LINK_WEAK
+ * defined.
+ */
+#if defined(HAVE_PRAGMA_WEAK) && defined(HAVE_LINK_WEAK)
+#pragma        weak SHA3_224_Init = rhash_sha3_224_init
+#pragma        weak SHA3_256_Init = rhash_sha3_256_init
+#pragma        weak SHA3_384_Init = rhash_sha3_384_init
+#pragma        weak SHA3_512_Init = rhash_sha3_512_init
+#pragma        weak SHA3_Update = rhash_sha3_update
+#else
+
+void SHA3_224_Init     __PR((SHA3_CTX *ctx));
+void SHA3_256_Init     __PR((SHA3_CTX *ctx));
+void SHA3_384_Init     __PR((SHA3_CTX *ctx));
+void SHA3_512_Init     __PR((SHA3_CTX *ctx));
+void SHA3_Update       __PR((SHA3_CTX *ctx,
+                               const unsigned char *msg,
+                               size_t size));
+
+void
+SHA3_224_Init(ctx)
+       SHA3_CTX        *ctx;
+{
+       rhash_sha3_224_init(ctx);
+}
+
+void
+SHA3_256_Init(ctx)
+       SHA3_CTX        *ctx;
+{
+       rhash_sha3_256_init(ctx);
+}
+
+void
+SHA3_384_Init(ctx)
+       SHA3_CTX        *ctx;
+{
+       rhash_sha3_384_init(ctx);
+}
+
+void
+SHA3_512_Init(ctx)
+       SHA3_CTX        *ctx;
+{
+       rhash_sha3_512_init(ctx);
+}
+
+void
+SHA3_Update(ctx, msg, size)
+       SHA3_CTX        *ctx;
+       const unsigned char *msg;
+       size_t          size;
+{
+       rhash_sha3_update(ctx, msg, size);
+}
+#endif /* defined(HAVE_PRAGMA_WEAK) && defined(HAVE_LINK_WEAK) */
+
+/* constants */
+#define        NumberOfRounds  24
+
+/* SHA3 (Keccak) constants for 24 rounds */
+static UInt64_t keccak_round_constants[NumberOfRounds] = {
+       UI64(0x0000000000000001), UI64(0x0000000000008082),
+       UI64(0x800000000000808A), UI64(0x8000000080008000),
+       UI64(0x000000000000808B), UI64(0x0000000080000001),
+       UI64(0x8000000080008081), UI64(0x8000000000008009),
+       UI64(0x000000000000008A), UI64(0x0000000000000088),
+       UI64(0x0000000080008009), UI64(0x000000008000000A),
+       UI64(0x000000008000808B), UI64(0x800000000000008B),
+       UI64(0x8000000000008089), UI64(0x8000000000008003),
+       UI64(0x8000000000008002), UI64(0x8000000000000080),
+       UI64(0x000000000000800A), UI64(0x800000008000000A),
+       UI64(0x8000000080008081), UI64(0x8000000000008080),
+       UI64(0x0000000080000001), UI64(0x8000000080008008)
+};
+
+/* Initializing a sha3 context for given number of output bits */
+static void
+rhash_keccak_init(ctx, bits)
+       sha3_ctx        *ctx;
+       unsigned        bits;
+{
+       /* NB: The Keccak capacity parameter = bits * 2 */
+       unsigned rate = 1600 - bits * 2;
+
+       memset(ctx, 0, sizeof (sha3_ctx));
+       ctx->block_size = rate / 8;
+       assert(rate <= 1600 && (rate % 64) == 0);
+}
+
+/*
+ * Initialize context before calculating hash.
+ *
+ * @param ctx context to initialize
+ */
+void
+rhash_sha3_224_init(ctx)
+       sha3_ctx        *ctx;
+{
+       rhash_keccak_init(ctx, 224);
+}
+
+/*
+ * Initialize context before calculating hash.
+ *
+ * @param ctx context to initialize
+ */
+void
+rhash_sha3_256_init(ctx)
+       sha3_ctx        *ctx;
+{
+       rhash_keccak_init(ctx, 256);
+}
+
+/*
+ * Initialize context before calculating hash.
+ *
+ * @param ctx context to initialize
+ */
+void
+rhash_sha3_384_init(ctx)
+       sha3_ctx        *ctx;
+{
+       rhash_keccak_init(ctx, 384);
+}
+
+/*
+ * Initialize context before calculating hash.
+ *
+ * @param ctx context to initialize
+ */
+void
+rhash_sha3_512_init(ctx)
+       sha3_ctx        *ctx;
+{
+       rhash_keccak_init(ctx, 512);
+}
+
+/* Keccak theta() transformation */
+static void
+keccak_theta(A)
+       UInt64_t        *A;
+{
+       unsigned int x;
+       UInt64_t C[5], D[5];
+
+       for (x = 0; x < 5; x++) {
+               C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
+       }
+       D[0] = ROTL64(C[1], 1) ^ C[4];
+       D[1] = ROTL64(C[2], 1) ^ C[0];
+       D[2] = ROTL64(C[3], 1) ^ C[1];
+       D[3] = ROTL64(C[4], 1) ^ C[2];
+       D[4] = ROTL64(C[0], 1) ^ C[3];
+
+       for (x = 0; x < 5; x++) {
+               A[x]      ^= D[x];
+               A[x + 5]  ^= D[x];
+               A[x + 10] ^= D[x];
+               A[x + 15] ^= D[x];
+               A[x + 20] ^= D[x];
+       }
+}
+
+/* Keccak pi() transformation */
+static void
+keccak_pi(A)
+       UInt64_t        *A;
+{
+       UInt64_t A1;
+       A1 = A[1];
+       A[ 1] = A[ 6];
+       A[ 6] = A[ 9];
+       A[ 9] = A[22];
+       A[22] = A[14];
+       A[14] = A[20];
+       A[20] = A[ 2];
+       A[ 2] = A[12];
+       A[12] = A[13];
+       A[13] = A[19];
+       A[19] = A[23];
+       A[23] = A[15];
+       A[15] = A[ 4];
+       A[ 4] = A[24];
+       A[24] = A[21];
+       A[21] = A[ 8];
+       A[ 8] = A[16];
+       A[16] = A[ 5];
+       A[ 5] = A[ 3];
+       A[ 3] = A[18];
+       A[18] = A[17];
+       A[17] = A[11];
+       A[11] = A[ 7];
+       A[ 7] = A[10];
+       A[10] = A1;
+       /* note: A[ 0] is left as is */
+}
+
+/* Keccak chi() transformation */
+static void
+keccak_chi(A)
+       UInt64_t        *A;
+{
+       int i;
+       for (i = 0; i < 25; i += 5) {
+               UInt64_t A0 = A[0 + i], A1 = A[1 + i];
+               A[0 + i] ^= ~A1 & A[2 + i];
+               A[1 + i] ^= ~A[2 + i] & A[3 + i];
+               A[2 + i] ^= ~A[3 + i] & A[4 + i];
+               A[3 + i] ^= ~A[4 + i] & A0;
+               A[4 + i] ^= ~A0 & A1;
+       }
+}
+
+static void
+rhash_sha3_permutation(state)
+       UInt64_t        *state;
+{
+       int round;
+       for (round = 0; round < NumberOfRounds; round++)
+       {
+               keccak_theta(state);
+
+               /* apply Keccak rho() transformation */
+               state[ 1] = ROTL64(state[ 1],  1);
+               state[ 2] = ROTL64(state[ 2], 62);
+               state[ 3] = ROTL64(state[ 3], 28);
+               state[ 4] = ROTL64(state[ 4], 27);
+               state[ 5] = ROTL64(state[ 5], 36);
+               state[ 6] = ROTL64(state[ 6], 44);
+               state[ 7] = ROTL64(state[ 7],  6);
+               state[ 8] = ROTL64(state[ 8], 55);
+               state[ 9] = ROTL64(state[ 9], 20);
+               state[10] = ROTL64(state[10],  3);
+               state[11] = ROTL64(state[11], 10);
+               state[12] = ROTL64(state[12], 43);
+               state[13] = ROTL64(state[13], 25);
+               state[14] = ROTL64(state[14], 39);
+               state[15] = ROTL64(state[15], 41);
+               state[16] = ROTL64(state[16], 45);
+               state[17] = ROTL64(state[17], 15);
+               state[18] = ROTL64(state[18], 21);
+               state[19] = ROTL64(state[19],  8);
+               state[20] = ROTL64(state[20], 18);
+               state[21] = ROTL64(state[21],  2);
+               state[22] = ROTL64(state[22], 61);
+               state[23] = ROTL64(state[23], 56);
+               state[24] = ROTL64(state[24], 14);
+
+               keccak_pi(state);
+               keccak_chi(state);
+
+               /* apply iota(state, round) */
+               *state ^= keccak_round_constants[round];
+       }
+}
+
+/*
+ * The core transformation. Process the specified block of data.
+ *
+ * @param hash the algorithm state
+ * @param block the message block to process
+ * @param block_size the size of the processed block in bytes
+ */
+static void
+rhash_sha3_process_block(hash, block, block_size)
+       UInt64_t        hash[25];
+       const UInt64_t  *block;
+       size_t          block_size;
+{
+       /* expanded loop */
+       hash[ 0] ^= le2me_64(block[ 0]);
+       hash[ 1] ^= le2me_64(block[ 1]);
+       hash[ 2] ^= le2me_64(block[ 2]);
+       hash[ 3] ^= le2me_64(block[ 3]);
+       hash[ 4] ^= le2me_64(block[ 4]);
+       hash[ 5] ^= le2me_64(block[ 5]);
+       hash[ 6] ^= le2me_64(block[ 6]);
+       hash[ 7] ^= le2me_64(block[ 7]);
+       hash[ 8] ^= le2me_64(block[ 8]);
+       /* if not sha3-512 */
+       if (block_size > 72) {
+               hash[ 9] ^= le2me_64(block[ 9]);
+               hash[10] ^= le2me_64(block[10]);
+               hash[11] ^= le2me_64(block[11]);
+               hash[12] ^= le2me_64(block[12]);
+               /* if not sha3-384 */
+               if (block_size > 104) {
+                       hash[13] ^= le2me_64(block[13]);
+                       hash[14] ^= le2me_64(block[14]);
+                       hash[15] ^= le2me_64(block[15]);
+                       hash[16] ^= le2me_64(block[16]);
+                       /* if not sha3-256 */
+                       if (block_size > 136) {
+                               hash[17] ^= le2me_64(block[17]);
+#ifdef FULL_SHA3_FAMILY_SUPPORT
+                               /* if not sha3-224 */
+                               if (block_size > 144) {
+                                       hash[18] ^= le2me_64(block[18]);
+                                       hash[19] ^= le2me_64(block[19]);
+                                       hash[20] ^= le2me_64(block[20]);
+                                       hash[21] ^= le2me_64(block[21]);
+                                       hash[22] ^= le2me_64(block[22]);
+                                       hash[23] ^= le2me_64(block[23]);
+                                       hash[24] ^= le2me_64(block[24]);
+                               }
+#endif
+                       }
+               }
+       }
+       /* make a permutation of the hash */
+       rhash_sha3_permutation(hash);
+}
+
+#define        SHA3_FINALIZED  0x80000000
+
+/*
+ * Calculate message hash.
+ * Can be called repeatedly with chunks of the message to be hashed.
+ *
+ * @param ctx the algorithm context containing current hashing state
+ * @param msg message chunk
+ * @param size length of the message chunk
+ */
+void
+rhash_sha3_update(ctx, msg, size)
+       sha3_ctx                *ctx;
+       const unsigned char     *msg;
+       size_t                  size;
+{
+       size_t idx = (size_t)ctx->rest;
+       size_t block_size = (size_t)ctx->block_size;
+
+       if (ctx->rest & SHA3_FINALIZED)
+               return; /* too late for additional input */
+       ctx->rest = (unsigned)((ctx->rest + size) % block_size);
+
+       /* fill partial block */
+       if (idx) {
+               size_t left = block_size - idx;
+               memcpy((char *)ctx->message + idx, msg,
+                       (size < left ? size : left));
+               if (size < left)
+                       return;
+
+               /* process partial block */
+               rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
+               msg  += left;
+               size -= left;
+       }
+       while (size >= block_size) {
+               UInt64_t *aligned_message_block;
+               if (IS_ALIGNED_64(msg)) {
+                       /*
+                        * the most common case is processing of an already
+                        * aligned message without copying it
+                        */
+                       aligned_message_block = (UInt64_t *)msg;
+               } else {
+                       memcpy(ctx->message, msg, block_size);
+                       aligned_message_block = ctx->message;
+               }
+
+               rhash_sha3_process_block(ctx->hash, aligned_message_block,
+                                       block_size);
+               msg  += block_size;
+               size -= block_size;
+       }
+       if (size) {
+               memcpy(ctx->message, msg, size); /* save leftovers */
+       }
+}
+
+/*
+ * Store calculated hash into the given array.
+ *
+ * @param ctx the algorithm context containing current hashing state
+ * @param result calculated hash in binary form
+ */
+void
+rhash_sha3_final(ctx, result)
+       sha3_ctx        *ctx;
+       unsigned char   *result;
+{
+       size_t digest_length = 100 - ctx->block_size / 2;
+       const size_t block_size = ctx->block_size;
+
+       if (!(ctx->rest & SHA3_FINALIZED))
+       {
+               /* clear the rest of the data queue */
+               memset((char *)ctx->message + ctx->rest, 0,
+                               block_size - ctx->rest);
+               ((char *)ctx->message)[ctx->rest] |= 0x06;
+               ((char *)ctx->message)[block_size - 1] |= 0x80;
+
+               /* process final block */
+               rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
+               ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
+       }
+
+       assert(block_size > digest_length);
+       if (result) me64_to_le_str(result, ctx->hash, digest_length);
+}
+
+void
+SHA3_Final(result, ctx)
+       UInt8_t         *result;
+       SHA3_CTX        *ctx;
+{
+       rhash_sha3_final(ctx, result);
+}
+
+#ifdef USE_KECCAK
+/*
+ * Store calculated hash into the given array.
+ *
+ * @param ctx the algorithm context containing current hashing state
+ * @param result calculated hash in binary form
+ */
+void
+rhash_keccak_final(sha3_ctx *ctx, unsigned char *result)
+{
+       size_t digest_length = 100 - ctx->block_size / 2;
+       const size_t block_size = ctx->block_size;
+
+       if (!(ctx->rest & SHA3_FINALIZED)) {
+               /* clear the rest of the data queue */
+               memset((char *)ctx->message + ctx->rest, 0,
+                               block_size - ctx->rest);
+               ((char *)ctx->message)[ctx->rest] |= 0x01;
+               ((char *)ctx->message)[block_size - 1] |= 0x80;
+
+               /* process final block */
+               rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
+               ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
+       }
+
+       assert(block_size > digest_length);
+       if (result)
+               me64_to_le_str(result, ctx->hash, digest_length);
+}
+#endif /* USE_KECCAK */
+
+#endif /* HAVE_LONGLONG */
index c222390..d1f4e89 100644 (file)
@@ -1,6 +1,6 @@
-/* @(#)fgetline.c      1.13 14/03/27 Copyright 1986, 1996-2014 J. Schilling */
+/* @(#)fgetline.c      1.14 16/11/07 Copyright 1986, 1996-2016 J. Schilling */
 /*
- *     Copyright (c) 1986, 1996-2014 J. Schilling
+ *     Copyright (c) 1986, 1996-2016 J. Schilling
  *
  *     This is an interface that exists in the public since 1982.
  *     The POSIX.1-2008 standard did ignore POSIX rules not to
 #define        fgetline        __no__fgetline__
 #define        getline         __no__getline__
 
+#define        FAST_GETC_PUTC          /* Will be reset if not possible */
 #include "schilyio.h"
 
+#ifdef LIB_SHEDIT
+#undef HAVE_USG_STDIO
+#undef FAST_GETC_PUTC
+#endif
+
 #ifndef        NO_GETLINE_COMPAT       /* Define to disable backward compatibility */
 #undef fgetline
 #undef getline
@@ -56,15 +62,12 @@ getline(buf, len)
 #endif
 #endif
 
-/*
- * XXX should we check if HAVE_USG_STDIO is defined and
- * XXX use something line memccpy to speed things up ???
- * XXX On Solaris 64 bits, we may use #define FAST_GETC_PUTC
- * XXX and getc_unlocked()
- */
 #if !defined(getc) && defined(USE_FGETS_FOR_FGETLINE)
 #include <schily/string.h>
 
+/*
+ * Warning: this prevents us from being able to have embedded null chars.
+ */
 EXPORT int
 js_fgetline(f, buf, len)
        register        FILE    *f;
@@ -93,15 +96,61 @@ js_fgetline(f, buf, len)
                        char    *buf;
        register        int     len;
 {
-       register int    c       = '\0';
        register char   *bp     = buf;
+#if    defined(HAVE_USG_STDIO) || defined(FAST_GETC_PUTC)
+       register char   *p;
+#else
        register int    nl      = '\n';
+       register int    c       = '\0';
+#endif
 
        down2(f, _IOREAD, _IORW);
 
+       if (len <= 0)
+               return (0);
+
+       *bp = '\0';
        for (;;) {
-               if ((c = getc(f)) < 0)
+#if    defined(HAVE_USG_STDIO) || defined(FAST_GETC_PUTC)
+               size_t  n;
+
+               if ((__c f)->_cnt <= 0) {
+                       if (usg_filbuf(f) == EOF) {
+                               /*
+                                * If buffer is empty and we hit EOF, return EOF
+                                */
+                               if (bp == buf)
+                                       return (EOF);
+                               break;
+                       }
+                       (__c f)->_cnt++;
+                       (__c f)->_ptr--;
+               }
+
+               n = len;
+               if (n > (__c f)->_cnt)
+                       n = (__c f)->_cnt;
+               p = movecbytes((__c f)->_ptr, bp, '\n', n);
+               if (p) {
+                       n = p - bp;
+               }
+               (__c f)->_ptr += n;
+               (__c f)->_cnt -= n;
+               bp += n;
+               len -= n;
+               if (p != NULL) {
+                       bp--;           /* Remove '\n' */
                        break;
+               }
+#else
+               if ((c = getc(f)) < 0) {
+                       /*
+                        * If buffer is empty and we hit EOF, return EOF
+                        */
+                       if (bp == buf)
+                               return (c);
+                       break;
+               }
                if (c == nl)
                        break;
                if (--len > 0) {
@@ -117,13 +166,9 @@ js_fgetline(f, buf, len)
 #endif
                        break;
                }
+#endif
        }
        *bp = '\0';
-       /*
-        * If buffer is empty and we hit EOF, return EOF
-        */
-       if (c < 0 && bp == buf)
-               return (c);
 
        return (bp - buf);
 }
index 427b8ae..7131c4f 100644 (file)
@@ -1,6 +1,6 @@
-/* @(#)schilyio.h      2.28 10/08/23 Copyright 1986, 1995-2010 J. Schilling */
+/* @(#)schilyio.h      2.31 16/11/06 Copyright 1986, 1995-2016 J. Schilling */
 /*
- *     Copyright (c) 1986, 1995-2010 J. Schilling
+ *     Copyright (c) 1986, 1995-2016 J. Schilling
  */
 /*
  * The contents of this file are subject to the terms of the
@@ -9,6 +9,8 @@
  * with the License.
  *
  * See the file CDDL.Schily.txt in this distribution for details.
+ * A copy of the CDDL is also available via the Internet at
+ * http://www.opensource.org/licenses/cddl1.txt
  *
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file CDDL.Schily.txt from this distribution.
@@ -150,11 +152,22 @@ extern    void    _io_add_my_flag __PR((FILE *, int));
 
 #endif /* DO_MYFLAG */
 
-#ifdef HAVE_USG_STDIO
+#if    defined(HAVE_USG_STDIO) || defined(FAST_GETC_PUTC)
+/*
+ * We are on a system with AT&T compatible stdio implementation
+ */
 
 /*
  * Use the right filbuf()/flsbuf() function.
  */
+#ifdef FAST_GETC_PUTC
+
+#define        __c     (struct SCHILY__FILE_TAG *)
+
+#ifndef        HAVE___FILBUF
+#define        HAVE___FILBUF
+#endif
+#endif
 #ifdef HAVE___FILBUF
 #      define  usg_filbuf(fp)          __filbuf(fp)
 #      define  usg_flsbuf(c, fp)       __flsbuf(c, fp)
@@ -162,7 +175,7 @@ extern      void    _io_add_my_flag __PR((FILE *, int));
  * Define prototypes to verify if our interface is right
  */
 extern int     __filbuf                __PR((FILE *));
-#else
+#else  /* !HAVE___FILBUF */
 #      ifdef   HAVE__FILBUF
 #      define  usg_filbuf(fp)          _filbuf(fp)
 #      define  usg_flsbuf(c, fp)       _flsbuf(c, fp)
@@ -175,7 +188,7 @@ extern      int     _filbuf                 __PR((FILE *));
  * no filbuf() but this will not happen on USG_STDIO systems.
  */
 #      endif
-#endif
+#endif /* !HAVE___FILBUF */
 /*
  * Do not check this because flsbuf()'s 1st parameter may be
  * int                 SunOS
@@ -184,11 +197,16 @@ extern    int     _filbuf                 __PR((FILE *));
  *
  * Note that the interface is now checked by autoconf.
  */
-#else
+#else  /* !HAVE_USG_STDIO */
 /*
  * If we are on a non USG system we cannot down file pointers
+ * and we do not know about the internals of the FILE structure.
  */
 #undef DO_DOWN
+#endif /* !HAVE_USG_STDIO */
+
+#ifndef        __c
+#define        __c
 #endif
 
 #ifndef        DO_DOWN
@@ -209,19 +227,19 @@ extern    int     _filbuf                 __PR((FILE *));
  *     and if iop->_flag refers to a stream with appropriate modes.
  *     If _iob[] gets expanded by malloc() we cannot check upper bound.
  */
-#define        down(f)         ((f) == 0 || (f)->_flag == 0 ? \
+#define        down(f)         ((f) == 0 || (__c f)->_flag == 0 ? \
                                (raisecond(_badfile, 0L), (FILE *)0) : (f))
 
-#define        down1(f, fl1)   ((f) == 0 || (f)->_flag == 0 ? \
+#define        down1(f, fl1)   ((f) == 0 || (__c f)->_flag == 0 ? \
                                        (raisecond(_badfile, 0L), (FILE *)0) : \
-                               (((f)->_flag & fl1) != fl1 ? \
+                               (((__c f)->_flag & fl1) != fl1 ? \
                                        (raisecond(_badop, 0L), (FILE *)0) : \
                                        (f)))
 
-#define        down2(f, fl1, fl2)      ((f) == 0 || (f)->_flag == 0 ? \
+#define        down2(f, fl1, fl2)      ((f) == 0 || (__c f)->_flag == 0 ? \
                                (raisecond(_badfile, 0L), (FILE *)0) : \
-                                   (((f)->_flag & fl1) != fl1 && \
-                                   ((f)->_flag & fl2)  != fl2 ? \
+                                   (((__c f)->_flag & fl1) != fl1 && \
+                                   ((__c f)->_flag & fl2)  != fl2 ? \
                                (raisecond(_badop, 0L), (FILE *)0) : \
                                (f)))
 #endif /* DO_DOWN */
index f8ec10b..f9257e3 100644 (file)
@@ -10,7 +10,20 @@ static       UConst char sccsid[] =
  *
  *     Copyright (c) 1999-2016 J. Schilling
  */
-/*@@C@@*/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
 
 #include "mkisofs.h"
 #include <schily/fcntl.h>
index db3dd47..d605dfb 100644 (file)
@@ -1,9 +1,9 @@
-/* @(#)defaults.h      1.25 13/02/14 joerg */
+/* @(#)defaults.h      1.26 16/12/12 joerg */
 /*
  * Header file defaults.h - assorted default values for character strings in
  * the volume descriptor.
  *
- * Copyright (c) 1999-2013 J. Schilling
+ * Copyright (c) 1999-2016 J. Schilling
  */
 
 #define        PREPARER_DEFAULT        NULL
 #define        SYSTEM_ID_DEFAULT       "AIX"
 #endif
 
-#if    defined(_WIN) || defined(__CYGWIN32__) || defined(__CYGWIN__)
-#define        SYSTEM_ID_DEFAULT       "Win32"
-#endif /* _WIN */
+#if    defined(__CYGWIN32__) || defined(__CYGWIN__)
+#define        SYSTEM_ID_DEFAULT       "Win32/Cygwin"
+#endif
 
-#if    !defined(SYSTEM_ID_DEFAULT) && defined(__MINGW32__)
+#if    defined(__MINGW32__)
 #define        SYSTEM_ID_DEFAULT       "Win32/MinGW"
-#endif /* __MINGW32__ */
+#endif
+
+#if    defined(_MSC_VER)
+#define        SYSTEM_ID_DEFAULT       "Win32/MSVC"
+#endif
 
 #ifdef __EMX__
 #define        SYSTEM_ID_DEFAULT       "OS/2"
index dc8641a..5b5794d 100644 (file)
@@ -1,8 +1,8 @@
-/* @(#)hash.c  1.28 10/12/19 joerg */
+/* @(#)hash.c  1.30 16/12/13 joerg */
 #include <schily/mconfig.h>
 #ifndef lint
 static UConst char sccsid[] =
-       "@(#)hash.c     1.28 10/12/19 joerg";
+       "@(#)hash.c     1.30 16/12/13 joerg";
 
 #endif
 /*
@@ -11,7 +11,7 @@ static        UConst char sccsid[] =
  * Written by Eric Youngdale (1993).
  *
  * Copyright 1993 Yggdrasil Computing, Incorporated
- * Copyright (c) 1999,2000-2010 J. Schilling
+ * Copyright (c) 1999,2000-2016 J. Schilling
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -47,8 +47,11 @@ static       UConst char sccsid[] =
  * allow to disable the mkisofs inode cache.
  */
 
+/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
+
 #include "mkisofs.h"
 #include <schily/schily.h>
+#include <schily/sha3.h>
 
 #define        NR_HASH (16*1024)
 
@@ -56,11 +59,32 @@ static      UConst char sccsid[] =
 
 static struct file_hash *hash_table[NR_HASH];
 
+#ifdef DUPLICATES_ONCE
+
+#define        DIGEST_FAST_SIZE                65536
+#define        UNIQUE_FILES_HASH_FN(SIZE)      ((SIZE) % NR_HASH)
+
+#ifndef        DIGEST_Init
+#define        DIGEST_Init                     SHA3_512_Init
+#define        DIGEST_Update                   SHA3_Update
+#define        DIGEST_Final                    SHA3_Final
+#define        DIGEST_CTX                      SHA3_CTX
+#define        DIGEST_LENGTH                   SHA3_512_DIGEST_LENGTH
+
+#ifdef SHORT_DIGEST
+#undef DIGEST_Init
+#undef DIGEST_LENGTH
+#define        DIGEST_Init                     SHA3_256_Init
+#define        DIGEST_LENGTH                   SHA3_256_DIGEST_LENGTH
+#endif /* SHORT_DIGEST */
+#endif /* DIGEST_Init */
+#endif
+
 #ifdef HASH_DEBUG
 EXPORT void            debug_hash      __PR((void));
 #endif
 EXPORT void            add_hash        __PR((struct directory_entry *spnt));
-EXPORT struct file_hash *find_hash     __PR((dev_t dev, ino_t inode));
+EXPORT struct file_hash *find_hash     __PR((struct directory_entry *spnt));
 EXPORT void            flush_hash      __PR((void));
 EXPORT void            add_directory_hash __PR((dev_t dev, ino_t inode));
 EXPORT struct file_hash *find_directory_hash __PR((dev_t dev, ino_t inode));
@@ -70,6 +94,12 @@ EXPORT       struct directory_entry *find_file_hash __PR((char *name));
 LOCAL  BOOL            isoname_endsok  __PR((char *name));
 EXPORT int             delete_file_hash __PR((struct directory_entry *de));
 EXPORT void            flush_file_hash __PR((void));
+#ifdef DUPLICATES_ONCE
+LOCAL  struct directory_entry *compare_files __PR((
+                                       struct directory_entry *spnt1,
+                                       struct directory_entry *spnt2));
+LOCAL  unsigned char   *DIGEST_File    __PR((char *name, size_t size));
+#endif
 
 #ifdef HASH_DEBUG
 EXPORT void
@@ -111,7 +141,7 @@ add_hash(spnt)
        struct directory_entry  *spnt;
 {
        struct file_hash *s_hash;
-       unsigned int    hash_number;
+       unsigned int    hash_number = 0;
 
        if (spnt->size == 0 || spnt->starting_block == 0)
                if (spnt->size != 0 && spnt->starting_block == 0) {
@@ -120,14 +150,26 @@ add_hash(spnt)
                                                        spnt->name);
                };
 
+#ifdef DUPLICATES_ONCE
+       if (!cache_inodes && !duplicates_once)
+#else
        if (!cache_inodes)
+#endif
                return;
        if (spnt->dev == UNCACHED_DEVICE &&
            (spnt->inode == TABLE_INODE || spnt->inode == UNCACHED_INODE)) {
                return;
        }
-       hash_number = HASH_FN((unsigned int) spnt->dev,
+#ifdef DUPLICATES_ONCE
+       if (cache_inodes)
+#endif
+               hash_number = HASH_FN((unsigned int) spnt->dev,
                                                (unsigned int) spnt->inode);
+#ifdef DUPLICATES_ONCE
+       else if (duplicates_once &&
+                   spnt->size && !(spnt->isorec.flags[0] & ISO_DIRECTORY))
+               hash_number = UNIQUE_FILES_HASH_FN((unsigned int) spnt->size);
+#endif
 
 #if 0
        if (verbose > 1)
@@ -140,38 +182,53 @@ add_hash(spnt)
        s_hash->nlink = 0;
        s_hash->starting_block = spnt->starting_block;
        s_hash->size = spnt->size;
-#ifdef SORTING
+#if    defined(SORTING) || defined(DUPLICATES_ONCE)
        s_hash->de = spnt;
-#endif /* SORTING */
+#endif /* defined(SORTING) || defined(DUPLICATES_ONCE) */
        hash_table[hash_number] = s_hash;
 }
 
-#ifdef PROTOTYPES
-EXPORT struct file_hash *
-find_hash(dev_t dev, ino_t inode)
-#else
 EXPORT struct file_hash *
-find_hash(dev, inode)
-       dev_t   dev;
-       ino_t   inode;
-#endif
+find_hash(spnt)
+       struct directory_entry  *spnt;
 {
        unsigned int    hash_number;
-       struct file_hash *spnt;
+       struct file_hash *s_hash;
 
+#ifdef DUPLICATES_ONCE
+       if (!cache_inodes && !duplicates_once)
+#else
        if (!cache_inodes)
+#endif
                return (NULL);
-       if (dev == UNCACHED_DEVICE &&
-           (inode == TABLE_INODE || inode == UNCACHED_INODE))
+       if (spnt->dev == UNCACHED_DEVICE &&
+           (spnt->inode == TABLE_INODE || spnt->inode == UNCACHED_INODE))
                return (NULL);
 
-       hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
-       spnt = hash_table[hash_number];
-       while (spnt) {
-               if (spnt->inode == inode && spnt->dev == dev)
-                       return (spnt);
-               spnt = spnt->next;
-       };
+#ifdef DUPLICATES_ONCE
+       if (cache_inodes) {
+#endif
+               hash_number = HASH_FN((unsigned int) spnt->dev,
+                                   (unsigned int) spnt->inode);
+               s_hash = hash_table[hash_number];
+               while (s_hash) {
+                       if (s_hash->inode == spnt->inode &&
+                           s_hash->dev == spnt->dev)
+                               return (s_hash);
+                       s_hash = s_hash->next;
+               }
+#ifdef DUPLICATES_ONCE
+       } else if (duplicates_once &&
+                   spnt->size && !(spnt->isorec.flags[0] & ISO_DIRECTORY)) {
+               hash_number = UNIQUE_FILES_HASH_FN((unsigned int) spnt->size);
+               s_hash = hash_table[hash_number];
+               while (s_hash) {
+                       if (compare_files(spnt, s_hash->de))
+                               return (s_hash);
+                       s_hash = s_hash->next;
+               }
+       }
+#endif
        return (NULL);
 }
 
@@ -197,6 +254,88 @@ flush_hash()
        }
 }
 
+#ifdef DUPLICATES_ONCE
+LOCAL struct directory_entry *
+compare_files(spnt1, spnt2)
+       struct directory_entry  *spnt1;
+       struct directory_entry  *spnt2;
+{
+       if (spnt1->size != spnt2->size)
+               return (NULL);
+
+       if (!spnt1->digest_fast)
+               if (!(spnt1->digest_fast = DIGEST_File(spnt1->whole_name,
+                               (spnt1->size > DIGEST_FAST_SIZE) ?
+                               DIGEST_FAST_SIZE : spnt1->size)))
+                       return (NULL);
+
+       if (spnt1->size <= DIGEST_FAST_SIZE)
+               spnt1->digest_full = spnt1->digest_fast;
+
+       if (!spnt2->digest_fast)
+               if (!(spnt2->digest_fast = DIGEST_File(spnt2->whole_name,
+                               (spnt2->size > DIGEST_FAST_SIZE) ?
+                               DIGEST_FAST_SIZE : spnt2->size)))
+                       return (NULL);
+
+       if (spnt2->size <= DIGEST_FAST_SIZE)
+               spnt2->digest_full = spnt2->digest_fast;
+
+       if (memcmp(spnt1->digest_fast, spnt2->digest_fast,
+                       DIGEST_LENGTH * sizeof (unsigned char)))
+               return (NULL);
+
+       if (!spnt1->digest_full)
+               if (!(spnt1->digest_full = DIGEST_File(spnt1->whole_name,
+                                               spnt1->size)))
+                       return (NULL);
+
+       if (!spnt2->digest_full)
+               if (!(spnt2->digest_full = DIGEST_File(spnt2->whole_name,
+                                               spnt2->size)))
+                       return (NULL);
+
+       if (memcmp(spnt1->digest_full, spnt2->digest_full,
+                       DIGEST_LENGTH * sizeof (unsigned char)))
+               return (NULL);
+
+       return (spnt2);
+}
+
+LOCAL unsigned char *
+DIGEST_File(name, size)
+       char            *name;
+       size_t          size;
+{
+       DIGEST_CTX      digest_ctx;
+       FILE            *infile;
+       unsigned char   buf[32768];
+       unsigned char   *digest_hash;
+       size_t          cnt;
+
+       DIGEST_Init(&digest_ctx);
+
+       if ((infile = fopen(name, "rb")) == NULL)
+               return (NULL);
+
+       while (size) {
+               cnt = (size > sizeof (buf)) ? sizeof (buf) : size;
+               if ((cnt = fread(buf, 1, cnt, infile)) <= 0) {
+                       fclose(infile);
+                       return (NULL);
+               }
+               DIGEST_Update(&digest_ctx, buf, cnt);
+               size -= cnt;
+       }
+
+       fclose(infile);
+
+       digest_hash = e_malloc(sizeof (unsigned char) * DIGEST_LENGTH);
+       DIGEST_Final(digest_hash, &digest_ctx);
+       return (digest_hash);
+}
+#endif
+
 static struct file_hash *directory_hash_table[NR_HASH];
 
 #ifdef PROTOTYPES
index 59d906e..0a61e18 100644 (file)
@@ -1,8 +1,8 @@
-/* @(#)inode.c 1.18 15/12/08 Copyright 2006-2015 J. Schilling */
+/* @(#)inode.c 1.19 16/11/14 Copyright 2006-2016 J. Schilling */
 #include <schily/mconfig.h>
 #ifndef lint
 static UConst char sccsid[] =
-       "@(#)inode.c    1.18 15/12/08 Copyright 2006-2015 J. Schilling";
+       "@(#)inode.c    1.19 16/11/14 Copyright 2006-2015 J. Schilling";
 #endif
 /*
  *     Inode and link count handling for ISO-9660/RR
@@ -14,7 +14,7 @@ static        UConst char sccsid[] =
  *     of asigning the related number to the "extent" field in the ISO
  *     directory record.
  *
- *     Copyright (c) 2006-2015 J. Schilling
+ *     Copyright (c) 2006-2016 J. Schilling
  */
 /*
  * This program is free software; you can redistribute it and/or modify
@@ -120,7 +120,7 @@ assign_inodes(dpnt)
                s_entry = dpnt->contents;
                for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) {
                        if (s_entry->starting_block == 0) {
-                               s_hash = find_hash(s_entry->dev, s_entry->inode);
+                               s_hash = find_hash(s_entry);
                                /* find_directory_hash() ? */
                                if (s_hash)
                                        s_entry->starting_block = s_hash->starting_block;
@@ -162,7 +162,7 @@ assign_inodes(dpnt)
                                s_entry->dev = PREV_SESS_DEV;
                                s_entry->inode = null_inodes;
                        }
-                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       s_hash = find_hash(s_entry);
                        if (s_hash) {
                                /*
                                 * Paranoia: Check for hashed files without proper inode #.
@@ -247,12 +247,12 @@ compute_linkcount(dpnt)
                                                s_entry->whole_name : s_entry->name);
                                }
                        }
-                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       s_hash = find_hash(s_entry);
                        if (s_hash) {
                                s_hash->nlink++;
                        } else {
                                add_hash(s_entry);
-                               s_hash = find_hash(s_entry->dev, s_entry->inode);
+                               s_hash = find_hash(s_entry);
                                if (s_hash == NULL) {
                                        if (s_entry->dev == UNCACHED_DEVICE &&
                                            s_entry->inode == TABLE_INODE) {
@@ -300,7 +300,7 @@ assign_linkcount(dpnt)
                        if (s_entry->de_flags & RESOURCE_FORK)
                                continue;
 
-                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       s_hash = find_hash(s_entry);
                        if (s_hash) {
                                update_nlink(s_entry, s_hash->nlink);
                        } else {
index 443f2e9..b66378b 100644 (file)
@@ -1,8 +1,8 @@
-/* @(#)match.c 1.31 16/10/10 joerg */
+/* @(#)match.c 1.34 16/11/27 joerg */
 #include <schily/mconfig.h>
 #ifndef lint
 static UConst char sccsid[] =
-       "@(#)match.c    1.31 16/10/10 joerg";
+       "@(#)match.c    1.34 16/11/27 joerg";
 #endif
 /*
  * 27-Mar-96: Jan-Piet Mens <jpm@mens.de>
@@ -32,6 +32,8 @@ struct match {
 
 typedef struct match match;
 
+static BOOL    isort;
+
 static match *mats[MAX_MAT];
 
 static char *mesg[MAX_MAT] = {
@@ -87,8 +89,12 @@ add_sort_match(fn, val)
 }
 
 EXPORT int
-add_sort_list(file)
-       char    *file;
+add_sort_list(file, valp, pac, pav, opt)
+       const char      *file;
+       void            *valp;
+       int             *pac;
+       char    *const  **pav;
+       const char      *opt;
 {
        FILE    *fp;
        char    name[4096];
@@ -96,6 +102,10 @@ add_sort_list(file)
        int     val;
 extern int     do_sort;
 
+       while (*opt == '-')
+               opt++;
+       if (*opt == 'i')
+               isort = TRUE;
        do_sort++;
        if ((fp = fopen(file, "r")) == NULL) {
                comerr(_("Can't open sort file list %s\n"), file);
@@ -136,9 +146,13 @@ sort_matches(fn, val)
        int     val;
 {
        register sort_match     *s_mat;
+               int             flags = FNM_PATHNAME;
+
+       if (isort)
+               flags |= FNM_IGNORECASE;
 
        for (s_mat = s_mats; s_mat; s_mat = s_mat->next) {
-               if (fnmatch(s_mat->name, fn, FNM_PATHNAME) != FNM_NOMATCH) {
+               if (fnmatch(s_mat->name, fn, flags) != FNM_NOMATCH) {
                        return (s_mat->val); /* found sort value */
                }
        }
@@ -350,12 +364,17 @@ gen_matches(fn, n)
        int     n;
 {
        register match * mat;
+               int             flags = FNM_PATHNAME;
+
 
        if (n >= MAX_MAT)
                return (0);
 
+       if (match_igncase)
+               flags |= FNM_IGNORECASE;
+
        for (mat = mats[n]; mat; mat = mat->next) {
-               if (fnmatch(mat->name, fn, FNM_PATHNAME) != FNM_NOMATCH) {
+               if (fnmatch(mat->name, fn, flags) != FNM_NOMATCH) {
                        return (1);     /* found -> excluded filename */
                }
        }
index bc82e65..98b6053 100644 (file)
@@ -1,10 +1,10 @@
-/* @(#)match.h 1.15 09/07/10 joerg */
+/* @(#)match.h 1.18 16/12/12 joerg */
 /*
  * 27th March 1996. Added by Jan-Piet Mens for matching regular expressions
  *                  in paths.
  *
  * Conversions to make the code more portable May 2000 .. March 2004
- * Copyright (c) 2000-2009 J. Schilling
+ * Copyright (c) 2000-2016 J. Schilling
  */
 
 #include <schily/fnmatch.h>
@@ -52,11 +52,15 @@ extern void gen_del_match   __PR((int n));
 
 #ifdef SORTING
 extern int     add_sort_match  __PR((char *fn, int val));
-extern int     add_sort_list   __PR((char *fn));
+extern int     add_sort_list   __PR((const char *fn, void *valp,
+                                       int *pac, char *const **pav,
+                                       const char *opt));
 extern int     sort_matches    __PR((char *fn, int val));
 extern void    del_sort        __PR((void));
 #endif /* SORTING */
 
+extern int     match_igncase;
+
 /*
  * The following are for compatiblity with the separate routines - the
  * main code should be changed to call the generic routines directly
index aec899a..a7136a5 100644 (file)
@@ -1,8 +1,8 @@
-/* @(#)mkisofs.c       1.284 16/10/23 joerg */
+/* @(#)mkisofs.c       1.288 16/12/13 joerg */
 #include <schily/mconfig.h>
 #ifndef lint
 static UConst char sccsid[] =
-       "@(#)mkisofs.c  1.284 16/10/23 joerg";
+       "@(#)mkisofs.c  1.288 16/12/13 joerg";
 #endif
 /*
  * Program mkisofs.c - generate iso9660 filesystem  based upon directory
@@ -32,6 +32,8 @@ static        UConst char sccsid[] =
 /* MAC UDF images by HELIOS Software GmbH support@helios.de */
 /* HFS+ by HELIOS Software GmbH support@helios.de */
 
+/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
+
 #ifdef USE_FIND
 #include <schily/walk.h>
 #include <schily/find.h>
@@ -227,6 +229,7 @@ struct eltorito_boot_entry_info *last_boot_entry = NULL;
 struct eltorito_boot_entry_info *current_boot_entry = NULL;
 
 int    use_graft_ptrs;         /* Use graft points */
+int    match_igncase;          /* Ignore case with -exclude-list and -hide* */
 int    jhide_trans_tbl;        /* Hide TRANS.TBL from Joliet tree */
 int    hide_rr_moved;          /* Name RR_MOVED .rr_moved in Rock Ridge tree */
 int    omit_period = 0;        /* Violates iso9660, but these are a pain */
@@ -243,6 +246,7 @@ int full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */
 int    nolimitpathtables = 0;  /* Don't limit size of pathtable. Violates iso9660 */
 int    relaxed_filenames = 0;  /* For Amiga.  Disc will not work with DOS */
 int    allow_lowercase = 0;    /* Allow lower case letters */
+int    no_allow_lowercase = 0; /* Do not allow lower case letters */
 int    allow_multidot = 0;     /* Allow more than on dot in filename */
 int    iso_translate = 1;      /* 1 == enables '#', '-' and '~' removal */
 int    allow_leading_dots = 0; /* DOS cannot read names with leading dots */
@@ -322,6 +326,10 @@ BOOL       correct_inodes = TRUE;  /* TRUE: add a "correct inodes" fingerprint */
 BOOL   rrip112 = TRUE;         /* TRUE: create Rock Ridge V 1.12           */
 BOOL   long_rr_time = FALSE;   /* TRUE: use long (17 Byte) time format     */
 
+#ifdef DUPLICATES_ONCE
+int    duplicates_once = 0;    /* encode duplicate files once */
+#endif
+
 siconvt_t      *in_nls = NULL;  /* input UNICODE conversion table */
 siconvt_t      *out_nls = NULL; /* output UNICODE conversion table */
 #ifdef APPLE_HYB
@@ -1104,6 +1112,10 @@ LOCAL const struct mki_option mki_options[] =
        __("Create old Rock Ridge V 1.10")},
        {{"rrip112", &rrip112 },
        __("Create new Rock Ridge V 1.12 (default)")},
+#ifdef DUPLICATES_ONCE
+       {{"duplicates-once", &duplicates_once},
+       __("Optimize storage by encoding duplicate files once")},
+#endif
        {{"check-oldnames", &check_oldnames },
        __("Check all imported ISO9660 names from old session")},
        {{"check-session*", &check_image },
@@ -1212,6 +1224,12 @@ LOCAL const struct mki_option mki_options[] =
        __("\1GLOBFILE\1Exclude file name")},
        {{"exclude-list&", NULL, (getpargfun)add_list},
        __("\1FILE\1File with list of file names to exclude")},
+
+       {{"hide-ignorecase", &match_igncase },
+       __("Ignore case with -exclude-list and -hide* options")},
+       {{"exclude-ignorecase", &match_igncase },
+       NULL},
+
        {{"modification-date&", &modification_date, (getpargfun)get_ldate },
        __("\1DATE\1Set the modification date field of the PVD")},
        {{"nobak%0", &all_files },
@@ -1264,8 +1282,10 @@ LOCAL const struct mki_option mki_options[] =
        __("Use short Rock Ridge time format")},
 
 #ifdef SORTING
-       { {"sort&", NULL, (getpargfun)add_sort_list },
+       { {"sort&", NULL, add_sort_list },
        __("\1FILE\1Sort file content locations according to rules in FILE")},
+       { {"isort&", NULL, add_sort_list },
+       __("\1FILE\1Sort file content locations according to rules in FILE (ignore case)")},
 #endif /* SORTING */
 
        {{"split-output", &split_output },
@@ -1314,6 +1334,10 @@ LOCAL const struct mki_option mki_options[] =
        __("Do not translate illegal ISO characters '~', '-' and '#' (violates ISO9660)")},
        {{"allow-lowercase", &allow_lowercase },
        __("Allow lower case characters in addition to the current character set (violates ISO9660)")},
+       {{"no-allow-lowercase", &no_allow_lowercase },
+       __("Do not allow lower case characters in addition to the current character set.")},
+       {{"+allow-lowercase", &no_allow_lowercase },
+       NULL},
        {{"allow-multidot", &allow_multidot },
        __("Allow more than one dot in filenames (e.g. .tar.gz) (violates ISO9660)")},
        {{"use-fileversion", &use_fileversion },
@@ -1668,7 +1692,8 @@ const char *
 optend(fmt)
        const char      *fmt;
 {
-       int     c;
+       int             c;
+       const char      *ofmt = fmt;
 
        for (; *fmt != '\0'; fmt++) {
                c = *fmt;
@@ -1678,7 +1703,9 @@ optend(fmt)
                        continue;
                }
                if (c == ',' || c == '%' || c == '*' || c == '?' ||
-                   c == '#' || c == '&' || c == '~' || c == '+')
+                   c == '#' || c == '&' || c == '~')
+                       break;
+               if (fmt > ofmt && c == '+')
                        break;
 
        }
@@ -2185,7 +2212,11 @@ Copyright (C) 1997-2016 %s\n"),
                        (Llong)strlen(biblio));
                }
        }
+#ifdef DUPLICATES_ONCE
+       if (!cache_inodes && !duplicates_once) {
+#else
        if (!cache_inodes) {
+#endif
                correct_inodes = FALSE;
                if (use_RockRidge) {
                        errmsgno(EX_BAD,
@@ -2195,6 +2226,14 @@ Copyright (C) 1997-2016 %s\n"),
                        _("Warning: Cannot add inode hints with -no-cache-inodes.\n"));
                }
        }
+#if    defined(__MINGW32__)
+       if (cache_inodes) {
+               cache_inodes = 0;
+               correct_inodes = FALSE;
+               errmsgno(EX_BAD,
+               _("Warning: cannot -cache-inodes on this platform - ignoring.\n"));
+       }
+#endif
        if (!correct_inodes)
                rrip112 = FALSE;
        if (check_image) {
@@ -2453,6 +2492,8 @@ Copyright (C) 1997-2016 %s\n"),
                allow_multidot++;               /* > 1 dots     */
                warn_violate++;
        }
+       if (no_allow_lowercase)
+               allow_lowercase = 0;
        if (relaxed_filenames && iso9660_level < 4)
                warn_violate++;
        if (iso_translate == 0 && iso9660_level < 4)
index 050f0e2..59b49fb 100644 (file)
@@ -1,4 +1,4 @@
-/* @(#)mkisofs.h       1.150 16/10/10 joerg */
+/* @(#)mkisofs.h       1.152 16/12/13 joerg */
 /*
  * Header file mkisofs.h - assorted structure definitions and typecasts.
  *
@@ -24,6 +24,8 @@
 
 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
 
+/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
+
 #include <schily/mconfig.h>    /* Must be before stdio.h for LARGEFILE support */
 #include <schily/stdio.h>
 #include <schily/types.h>
@@ -145,6 +147,10 @@ struct directory_entry {
 #ifdef UDF
        int             udf_file_entry_sector;  /* also used as UDF unique ID */
 #endif
+#ifdef DUPLICATES_ONCE
+       unsigned char   *digest_fast;
+       unsigned char   *digest_full;
+#endif
 };
 
 struct file_hash {
@@ -154,7 +160,7 @@ struct file_hash {
        nlink_t         nlink;          /* Used to compute new link count */
        unsigned int    starting_block;
        off_t           size;
-#ifdef SORTING
+#if    defined(SORTING) || defined(DUPLICATES_ONCE)
        struct directory_entry *de;
 #endif /* SORTING */
 };
@@ -376,6 +382,9 @@ extern int  dirmode_to_use;
 extern int     new_dir_mode;
 extern int     follow_links;
 extern int     cache_inodes;
+#ifdef DUPLICATES_ONCE
+extern int     duplicates_once;
+#endif
 extern int     verbose;
 extern int     debug;
 extern int     gui;
@@ -593,7 +602,7 @@ extern int iso9660_file_length __PR((const char *name,
 extern int iso9660_date __PR((char *, time_t));
 extern int iso9660_ldate __PR((char *, time_t, int, int));
 extern void add_hash __PR((struct directory_entry *));
-extern struct file_hash *find_hash __PR((dev_t, ino_t));
+extern struct file_hash *find_hash __PR((struct directory_entry *spnt));
 
 extern void flush_hash __PR((void));
 extern void add_directory_hash __PR((dev_t, ino_t));
index 09d1a1f..068a53d 100644 (file)
@@ -1,8 +1,21 @@
-/* @(#)scsi.h  1.3 16/10/13 Copyright 1997-2004 J. Schilling */
+/* @(#)scsi.h  1.4 16/11/14 Copyright 1997-2016 J. Schilling */
 /*
- *     Copyright (c) 1997-2004 J. Schilling
+ *     Copyright (c) 1997-2016 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-/*@@C@@*/
 
 #ifndef        _SCSI_H
 #define        _SCSI_H
index 64db121..0e2a018 100644 (file)
@@ -1,8 +1,8 @@
-/* @(#)tree.c  1.136 16/10/23 joerg */
+/* @(#)tree.c  1.137 16/12/13 joerg */
 #include <schily/mconfig.h>
 #ifndef lint
 static UConst char sccsid[] =
-       "@(#)tree.c     1.136 16/10/23 joerg";
+       "@(#)tree.c     1.137 16/12/13 joerg";
 #endif
 /*
  * File tree.c - scan directory  tree and build memory structures for iso9660
@@ -31,6 +31,8 @@ static        UConst char sccsid[] =
 
 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
 
+/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
+
 #include "mkisofs.h"
 #include "rock.h"
 #include "match.h"
@@ -1818,6 +1820,10 @@ insert_file_entry(this_dir, whole_path, short_name, statp, have_rsrc)
        s_entry->de_flags = 0;
        if (S_ISLNK(lstatbuf.st_mode))
                s_entry->de_flags |= IS_SYMLINK;
+#ifdef DUPLICATES_ONCE
+       s_entry->digest_fast = NULL;
+       s_entry->digest_full = NULL;
+#endif
 
        /*
         * If the current directory is hidden, then hide all it's members
index 17a57c3..2288f06 100644 (file)
@@ -1,8 +1,8 @@
-/* @(#)write.c 1.144 16/10/10 joerg */
+/* @(#)write.c 1.146 16/12/13 joerg */
 #include <schily/mconfig.h>
 #ifndef lint
 static UConst char sccsid[] =
-       "@(#)write.c    1.144 16/10/10 joerg";
+       "@(#)write.c    1.146 16/12/13 joerg";
 #endif
 /*
  * Program write.c - dump memory  structures to  file for iso9660 filesystem.
@@ -29,6 +29,8 @@ static        UConst char sccsid[] =
 
 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
 
+/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
+
 #include "mkisofs.h"
 #include <schily/time.h>
 #include <schily/fcntl.h>
@@ -952,7 +954,7 @@ reassign_link_addresses(dpnt)
                                continue;
 
                        /* update the start extent */
-                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       s_hash = find_hash(s_entry);
                        if (s_hash) {
                                set_733((char *)s_entry->isorec.extent, s_hash->starting_block);
                                s_entry->starting_block = s_hash->starting_block;
@@ -1135,7 +1137,7 @@ assign_file_addresses(dpnt, isnest)
                         * If this is a multi-extent file, we get mxpart == 1
                         * from find_hash().
                         */
-                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       s_hash = find_hash(s_entry);
                        if (s_hash) {
                                if (verbose > 2) {
                                        fprintf(stderr, _("Cache hit for '%s%s%s'\n"),
@@ -1502,6 +1504,19 @@ free_one_directory(dpnt)
                }
 #endif /* APPLE_HYB */
 
+#ifdef DUPLICATES_ONCE
+               if (s_entry_d->digest_fast) {
+
+                       if (s_entry_d->digest_full &&
+                           (s_entry_d->digest_full != s_entry_d->digest_fast))
+                               free(s_entry_d->digest_full);
+
+                       free(s_entry_d->digest_fast);
+
+                       s_entry_d->digest_fast = NULL;
+                       s_entry_d->digest_full = NULL;
+               }
+#endif
                free(s_entry_d);
                s_entry_d = NULL;
        }
@@ -2887,7 +2902,7 @@ adj_size_other(dpnt)
                         * find any cached entry and assign new starting
                         * extent
                         */
-                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       s_hash = find_hash(s_entry);
                        if (s_hash) {
                                set_733((char *)s_entry->isorec.extent,
                                                s_hash->starting_block);