Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qpress for openSUSE:Factory checked 
in at 2026-09-12 21:21:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qpress (Old)
 and      /work/SRC/openSUSE:Factory/.qpress.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qpress"

Sat Sep 12 21:21:56 2026 rev:10 rq:1377549 version:20260802

Changes:
--------
--- /work/SRC/openSUSE:Factory/qpress/qpress.changes    2025-02-21 
21:37:36.775349512 +0100
+++ /work/SRC/openSUSE:Factory/.qpress.new.1265/qpress.changes  2026-09-12 
21:25:50.887771113 +0200
@@ -1,0 +2,16 @@
+Sat Sep 12 14:22:12 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 20260802:
+  * fixes for crafted-archive memory safety issues: path traversal
+    via bare ".." entries, heap overflows from unchecked QLZ block
+    sizes, strcpy overflow of destination buffer, NAME_BUFFER_SIZE
+    check bypass
+  * memory leak fix in parse_flags, performance fix for -P1 on
+    Windows, FreeBSD build fix
+  * makefile reworked for packagers: DESTDIR support, overridable
+    PREFIX/CXX/CXXFLAGS/LDFLAGS; spec now passes optflags and
+    installs with DESTDIR; PGO feedback build fixed to actually
+    recompile and to not re-instrument the final binary
+  * CI moved to GitHub Actions with Windows build, CircleCI dropped
+
+-------------------------------------------------------------------

Old:
----
  qpress-20230507.tar.gz

New:
----
  qpress-20260802.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qpress.spec ++++++
--- /var/tmp/diff_new_pack.1OOLf5/_old  2026-09-12 21:25:51.345790336 +0200
+++ /var/tmp/diff_new_pack.1OOLf5/_new  2026-09-12 21:25:51.346790378 +0200
@@ -2,7 +2,7 @@
 # spec file for package qpress
 #
 # Copyright (c) 2025 Andreas Stieger <[email protected]>
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,11 +18,10 @@
 
 
 Name:           qpress
-Version:        20230507
+Version:        20260802
 Release:        0
 Summary:        File archiver designed for speed
 License:        GPL-1.0-only AND GPL-2.0-only AND GPL-3.0-only
-Group:          Productivity/Archiving/Compression
 URL:            https://github.com/PierreLvx/qpress
 Source0:        
https://github.com/PierreLvx/qpress/archive/refs/tags/%{version}.tar.gz#/%{name}-%{version}.tar.gz
 BuildRequires:  c++_compiler
@@ -45,18 +44,20 @@
 %autosetup -p1
 
 %build
-export CFLAGS="%{optflags}"
+export CXXFLAGS="%{optflags}"
 %if %{do_profiling}
-  %make_build CFLAGS="$CFLAGS %{cflags_profile_generate}" 
LDFLAGS="-fprofile-arcs"
+  %make_build CXXFLAGS="$CXXFLAGS %{cflags_profile_generate}" 
LDFLAGS="-fprofile-arcs"
   ./qpress -o *.cpp | ./qpress -dio > /dev/null
-  %make_build CFLAGS="$CFLAGS %{cflags_profile_feedback}" 
LDFLAGS="-fprofile-arcs"
+  # force feedback rebuild: single-target makefile sees qpress as up to date
+  rm -f qpress
+  # no LDFLAGS here: -fprofile-arcs would re-instrument the final binary
+  %make_build CXXFLAGS="$CXXFLAGS %{cflags_profile_feedback}"
 %else
-  %make_build
+  %make_build CXXFLAGS="%{optflags}"
 %endif
 
 %install
-mkdir -p %{buildroot}/usr/bin
-%make_install PREFIX=%{buildroot}/usr
+%make_install PREFIX=%{_prefix}
 
 %files
 %license LICENSE.GPL-1.0

