From 04259f737b589dfe0e01173706875749e7ce81b9 Mon Sep 17 00:00:00 2001 From: Jakub Martisko Date: Tue, 6 Feb 2024 15:12:45 +0100 Subject: [PATCH] Add: gating tests Resolves: RHEL-24429 --- tests/gating/all.sh | 55 +++++++ tests/gating/build/__debug.h | 96 ++++++++++++ tests/gating/build/__fnmatch.h | 32 ++++ tests/gating/build/__hints.h | 195 ++++++++++++++++++++++++ tests/gating/build/__mkdir.h | 12 ++ tests/gating/build/__string.h | 67 ++++++++ tests/gating/build/test.sh | 5 + tests/gating/build/unzzip-states.h | 24 +++ tests/gating/build/unzzip.c | 81 ++++++++++ tests/gating/build/unzzipcat-zip.c | 235 +++++++++++++++++++++++++++++ tests/gating/build/unzzipcat-zip.h | 10 ++ tests/gating/build/unzzipdir-mix.c | 150 ++++++++++++++++++ tests/gating/build/unzzipdir-zip.h | 10 ++ tests/tests.yml | 21 +++ zziplib.spec | 6 +- 15 files changed, 998 insertions(+), 1 deletion(-) create mode 100755 tests/gating/all.sh create mode 100644 tests/gating/build/__debug.h create mode 100644 tests/gating/build/__fnmatch.h create mode 100644 tests/gating/build/__hints.h create mode 100644 tests/gating/build/__mkdir.h create mode 100644 tests/gating/build/__string.h create mode 100755 tests/gating/build/test.sh create mode 100644 tests/gating/build/unzzip-states.h create mode 100644 tests/gating/build/unzzip.c create mode 100644 tests/gating/build/unzzipcat-zip.c create mode 100644 tests/gating/build/unzzipcat-zip.h create mode 100644 tests/gating/build/unzzipdir-mix.c create mode 100644 tests/gating/build/unzzipdir-zip.h create mode 100644 tests/tests.yml diff --git a/tests/gating/all.sh b/tests/gating/all.sh new file mode 100755 index 0000000..e156281 --- /dev/null +++ b/tests/gating/all.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright (C) 2019 Jakub Martisko + +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: + +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. + +# 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. + +passed=0 +subtests=(build) +total=${#subtests[@]} +skipped=0 + +for subtest in ${subtests[@]} +do + #tests to be skipped + if [ $subtest == "foo" ] + then + ((skipped++)) + continue + fi + pushd $subtest >/dev/null + ./test.sh + result=$? + echo "Test $subtest result: $result" + if [ "$result" == "0" ] + then + ((passed++)) + fi + popd >/dev/null +done + +echo "Passed $passed/$total tests" +echo "Skipped $skipped/$total tests" +[[ $total == $((passed + skipped)) ]] || exit 1 diff --git a/tests/gating/build/__debug.h b/tests/gating/build/__debug.h new file mode 100644 index 0000000..49632a6 --- /dev/null +++ b/tests/gating/build/__debug.h @@ -0,0 +1,96 @@ +#ifndef __ZZIP_INTERNAL_DEBUG_H +#define __ZZIP_INTERNAL_DEBUG_H + +#include +#include "__hints.h" + +/* perhaps want to show on syslog(3) ?? */ + +#ifdef DEBUG +#include +#define MSG1(X1) ZZIP_FOR1 { \ + fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \ + ); } ZZIP_END1 +#define MSG2(X1,X2) ZZIP_FOR1 { \ + fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \ + ,X2);} ZZIP_END1 +#define MSG3(X1,X2,X3) ZZIP_FOR1 { \ + fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \ + ,X2,X3); } ZZIP_END1 +#define MSG4(X1,X2,X3,X4) ZZIP_FOR1 { \ + fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \ + ,X2,X3,X4); } ZZIP_END1 +#define MSG5(X1,X2,X3,X4,X5) ZZIP_FOR1 { \ + fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \ + ,X2,X3,X4,X5); } ZZIP_END1 +#define MSG6(X1,X2,X3,X4,X5,X6) ZZIP_FOR1 { \ + fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \ + ,X2,X3,X4,X5,X6); } ZZIP_END1 + +#else +#define MSG1(X1) {} +#define MSG2(X1,X2) {} +#define MSG3(X1,X2,X3) {} +#define MSG4(X1,X2,X3,X4) {} +#define MSG5(X1,X2,X3,X4,X5) {} +#define MSG6(X1,X2,X3,X4,X5,X6) {} +#endif + +#define DBG1(X1) MSG1("DEBUG: " X1) +#define DBG2(X1,X2) MSG2("DEBUG: " X1,X2) +#define DBG3(X1,X2,X3) MSG3("DEBUG: " X1,X2,X3) +#define DBG4(X1,X2,X3,X4) MSG4("DEBUG: " X1,X2,X3,X4) +#define DBG5(X1,X2,X3,X4,X5) MSG5("DEBUG: " X1,X2,X3,X4,X5) +#define DBG6(X1,X2,X3,X4,X5,X6) MSG6("DEBUG: " X1,X2,X3,X4,X5,X6) + +#define HINT1(X1) MSG1("HINT: " X1) +#define HINT2(X1,X2) MSG2("HINT: " X1,X2) +#define HINT3(X1,X2,X3) MSG3("HINT: " X1,X2,X3) +#define HINT4(X1,X2,X3,X4) MSG4("HINT: " X1,X2,X3,X4) +#define HINT5(X1,X2,X3,X4,X5) MSG5("HINT: " X1,X2,X3,X4,X5) +#define HINT6(X1,X2,X3,X4,X5,X6) MSG6("HINT: " X1,X2,X3,X4,X5,X6) + +#define NOTE1(X1) MSG1("NOTE: " X1) +#define NOTE2(X1,X2) MSG2("NOTE: " X1,X2) +#define NOTE3(X1,X2,X3) MSG3("NOTE: " X1,X2,X3) +#define NOTE4(X1,X2,X3,X4) MSG4("NOTE: " X1,X2,X3,X4) +#define NOTE5(X1,X2,X3,X4,X5) MSG5("NOTE: " X1,X2,X3,X4,X5) +#define NOTE6(X1,X2,X3,X4,X5,X6) MSG6("NOTE: " X1,X2,X3,X4,X5,X6) + +#define WARN1(X1) MSG1("WARN: " X1) +#define WARN2(X1,X2) MSG2("WARN: " X1,X2) +#define WARN3(X1,X2,X3) MSG3("WARN: " X1,X2,X3) +#define WARN4(X1,X2,X3,X4) MSG4("WARN: " X1,X2,X3,X4) +#define WARN5(X1,X2,X3,X4,X5) MSG5("WARN: " X1,X2,X3,X4,X5) +#define WARN6(X1,X2,X3,X4,X5,X6) MSG6("WARN: " X1,X2,X3,X4,X5,X6) + +#define FAIL1(X1) MSG1("FAIL: " X1) +#define FAIL2(X1,X2) MSG2("FAIL: " X1,X2) +#define FAIL3(X1,X2,X3) MSG3("FAIL: " X1,X2,X3) +#define FAIL4(X1,X2,X3,X4) MSG4("FAIL: " X1,X2,X3,X4) +#define FAIL5(X1,X2,X3,X4,X5) MSG5("FAIL: " X1,X2,X3,X4,X5) +#define FAIL6(X1,X2,X3,X4,X5,X6) MSG6("FAIL: " X1,X2,X3,X4,X5,X6) + + + +#ifdef DEBUG +_zzip_inline static void zzip_debug_xbuf (unsigned char* p, int l) + /* ZZIP_GNUC_UNUSED */ +{ +# define q(a) ((a&0x7F)<32?32:(a&0x7F)) + while (l > 0) + { + fprintf (stderr, + "%02x %02x %02x %02x " + "%02x %02x %02x %02x " + "%c%c%c%c %c%c%c%c\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + q(p[0]), q(p[1]), q(p[2]), q(p[3]), + q(p[4]), q(p[5]), q(p[6]), q(p[7])); + p += 8; l -= 8; + } +# undef q +} +#endif + +#endif diff --git a/tests/gating/build/__fnmatch.h b/tests/gating/build/__fnmatch.h new file mode 100644 index 0000000..90d36dc --- /dev/null +++ b/tests/gating/build/__fnmatch.h @@ -0,0 +1,32 @@ +#ifndef __ZZIP_INTERNAL_FNMATCH_H +#define __ZZIP_INTERNAL_FNMATCH_H +/** included by fseeko.c, mmapped.c, memdisk.c */ + +#include +#include +#include + +#ifdef ZZIP_HAVE_FNMATCH_H +#include +#endif + +#ifdef ZZIP_HAVE_FNMATCH_H +#define _zzip_fnmatch fnmatch +# ifdef FNM_CASEFOLD +# define _zzip_FNM_CASEFOLD FNM_CASEFOLD +# else +# define _zzip_FNM_CASEFOLD 0 +# endif +#else +# define _zzip_FNM_CASEFOLD 0 +/* if your system does not have fnmatch, we fall back to strcmp: */ +static int _zzip_fnmatch(char* pattern, char* string, int flags) +{ +# ifdef DBG2 + DBG1(""); +# endif + return strcmp (pattern, string); +} +#endif + +#endif diff --git a/tests/gating/build/__hints.h b/tests/gating/build/__hints.h new file mode 100644 index 0000000..1d2eef0 --- /dev/null +++ b/tests/gating/build/__hints.h @@ -0,0 +1,195 @@ +#ifndef __ZZIP_INTERNAL_HINTS_H +#define __ZZIP_INTERNAL_HINTS_H +#include + +#ifndef ZZIP_GNUC_ATLEAST +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define ZZIP_GNUC_ATLEAST(_M_,_N_) \ + ((__GNUC__ << 10) + __GNUC_MINOR__ >= ((_M_) << 10) + (_N_)) +# elif defined __GNUC__ +# define ZZIP_GNUC_ATLEAST(_M_,_N_) \ + ((__GNUC__ << 10) >= ((_M_) << 10)) +# else +# define ZZIP_GNUC_ATLEAST(_M_, _N_) 0 +# endif +#endif + +#ifndef ZZIP_GNUC_EXTENSION +# if ZZIP_GNUC_ATLEAST(2,8) +# define ZZIP_GNUC_EXTENSION __extension__ +# else +# define ZZIP_GNUC_EXTENSION +# endif +#endif + +/* func has no side effects, return value depends only on params and globals */ +#ifndef ZZIP_GNUC_PURE +# if ZZIP_GNUC_ATLEAST(2,8) +# define ZZIP_GNUC_PURE __attribute__((__pure__)) +# else +# define ZZIP_GNUC_PURE +# endif +#endif + +/* func has no side effects, return value depends only on params */ +#ifndef ZZIP_GNUC_CONST +# if ZZIP_GNUC_ATLEAST(2,4) +# define ZZIP_GNUC_CONST __attribute__((__const__)) +# else +# define ZZIP_GNUC_CONST +# endif +#endif + +/* typename / variable / function possibly unused */ +#ifndef ZZIP_GNUC_UNUSED +# if ZZIP_GNUC_ATLEAST(2,4) +# define ZZIP_GNUC_UNUSED __attribute__((__unused__)) +# else +# define ZZIP_GNUC_UNUSED +# endif +#endif + +/* obvious. btw, a noreturn-func should return void */ +#ifndef ZZIP_GNUC_NORETURN +# if ZZIP_GNUC_ATLEAST(2,5) +# define ZZIP_GNUC_NORETURN __attribute__((__noreturn__)) +# else +# define ZZIP_GNUC_NORETURN +# endif +#endif + +/* omit function from profiling with -finstrument-functions */ +#ifndef ZZIP_GNUC_NO_INSTRUMENT +# if ZZIP_GNUC_ATLEAST(2,4) +# define ZZIP_GNUC_NO_INSTRUMENT __attribute__((__no_instrument_function__)) +# else +# define ZZIP_GNUC_NO_INSTRUMENT +# endif +#endif + +/* all pointer args must not be null, and allow optimiztons based on the fact*/ +#ifndef ZZIP_GNUC_NONNULL +# if ZZIP_GNUC_ATLEAST(3,1) +# define ZZIP_GNUC_NONNULL __attribute__((nonnull)) +# else +# define ZZIP_GNUC_NONNULL +# endif +#endif + +/* the function can not throw - the libc function are usually nothrow */ +#ifndef ZZIP_GNUC_NOTHROW +# if ZZIP_GNUC_ATLEAST(3,2) +# define ZZIP_GNUC_NOTHROW __attribute__((nothrow)) +# else +# define ZZIP_GNUC_NOTHROW +# endif +#endif + +/* typename / function / variable is obsolete but still listed in headers */ +#ifndef ZZIP_GNUC_DEPRECATED +# if ZZIP_GNUC_ATLEAST(3,1) +# define ZZIP_GNUC_DEPRECATED __attribute__((deprecated)) +# else +# define ZZIP_GNUC_DEPRECATED +# endif +#endif + +/* resolve references to this function during pre-linking the library */ +#ifndef ZZIP_GNUC_LIB_PROTECTED +# if ZZIP_GNUC_ATLEAST(3,1) +# define ZZIP_GNUC_LIB_PROTECTED __attribute__((visiblity("protected"))) +# else +# define ZZIP_GNUC_LIB_PROTECTED +# endif +#endif + +/* func shall only be usable within the same lib (so, no entry in lib symtab)*/ +#ifndef ZZIP_GNUC_LIB_PRIVATE +# if ZZIP_GNUC_ATLEAST(3,1) +# define ZZIP_GNUC_LIB_PRIVATE __attribute__((visiblity("hidden"))) +# else +# define ZZIP_GNUC_LIB_PRIVATE +# endif +#endif + +/* ... and not even passed as a function pointer reference to outside the lib*/ +#ifndef ZZIP_GNUC_LIB_INTERNAL +# if ZZIP_GNUC_ATLEAST(3,1) +# define ZZIP_GNUC_LIB_INTERNAL __attribute__((visiblity("internal"))) +# else +# define ZZIP_GNUC_LIB_INTERNAL +# endif +#endif + + +#ifndef ZZIP_GNUC_FORMAT +# if ZZIP_GNUC_ATLEAST(2,4) +# define ZZIP_GNUC_FORMAT(_X_) __attribute__((__format_arg__(_X_))) +# else +# define ZZIP_GNUC_FORMAT(_X_) +# endif +#endif + +#ifndef ZZIP_GNUC_SCANF +# if ZZIP_GNUC_ATLEAST(2,4) +# define ZZIP_GNUC_SCANF(_S_,_X_) __attribute__((__scanf__(_S_,_X_))) +# else +# define ZZIP_GNUC_SCANF(_S_,_X_) +# endif +#endif + +#ifndef ZZIP_GNUC_PRINTF +# if ZZIP_GNUC_ATLEAST(2,4) +# define ZZIP_GNUC_PRINTF(_S_,_X_) __attribute__((__printf__(_S_,_X_))) +# else +# define ZZIP_GNUC_PRINTF(_S_,_X_) +# endif +#endif + +#ifdef __GNUC__ +#define ZZIP_GNUC_PACKED __attribute__((packed)) +#else +#define ZZIP_GNUC_PACKED +#endif + +#ifndef ZZIP_FUNCTION +# if ZZIP_GNUC_ATLEAST(2,6) +# define ZZIP_FUNC __FUNCTION__ +# define ZZIP_FUNCTION __FUNCTION__ +# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define ZZIP_FUNC __func__ +# define ZZIP_FUNCTION "" +# else +# define ZZIP_FUNC 0 +# define ZZIP_FUNCTION "" +# endif +#endif + +#ifndef ZZIP_STRING +#define ZZIP_STRING(_X_) ZZIP_STRING_(_X_) +#define ZZIP_STRING_(_Y_) #_Y_ +#endif + +#ifndef ZZIP_DIM +#define ZZIP_DIM(_A_) (sizeof(_A_) / sizeof ((_A_)[0])) +#endif + +#if !(defined ZZIP_FOR1 && defined ZZIP_END1) +# if defined sun || defined __sun__ +# define ZZIP_FOR1 if (1) +# define ZZIP_END1 else (void)0 +# else +# define ZZIP_FOR1 do +# define ZZIP_END1 while (0) +# endif +#endif + +#ifndef ZZIP_BRANCH_OVER +# if ZZIP_GNUC_ATLEAST(2,96) +# define ZZIP_BRANCH_OVER(_X_) __builtin_expect((_X_),0) +# else +# define ZZIP_BRANCH_OVER(_X_) (_X_) +# endif +#endif + +#endif diff --git a/tests/gating/build/__mkdir.h b/tests/gating/build/__mkdir.h new file mode 100644 index 0000000..c1bffa4 --- /dev/null +++ b/tests/gating/build/__mkdir.h @@ -0,0 +1,12 @@ +#ifndef __ZZIP_INTERNAL_MKDIR_H +#define __ZZIP_INTERNAL_MKDIR_H + +#include + +# ifdef ZZIP_HAVE_DIRECT_H +# define _zzip_mkdir(a,b) mkdir(a) +# else +# define _zzip_mkdir mkdir +# endif + +#endif diff --git a/tests/gating/build/__string.h b/tests/gating/build/__string.h new file mode 100644 index 0000000..351b0c1 --- /dev/null +++ b/tests/gating/build/__string.h @@ -0,0 +1,67 @@ +#ifndef __ZZIP_INTERNAL_STRING_H +#define __ZZIP_INTERNAL_STRING_H + +#ifdef __linux__ +#define _GNU_SOURCE _glibc_developers_are_idiots_to_call_strndup_gnu_specific_ +#endif + +#include + +#if defined ZZIP_HAVE_STRING_H +#include +#elif defined ZZIP_HAVE_STRINGS_H +#include +#endif + + +#if defined ZZIP_HAVE_STRNDUP || defined strndup +#define _zzip_strndup strndup +#else + +/* if your system does not have strndup: */ +zzip__new__ static char * +_zzip_strndup(char const *p, size_t maxlen) +{ + if (p == NULL) + { + return p; + } else + { + size_t len = strnlen(p, maxlen); + char* r = malloc(len + 1); + if (r == NULL) + return NULL; /* errno = ENOMEM */ + r[len] = '\0'; + return memcpy(r, p, len); + } +} +#endif + +#if defined ZZIP_HAVE_STRCASECMP || defined strcasecmp +#define _zzip_strcasecmp strcasecmp +#else + +/* if your system does not have strcasecmp: */ +static int +_zzip_strcasecmp(char *__zzip_restrict a, char *_zzip_restrict b) +{ + if (! a) + return (b) ? 1 : 0; + if (! b) + return -1; + while (1) + { + int v = tolower(*a) - tolower(*b); + if (v) + return v; + if (! *a) + return 1; + if (! *b) + return -1; + a++; + b++; + } +} +#endif + +#endif diff --git a/tests/gating/build/test.sh b/tests/gating/build/test.sh new file mode 100755 index 0000000..baef724 --- /dev/null +++ b/tests/gating/build/test.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +(gcc unzzip.c unzzipcat-zip.c unzzipdir-mix.c -lzzip -o foo && ./foo) || exit 1 +rm ./foo +exit 0 diff --git a/tests/gating/build/unzzip-states.h b/tests/gating/build/unzzip-states.h new file mode 100644 index 0000000..55ea8c0 --- /dev/null +++ b/tests/gating/build/unzzip-states.h @@ -0,0 +1,24 @@ +#ifndef UNZZIP_STATES_H +#define UNZZIP_STATES_H + +/* DIAGNOSTICS according to the unzip(1) manpage */ + +#define EXIT_OK 0 +#define EXIT_WARNINGS 1 +#define EXIT_ERRORS 2 +#define EXIT_FILEFORMAT 3 +#define EXIT_ENOMEM 4 +#define EXIT_ENOTTY_FOR_PASSWORD 5 +#define EXIT_ENOMEM_ZIP_TO_DISK 6 +#define EXIT_ENOMEM_ZIP_TO_MEM 7 +#define EXIT_ZIP_NOT_FOUND 9 +#define EXIT_INVALID_OPTION 10 +#define EXIT_FILE_NOT_FOUND 11 +#define EXIT_DISKFULL 50 +#define EXIT_EARLY_END_OF_FILE 51 +#define EXIT_SIGTERM 80 +#define EXIT_UNSUPPORTED_COMPRESSION 81 +#define EXIT_WRONG_PASSWORD 82 + +#endif + diff --git a/tests/gating/build/unzzip.c b/tests/gating/build/unzzip.c new file mode 100644 index 0000000..f91c5eb --- /dev/null +++ b/tests/gating/build/unzzip.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003 Guido Draheim + * Use freely under the restrictions of the ZLIB license. + * + * This file is used as an example to clarify zzip api usage. + */ + +#include +#include +#include +#include "unzzipcat-zip.h" +#include "unzzipdir-zip.h" +#include "unzzip-states.h" + +static const char usage[] = +{ + "unzzip .. \n" + " - unzzip the files contained in a zip archive.\n" + " -p print content of files to pipe\n" + " -l list names in archive (short format)\n" +}; + +static int unzzip_version(void) +{ + printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n"); + return 0; +} + +static int unzzip_help(void) +{ + printf (usage); + return 0; +} + +int +main (int argc, char ** argv) +{ + int argn; + int exitcode = 0; + zzip_error_t error; + + if (argc <= 1 || ! strcmp (argv[1], "--help")) + { + return unzzip_help(); + } + if (! strcmp (argv[1], "--version")) + { + return unzzip_version(); + } + if (! strcmp (argv[1], "-l") || ! strcmp(argv[1], "--list")) + { + argc -= 1; argv += 1; + return unzzip_show_list(argc, argv); + } + if (! strcmp (argv[1], "-v") || ! strcmp(argv[1], "--versions")) + { + if (argc == 2) + return unzzip_version(); /* compatible with info-zip */ + argc -= 1; argv += 1; + return unzzip_long_list(argc, argv); + } + if (! strcmp (argv[1], "-p") || ! strcmp(argv[1], "--pipe")) + { + argc -= 1; argv += 1; + return unzzip_print(argc, argv); + } + + if (! strcmp (argv[1], "-")) + { + fprintf(stderr, "unknown option %s", argv[1]); + return EXIT_INVALID_OPTION; + } + + return unzzip_extract(argc, argv); +} + +/* + * Local variables: + * c-file-style: "stroustrup" + * End: + */ diff --git a/tests/gating/build/unzzipcat-zip.c b/tests/gating/build/unzzipcat-zip.c new file mode 100644 index 0000000..0f0b1d5 --- /dev/null +++ b/tests/gating/build/unzzipcat-zip.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2003 Guido Draheim + * Use freely under the restrictions of the ZLIB license. + * + * This file is used as an example to clarify zzip api usage. + */ + +#include +#include +#include +#include +#include +#include "__mkdir.h" +#include "__string.h" +#include "__fnmatch.h" +#include "__debug.h" +#include "unzzipcat-zip.h" +#include "unzzip-states.h" + +#ifdef ZZIP_HAVE_UNISTD_H +#include +#endif +#ifdef ZZIP_HAVE_IO_H +#include +#endif + +static int exitcode(int e) +{ + switch (e) + { + case ZZIP_NO_ERROR: + return EXIT_OK; + case ZZIP_OUTOFMEM: /* out of memory */ + return EXIT_ENOMEM; + case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */ + return EXIT_ZIP_NOT_FOUND; + case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */ + case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */ + case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */ + case ZZIP_DIR_TOO_SHORT: + case ZZIP_DIR_EDH_MISSING: + return EXIT_FILEFORMAT; + case ZZIP_DIRSIZE: + return EXIT_EARLY_END_OF_FILE; + case ZZIP_ENOENT: + return EXIT_FILE_NOT_FOUND; + case ZZIP_UNSUPP_COMPR: + return EXIT_UNSUPPORTED_COMPRESSION; + case ZZIP_CORRUPTED: + case ZZIP_UNDEF: + case ZZIP_DIR_LARGEFILE: + return EXIT_FILEFORMAT; + } + return EXIT_ERRORS; +} + +static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out) +{ + ZZIP_FILE* file = zzip_file_open (disk, name, 0); + if (file) + { + char buffer[1024]; int len; + while ((len = zzip_file_read (file, buffer, 1024))) + { + fwrite (buffer, 1, len, out); + } + + zzip_file_close (file); + } +} + +/* + * NAME: remove_dotdotslash + * PURPOSE: To remove any "../" components from the given pathname + * ARGUMENTS: path: path name with maybe "../" components + * RETURNS: Nothing, "path" is modified in-place + * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it! + * Also, "path" is not used after creating it. + * So modifying "path" in-place is safe to do. + */ +static inline void +remove_dotdotslash(char *path) +{ + /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */ + char *dotdotslash; + int warned = 0; + + dotdotslash = path; + while ((dotdotslash = strstr(dotdotslash, "../")) != NULL) + { + /* + * Remove only if at the beginning of the pathname ("../path/name") + * or when preceded by a slash ("path/../name"), + * otherwise not ("path../name..")! + */ + if (dotdotslash == path || dotdotslash[-1] == '/') + { + char *src, *dst; + if (!warned) + { + /* Note: the first time through the pathname is still intact */ + fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path); + warned = 1; + } + /* We cannot use strcpy(), as there "The strings may not overlap" */ + for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++) + ; + } + else + dotdotslash +=3; /* skip this instance to prevent infinite loop */ + } +} + +static void makedirs(const char* name) +{ + char* p = strrchr(name, '/'); + if (p) { + char* dir_name = _zzip_strndup(name, p-name); + makedirs(dir_name); + free (dir_name); + } + if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST) + { + DBG3("while mkdir %s : %s", name, strerror(errno)); + } + errno = 0; +} + +static FILE* create_fopen(char* name, char* mode, int subdirs) +{ + char *name_stripped; + FILE *fp; + int mustfree = 0; + + if ((name_stripped = strdup(name)) != NULL) + { + remove_dotdotslash(name_stripped); + name = name_stripped; + mustfree = 1; + } + if (subdirs) + { + char* p = strrchr(name, '/'); + if (p) { + char* dir_name = _zzip_strndup(name, p-name); + makedirs(dir_name); + free (dir_name); + } + } + fp = fopen(name, mode); + if (mustfree) + free(name_stripped); + return fp; +} + +static int unzzip_cat (int argc, char ** argv, int extract) +{ + int done = 0; + int argn; + ZZIP_DIR* disk; + zzip_error_t error; + + if (argc == 1) + { + printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n"); + return EXIT_OK; /* better provide an archive argument */ + } + + disk = zzip_dir_open (argv[1], &error); + if (! disk) { + fprintf(stderr, "%s: %s\n", argv[1], zzip_strerror(error)); + return exitcode(error); + } + + if (argc == 2) + { /* list all */ + ZZIP_DIRENT entry; + while(zzip_dir_read(disk, &entry)) + { + char* name = entry.d_name; + FILE* out = stdout; + if (extract) out = create_fopen(name, "w", 1); + if (! out) { + DBG3("fopen' %s : %s", name, strerror(errno)); + if (errno != EISDIR) done = EXIT_ERRORS; + continue; + } + unzzip_cat_file (disk, name, out); + if (extract) fclose(out); + } + } + else + { /* list only the matching entries - in order of zip directory */ + ZZIP_DIRENT entry; + while(zzip_dir_read(disk, &entry)) + { + char* name = entry.d_name; + for (argn=1; argn < argc; argn++) + { + if (! _zzip_fnmatch (argv[argn], name, + FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) + { + FILE* out = stdout; + if (extract) out = create_fopen(name, "w", 1); + if (! out) { + DBG3("fopen. %s : %s", name, strerror(errno)); + if (errno != EISDIR) done = EXIT_ERRORS; + continue; + } + unzzip_cat_file (disk, name, out); + if (extract) fclose(out); + break; /* match loop */ + } + } + } + } + zzip_dir_close(disk); + return done; +} + +int unzzip_print (int argc, char ** argv) +{ + return unzzip_cat(argc, argv, 0); +} + +int unzzip_extract (int argc, char ** argv) +{ + return unzzip_cat(argc, argv, 1); +} + +/* + * Local variables: + * c-file-style: "stroustrup" + * End: + */ diff --git a/tests/gating/build/unzzipcat-zip.h b/tests/gating/build/unzzipcat-zip.h new file mode 100644 index 0000000..cba2a40 --- /dev/null +++ b/tests/gating/build/unzzipcat-zip.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2003 Guido Draheim + * Use freely under the restrictions of the ZLIB license. + * + * This file is used as an example to clarify zzip api usage. + */ + +extern int unzzip_print(int argc, char** argv); +extern int unzzip_extract(int argc, char** argv); + diff --git a/tests/gating/build/unzzipdir-mix.c b/tests/gating/build/unzzipdir-mix.c new file mode 100644 index 0000000..140410e --- /dev/null +++ b/tests/gating/build/unzzipdir-mix.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2003 Guido Draheim + * Use freely under the restrictions of the ZLIB license. + * + * This file is used as an example to clarify zzip api usage. + */ + +#include +#include "__debug.h" +#include +#include +#include +#include "unzzipdir-zip.h" +#include "unzzip-states.h" + +#ifdef ZZIP_HAVE_UNISTD_H +#include +#endif +#ifdef ZZIP_HAVE_IO_H +#include +#endif + +#ifdef ZZIP_HAVE_FNMATCH_H +#include +#else +#define fnmatch(x,y,z) strcmp(x,y) +#endif + +static const char* comprlevel[] = { + "stored", "shrunk", "redu:1", "redu:2", "redu:3", "redu:4", + "impl:N", "toknze", "defl:N", "defl:B", "impl:B" }; + +static int exitcode(int e) +{ + switch (e) + { + case ZZIP_NO_ERROR: + return EXIT_OK; + case ZZIP_OUTOFMEM: /* out of memory */ + return EXIT_ENOMEM; + case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */ + return EXIT_ZIP_NOT_FOUND; + case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */ + case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */ + case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */ + case ZZIP_DIR_TOO_SHORT: + case ZZIP_DIR_EDH_MISSING: + return EXIT_FILEFORMAT; + case ZZIP_DIRSIZE: + return EXIT_EARLY_END_OF_FILE; + case ZZIP_ENOENT: + return EXIT_FILE_NOT_FOUND; + case ZZIP_UNSUPP_COMPR: + return EXIT_UNSUPPORTED_COMPRESSION; + case ZZIP_CORRUPTED: + case ZZIP_UNDEF: + case ZZIP_DIR_LARGEFILE: + return EXIT_FILEFORMAT; + } + return EXIT_ERRORS; +} + +static int +unzzip_list (int argc, char ** argv, int verbose) +{ + int argn; + ZZIP_DIR* disk; + + if (argc == 1) + { + printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n"); + return EXIT_OK; /* better provide an archive argument */ + } + + disk = zzip_opendir (argv[1]); + if (! disk) { + DBG3("opendir failed [%i] %s", errno, strerror(errno)); + perror(argv[1]); + return exitcode(errno); + } + + if (argc == 2) + { /* list all */ + ZZIP_DIRENT* entry = 0; + while((entry = zzip_readdir(disk))) + { + char* name = entry->d_name; + long long usize = entry->st_size; + if (!verbose) + { + printf ("%22lli %s\n", usize, name); + } else + { + long long csize = entry->d_csize; + unsigned compr = entry->d_compr; + const char* defl = (compr < sizeof(comprlevel)) ? comprlevel[compr] : "(redu)"; + printf ("%lli/%lli %s %s\n", usize, csize, defl, name); + } + } + DBG2("readdir done %s", strerror(errno)); + } + else + { /* list only the matching entries - in order of zip directory */ + ZZIP_DIRENT* entry = 0; + while((entry = zzip_readdir(disk))) + { + char* name = entry->d_name; + for (argn=1; argn < argc; argn++) + { + if (! fnmatch (argv[argn], name, + FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) + { + long long usize = entry->st_size; + if (!verbose) + { + printf ("%22lli %s\n", usize, name); + } else + { + long long csize = entry->d_csize; + unsigned compr = entry->d_compr; + const char* defl = (compr < sizeof(comprlevel)) ? comprlevel[compr] : "(redu)"; + printf ("%lli/%lli %s %s\n", usize, csize, defl, name); + } + break; /* match loop */ + } + } + } + DBG2("readdir done %s", strerror(errno)); + } + zzip_closedir(disk); + return 0; +} + +int +unzzip_long_list (int argc, char ** argv) +{ + return unzzip_list(argc, argv, 1); +} + +int +unzzip_show_list (int argc, char ** argv) +{ + return unzzip_list(argc, argv, 0); +} + +/* + * Local variables: + * c-file-style: "stroustrup" + * End: + */ diff --git a/tests/gating/build/unzzipdir-zip.h b/tests/gating/build/unzzipdir-zip.h new file mode 100644 index 0000000..683c138 --- /dev/null +++ b/tests/gating/build/unzzipdir-zip.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2003 Guido Draheim + * Use freely under the restrictions of the ZLIB license. + * + * This file is used as an example to clarify zzip api usage. + */ + +extern int unzzip_show_list(int argc, char** argv); +extern int unzzip_long_list(int argc, char** argv); + diff --git a/tests/tests.yml b/tests/tests.yml new file mode 100644 index 0000000..4dee648 --- /dev/null +++ b/tests/tests.yml @@ -0,0 +1,21 @@ +--- +- hosts: localhost + vars: + - artifacts: ./artifacts + remote_user: root + roles: + - role: standard-test-basic + tags: + - atomic + - classic + - container + tests: + - simple: + dir: gating + run: ./all.sh + required_packages: + - zziplib + - zziplib-devel + - zziplib-utils + - coreutils + - gcc diff --git a/zziplib.spec b/zziplib.spec index 10c3415..cc6eac0 100644 --- a/zziplib.spec +++ b/zziplib.spec @@ -1,7 +1,7 @@ Summary: Lightweight library to easily extract data from zip files Name: zziplib Version: 0.13.68 -Release: 11%{?dist} +Release: 12%{?dist} License: LGPLv2+ or MPLv1.1 Group: Applications/Archiving URL: http://zziplib.sourceforge.net/ @@ -147,6 +147,10 @@ make install DESTDIR=%{buildroot} %{_mandir}/man3/* %changelog +* Tue Feb 06 2024 Jakub Martisko - 0.13.68-12 +- Add the gating tests from the 8.8.0 branch + Resolves: RHEL-24429 + * Sat Jan 27 2024 Jakub Martisko - 0.13.68-11 - Use %__python3 macro during the config phase (used for doc generation) Resolves: RHEL-22880