++++++ qpress-20230507.tar.gz -> qpress-20260802.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/.circleci/config.yml 
new/qpress-20260802/.circleci/config.yml
--- old/qpress-20230507/.circleci/config.yml    2023-05-07 23:02:14.000000000 
+0200
+++ new/qpress-20260802/.circleci/config.yml    1970-01-01 01:00:00.000000000 
+0100
@@ -1,52 +0,0 @@
-version: 2.1
-
-jobs:
-  build-macos:
-    parameters:
-      xcode_version:
-        type: string
-    macos:
-      xcode: << parameters.xcode_version >>
-    steps:
-      - checkout
-      - run:
-          name: Makefile
-          command: make
-      - run:
-          name: Test executable
-          command: ./qpress -v readme.md readme.qp
-
-  build-linux:
-    parameters:
-      image:
-        type: string
-    machine:
-      image: << parameters.image >>
-    steps:
-      - checkout
-      - run:
-          name: Makefile
-          command: make
-      - run:
-          name: Test executable
-          command: ./qpress -v readme.md readme.qp
-
-workflows:
-  test-macos:
-    jobs:
-      - build-macos:
-          matrix:
-            parameters:
-              xcode_version: [
-                14.2.0,   # macOS 12.6
-                14.1.0,   # macOS 12.5.1
-                13.4.1,   # macOS 12.3.1
-                13.2.1,   # macOS 11.6.2
-                11.7.0    # macOS 10.15.5
-                ]
-  test-linux:
-    jobs:
-      - build-linux:
-          matrix:
-            parameters:
-              image: [ubuntu-2204:current, ubuntu-2004:current]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/.github/workflows/build.yml 
new/qpress-20260802/.github/workflows/build.yml
--- old/qpress-20230507/.github/workflows/build.yml     1970-01-01 
01:00:00.000000000 +0100
+++ new/qpress-20260802/.github/workflows/build.yml     2026-08-02 
14:23:57.000000000 +0200
@@ -0,0 +1,56 @@
+name: Build
+
+on:
+  push:
+  pull_request:
+
+jobs:
+  build-macos:
+    strategy:
+      matrix:
+        os:
+          - macos-14
+          - macos-15
+          - macos-26
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Build
+        run: make
+      - name: Test
+        run: ./qpress -v readme.md readme.qp
+
+  build-linux:
+    strategy:
+      matrix:
+        os:
+          - ubuntu-22.04
+          - ubuntu-24.04
+          - ubuntu-26.04
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Build
+        run: make
+      - name: Test
+        run: ./qpress -v readme.md readme.qp
+
+  build-windows:
+    strategy:
+      matrix:
+        os:
+          - windows-2022
+          - windows-2025
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v4
+      - uses: msys2/setup-msys2@v2
+        with:
+          msystem: MINGW64
+          install: mingw-w64-x86_64-gcc make
+      - name: Build
+        shell: msys2 {0}
+        run: g++ -O3 -o qpress.exe -x c quicklz.c -x c++ qpress.cpp aio.cpp 
utilities.cpp dirent_win.c -lpthread -Wall -Wextra -Werror
+      - name: Test
+        shell: msys2 {0}
+        run: ./qpress.exe -v readme.md readme.qp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/aio.cpp new/qpress-20260802/aio.cpp
--- old/qpress-20230507/aio.cpp 2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/aio.cpp 2026-08-02 14:23:57.000000000 +0200
@@ -22,19 +22,21 @@
 //#define PRE_ALLOCATE
 
 #include "aio.hpp"
-#include "utilities.hpp"
-
-#include <stdio.h>
 
-#define _CRT_SECURE_NO_WARNINGS
-
-#ifdef WINDOWS
+// windows.h must be included before utilities.hpp pulls in <string> ("using 
namespace std")
+// - otherwise the plain "byte" typedefs used internally by windows.h's RPC 
headers become
+// ambiguous with std::byte.
+#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
     #define handle_type HANDLE
     #include <windows.h>
 #else
     #define handle_type FILE *
 #endif
 
+#include "utilities.hpp"
+
+#include <stdio.h>
+
 static size_t largest_request_pub;
 static bool buffering = true;
 
@@ -246,7 +248,7 @@
         size_t n;
 
         if(size > largest_request_pub)
-            abort("Internal error, aread(%d) with largest_request == %d", 
(int)size, (int)largest_request_pub);
+            abort("Internal error, awrite(%d) with largest_request == %d", 
(int)size, (int)largest_request_pub);
 
         memcpy(write_buffer + queued, src, size);
         queued += size;
@@ -321,6 +323,12 @@
 
 bool aopen_write(const char *file)
 {
+    // destination_file is a fixed-size buffer; a path this long would 
overflow it.
+    // Fail here so the caller (try_aopen) reports a clean "error creating 
file"
+    // instead of strcpy() writing past the end of the buffer.
+    if(strlen(file) >= sizeof(destination_file))
+        return false;
+
     strcpy(destination_file, file);
     written = 0;
     last_extended_to = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/dirent_win.c 
new/qpress-20260802/dirent_win.c
--- old/qpress-20230507/dirent_win.c    2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/dirent_win.c    2026-08-02 14:23:57.000000000 +0200
@@ -169,7 +169,7 @@
   static WIN32_FIND_DATA fData;
   char search[1024];
   memset(search, 0, 1024);
-  strncpy(search, dir->szDirName, strlen(dir->szDirName) - 1);
+  memcpy(search, dir->szDirName, strlen(dir->szDirName) - 1);
   strcat(search, wildcard);
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/makefile new/qpress-20260802/makefile
--- old/qpress-20230507/makefile        2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/makefile        2026-08-02 14:23:57.000000000 +0200
@@ -1,9 +1,22 @@
-PREFIX = /usr/local
+DESTDIR ?=
+PREFIX ?= /usr/local
+CXX ?= g++
+CXXFLAGS ?= -O3
+CXXFLAGS += -Wall -Wextra -Werror
+LDFLAGS ?=
 
-g++:   qpress.cpp aio.cpp quicklz.c utilities.cpp
-       g++ -O3 -o qpress -x c quicklz.c -x c++ qpress.cpp aio.cpp 
utilities.cpp -lpthread -Wall -Wextra -Werror
+all: qpress
+
+qpress:        qpress.cpp aio.cpp quicklz.c utilities.cpp
+       $(CXX) $(CXXFLAGS) -o qpress -x c quicklz.c -x c++ qpress.cpp aio.cpp 
utilities.cpp -lpthread $(LDFLAGS)
 
 install: qpress
-       install -m 0755 qpress $(PREFIX)/bin
+       install -d $(DESTDIR)$(PREFIX)/bin
+       install -m 0755 qpress $(DESTDIR)$(PREFIX)/bin
+
+clean:
+       rm -f qpress
+
+g++: qpress
 
-.PHONY: install g++
+.PHONY: all clean install g++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/qpress.cpp 
new/qpress-20260802/qpress.cpp
--- old/qpress-20230507/qpress.cpp      2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/qpress.cpp      2026-08-02 14:23:57.000000000 +0200
@@ -89,23 +89,29 @@
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <stdio.h>
+
+// windows.h must be included before <string>/<vector> pull in std::byte (via 
<cstddef>) and
+// "using namespace std" below - otherwise the plain "byte" typedefs used 
internally by
+// windows.h's RPC headers become ambiguous with std::byte.
+#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
+  #include <fcntl.h>
+  #include <time.h>
+  #include <windows.h>
+  #include <io.h>
+#endif
+
 #include "aio.hpp"
 #include <stdarg.h>
 #include <string>
+#include <vector>
 #include "levels.c"
 #include "utilities.hpp"
 
-#if defined(__APPLE__) || defined(__linux__)
+#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
     #include <unistd.h>
 #endif
 
-using namespace std;
-
 #ifdef WINDOWS
-  #include <fcntl.h>
-  #include <time.h>
-  #include <windows.h>
-  #include <io.h>
   #include "dirent_win.h"
   #include "pthread.h"
 #else
@@ -113,6 +119,8 @@
   #include <pthread.h>
 #endif
 
+using namespace std;
+
 #if QLZ_STREAMING_BUFFER != 0
 #error QLZ_STREAMING_BUFFER must be 0
 #endif
@@ -125,6 +133,9 @@
        #ifndef PROCESS_MODE_BACKGROUND_BEGIN
            #define PROCESS_MODE_BACKGROUND_BEGIN   0x00100000
     #endif
+       #ifndef THREAD_MODE_BACKGROUND_BEGIN
+           #define THREAD_MODE_BACKGROUND_BEGIN    0x00010000
+    #endif
 #else
        #define CURDIR "./"
     #define DELIM_STR "/"
@@ -146,6 +157,11 @@
 bool decompress_flag = false;
 bool recover_flag = false;
 bool benchmark_flag = false;
+// -P1: THREAD_MODE_BACKGROUND_BEGIN is applied per-thread rather than via the 
process-wide
+// PROCESS_MODE_BACKGROUND_BEGIN, which caps the whole process's working set 
at ~32 MiB and can
+// slow down compression/decompression by 250x-800x once that cap is exceeded 
(see qpress issue #13
+// and 
https://randomascii.wordpress.com/2023/10/01/32-mib-working-sets-on-a-64-gib-machine/)
+bool background_priority_flag = false;
 unsigned long long compress_chunk_size = DEFAULT_COMPRESS_CHUNK_SIZE;
 unsigned int compression_level = DEFAULT_COMPRESSION_LEVEL;
 unsigned int threads = DEFAULT_THREAD_COUNT;
@@ -252,10 +268,7 @@
 
 void parse_flags(int argc, char* argv[])
 {
-    string *arg = new string[argc];
-
-    for(int i = 0; i < argc; i++)
-        arg[i] = argv[i];
+    vector<string> arg(argv, argv + argc);
 
     if(argc > 1 && arg[1].substr(0, 1) == "-")
     {
@@ -280,7 +293,6 @@
         decompress_flag = arg[1].find_first_of("d") != string::npos ? true : 
false;
         recursive_flag = arg[1].find_first_of("r") != string::npos ? true : 
false;
         verbose_flag = arg[1].find_first_of("v") != string::npos ? true : 
false;
-        output_pipe = arg[1].find_first_of("o") != string::npos ? true : false;
         benchmark_flag = arg[1].find_first_of("m") != string::npos ? true : 
false;
         recover_flag = arg[1].find_first_of("R") != string::npos ? true : 
false;
         force_flag = arg[1].find_first_of("f") != string::npos ? true : false;
@@ -295,11 +307,18 @@
             switch(int_flag(arg[1], "P"))
             {
                 case 1:
-                                       if 
(!SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN))
+                                       // Deliberately not using 
PROCESS_MODE_BACKGROUND_BEGIN here: it also lowers the
+                                       // process's memory priority, which 
makes Windows cap the whole process's working
+                                       // set at ~32 MiB - causing massive 
slowdowns once compression/decompression touches
+                                       // more memory than that. Applying 
THREAD_MODE_BACKGROUND_BEGIN per-thread instead
+                                       // gives the same lowered CPU/disk I/O 
priority without that working-set cap.
+                                       if 
(!SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN))
                                        {
                                                PRINT(WARNING, "%s%s: -P1 not 
supported by this OS - using -P2 instead\n", BLANK_LINE, "qpress");
                                                
SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
                                        }
+                                       else
+                                               background_priority_flag = true;
                                        break;
                 case 2: SetPriorityClass(GetCurrentProcess(), 
IDLE_PRIORITY_CLASS); break;
                 case 3: SetPriorityClass(GetCurrentProcess(), 
NORMAL_PRIORITY_CLASS); break;
@@ -376,8 +395,8 @@
     "    -B   Windows only: Disable file system caching 
(FILE_FLAG_NO_BUFFERING) to\n"
     "         prevent cache of other applications from being be flushed. 
Keep\n"
     "         enabled if files are small and need further processing\n"
-    "    -Pn  Windows only: Set CPU and disk I/O priority to n where 1 = 
BACKGORUND\n"
-       "         (Vista, 7, 2008 only), 2 = IDLE, 3 = NORMAL or 4 = ABOVE 
(default = 3)\n\n"
+    "    -Pn  Windows only: Set CPU and disk I/O priority to n where 1 = 
BACKGROUND,\n"
+       "         2 = IDLE, 3 = NORMAL or 4 = ABOVE (default = 3)\n\n"
     "Examples of compression:\n"
 #ifdef WINDOWS
     "    qpress -rv d:\\dir\\* database.qp\n"
@@ -460,9 +479,20 @@
     }
 }
 
+// Propagates the -P1 background priority (see background_priority_flag above) 
to worker threads,
+// since THREAD_MODE_BACKGROUND_BEGIN only affects the thread that calls it.
+void apply_background_priority()
+{
+#ifdef WINDOWS
+    if(background_priority_flag)
+        SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
+#endif
+}
+
 void *benchmark_compress_thread(void *arg)
 {
     unsigned long long y = 0;
+    apply_background_priority();
     size_t id = (size_t)arg;
     double t = GetTickCount();
        while(GetTickCount() == t) {};
@@ -480,6 +510,7 @@
 
 void *benchmark_decompress_thread(void *arg)
 {
+    apply_background_priority();
     unsigned long long y = 0;
     size_t id = (size_t)arg;
     double t = GetTickCount();
@@ -642,6 +673,7 @@
 
 void *decompress_file_thread(void *arg)
 {
+    apply_background_priority();
     size_t thread_id = (size_t)arg;
     bool just_recovered_block = false;
     recovery_file_written = 0;
@@ -689,7 +721,14 @@
 
         crc_original = fread32();
         try_aread(src[thread_id], 9);
-        if (QLZ_SIZE_COMPRESSED(src[thread_id]) > compress_chunk_size + 
QLZ_SIZE_OVERHEAD)
+        // Lower bound prevents "QLZ_SIZE_COMPRESSED(...) - 9" (both size_t) 
from
+        // underflowing into a huge read count on a crafted/corrupt block. The
+        // decompressed-size bound is a separate, independently 
attacker-controlled
+        // header field - without it, QLZ_DECOMPRESS() below would trust it as 
the
+        // write bound and happily overflow dst[thread_id], which only has 
room for
+        // compress_chunk_size + QLZ_SIZE_OVERHEAD decompressed bytes.
+        if (QLZ_SIZE_COMPRESSED(src[thread_id]) < 9 || 
QLZ_SIZE_COMPRESSED(src[thread_id]) > compress_chunk_size + QLZ_SIZE_OVERHEAD ||
+            QLZ_SIZE_DECOMPRESSED(src[thread_id]) > compress_chunk_size + 
QLZ_SIZE_OVERHEAD)
             abort("Data error, not recoverable"); // todo, it is recoverable, 
but code is not implemented yet
 
         try_aread(src[thread_id] + 9, QLZ_SIZE_COMPRESSED(src[thread_id]) - 9);
@@ -758,6 +797,7 @@
 
 void *compress_file_thread(void *arg)
 {
+    apply_background_priority();
     size_t read;
     do
     {
@@ -919,7 +959,7 @@
     if(recursive_flag && (dir = opendir(void2curdir(api_path).c_str())))
        {
 #ifdef WINDOWS
-        while((entry = readdir_wildcard(dir, "*")))
+        while((entry = readdir_wildcard(dir, (char *)"*")))
 #else
         while((entry = readdir(dir)))
 #endif
@@ -939,18 +979,22 @@
 
 bool check_if_path_has_dir_traversal(char * new_path)
 {
-    bool ret_val = false;
-    char *found_template1 = NULL;
-       found_template1 = strstr (new_path,"../");
-       #ifdef WINDOWS 
-           char *found_template2 = NULL;
-           found_template2 = strstr (new_path,"..\\");
-           ret_val = (found_template1 !=  NULL) || (found_template2 != NULL);
-       #else
-           ret_val = found_template1 !=  NULL;
-       #endif
-    
-    return ret_val;
+    // Reject any "/" or "\" delimited path component that is exactly "..", 
whether
+    // embedded (foo/../bar) or the whole (delimiter-free) string ("..") - 
archives
+    // are portable across platforms, so both delimiters are checked 
regardless of
+    // the platform we're running on.
+    size_t start = 0;
+    for(size_t i = 0; ; i++)
+    {
+        if(new_path[i] == '/' || new_path[i] == '\\' || new_path[i] == '\0')
+        {
+            if(i - start == 2 && new_path[start] == '.' && new_path[start + 1] 
== '.')
+                return true;
+            if(new_path[i] == '\0')
+                return false;
+            start = i + 1;
+        }
+    }
 }
 
 void decompress_directory(string extract_dir, bool std_out)
@@ -972,7 +1016,7 @@
         {
                        // read directory name, append it to current path and 
create the directory
             chunk_size = fread32();
-                       if(NAME_BUFFER_SIZE < chunk_size + 1)
+                       if(chunk_size >= (unsigned int)NAME_BUFFER_SIZE)
             {
                 abort("File path string is bigger than buffer size");
             }
@@ -1001,7 +1045,7 @@
         else if(c == 'F')
         {
             chunk_size = fread32(); // read length of file name
-            if(NAME_BUFFER_SIZE < chunk_size + 1)
+            if(chunk_size >= (unsigned int)NAME_BUFFER_SIZE)
                     {
                         abort("File path string is bigger than buffer size");
                     }
@@ -1086,7 +1130,6 @@
 #ifdef WINDOWS
     setmode(fileno(stdin), _O_BINARY);
     setmode(fileno(stdout), _O_BINARY);
-    pthread_win32_process_attach_np ();
 #endif
 
 // In-memory benchmark
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/readme.md 
new/qpress-20260802/readme.md
--- old/qpress-20230507/readme.md       2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/readme.md       2026-08-02 14:23:57.000000000 +0200
@@ -1,13 +1,31 @@
 # qpress - Portable high-speed file archiver
 
-[![CircleCI](https://dl.circleci.com/status-badge/img/gh/PierreLvx/qpress/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/PierreLvx/qpress/tree/master)
+This repo is a copy of the latest publicly available version of `qpress`, with 
several patches (performance, cleanup, security), including MacOS compatibility.
 
-This repo is a copy of the latest [publicly 
available](http://www.quicklz.com/) version of `qpress`, with several patches, 
including MacOS compatibility.
-
-Please see the CircleCI build matrix for a list of tested build environments.
+Please see the GitHub Actions build matrix for a list of tested build 
environments.
 
 Pull requests are welcome.
 
+## Installation
+
+### macOS (Homebrew)
+
+```
+brew tap PierreLvx/qpress
+brew install qpress
+```
+
+### From source
+
+Requires a C++ compiler (e.g. Xcode Command Line Tools on macOS, `xcode-select 
--install`).
+
+```
+git clone [email protected]:PierreLvx/qpress.git
+cd qpress
+make
+make install
+```
+
 ## Usage
 
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/utilities.cpp 
new/qpress-20260802/utilities.cpp
--- old/qpress-20230507/utilities.cpp   2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/utilities.cpp   2026-08-02 14:23:57.000000000 +0200
@@ -1,17 +1,21 @@
 
 #include <sys/stat.h>
-#include <string>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "utilities.hpp"
 
-#ifdef WINDOWS
+// windows.h must be included before <string> (via utilities.hpp) pulls in 
std::byte and
+// "using namespace std" below - otherwise the plain "byte" typedefs used 
internally by
+// windows.h's RPC headers become ambiguous with std::byte.
+#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
   #include <windows.h>
 #else
   #include <sys/time.h>
 #endif
 
+#include <string>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "utilities.hpp"
+
 using namespace std;
 
 #ifndef WINDOWS
@@ -32,7 +36,7 @@
 #endif
 }
 
-string lcase(string &str)
+string lcase(string str)
 {
        //change each element of the string to lower case
        string s = str;
@@ -62,6 +66,9 @@
     unsigned char c;
     unsigned int i;
 
+    if(s[0] == '\0')
+        return;
+
     for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
         c = s[i];
         s[i] = s[j];
@@ -220,11 +227,7 @@
 
     memset(s, 0, 25);
     memset(d, 0, 25);
-#ifdef WINDOWS
-    sprintf(s, "%I64d", l);
-#else
     snprintf(s, sizeof(s), "%lld", l);
-#endif
     for(i = 0; i < strlen(s); i++)
     {
         if((strlen(s) - i) % 3 == 0 && i != 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpress-20230507/utilities.hpp 
new/qpress-20260802/utilities.hpp
--- old/qpress-20230507/utilities.hpp   2023-05-07 23:02:14.000000000 +0200
+++ new/qpress-20260802/utilities.hpp   2026-08-02 14:23:57.000000000 +0200
@@ -18,21 +18,17 @@
        #include <pthread.h>
 #endif
 
-#define _CRT_SECURE_NO_WARNINGS
-string ucase(string str);
 string lcase(string str);
 string remove_leading_curdir(string path);
 string remove_delimitor(string path);
 void utils_yield(void);
 char *absolute_path(char *source, char *destination);
 void abort(const char *fmt, ...);
-string get_pid(void);
 unsigned int adler(unsigned char *data, size_t len, unsigned int crc);
 bool exists(string file);
 bool is_dir(string path);
 string str(int intValue);
 string delimiter(long long l);
-void *aligned_memory_alloc(size_t size, size_t alignment);
 void aligned_free(void *ptr);
 void *aligned_realloc(void *ptr, size_t size, size_t alignment);
 #ifndef WINDOWS

Reply via email to