Blob Blame History Raw
From c9de6c53dcf3eb1071c7999c8accc43ef2b3f458 Mon Sep 17 00:00:00 2001
From: Mark Adler <madler@alumni.caltech.edu>
Date: Sun, 24 Jan 2021 22:00:00 -0800
Subject: [PATCH] Portability improvements.

Avoid many bogus warnings across versions of gcc. Work around
missing definitions on some systems. Fix some printf format types.
---
 pigz.c                      | 77 ++++++++++++++++++++-----------------
 try.h                       |  6 +--
 zopfli/src/zopfli/cache.c   |  2 +-
 zopfli/src/zopfli/deflate.c | 13 ++++---
 4 files changed, 53 insertions(+), 45 deletions(-)

diff --git a/pigz.c b/pigz.c
index 7430e1e..6ec3a82 100644
--- a/pigz.c
+++ b/pigz.c
@@ -333,7 +333,7 @@
 // Portability defines.
 #define _FILE_OFFSET_BITS 64            // Use large file functions
 #define _LARGE_FILES                    // Same thing for AIX
-#define _POSIX_C_SOURCE 200809L         // For MinGW
+#define _XOPEN_SOURCE 700               // For POSIX 2008
 
 // Included headers and what is expected from each.
 #include <stdio.h>      // fflush(), fprintf(), fputs(), getchar(), putc(),
@@ -874,10 +874,10 @@ local void log_dump(void) {
         ;
     log_free();
     if (mem_track.num || mem_track.size)
-        complain("memory leak: %lu allocs of %lu bytes total",
+        complain("memory leak: %zu allocs of %zu bytes total",
                  mem_track.num, mem_track.size);
     if (mem_track.max)
-        fprintf(stderr, "%lu bytes of memory used in %lu allocs\n",
+        fprintf(stderr, "%zu bytes of memory used in %zu allocs\n",
                 mem_track.max, mem_track.tot);
 }
 
@@ -993,7 +993,7 @@ local size_t writen(int desc, void const *buf, size_t len) {
     size_t left = len;
 
     while (left) {
-        size_t const max = SIZE_MAX >> 1;       // max ssize_t
+        size_t const max = SSIZE_MAX;
         ssize_t ret = write(desc, next, left > max ? max : left);
         if (ret < 1)
             throw(errno, "write error on %s (%s)", g.outf, strerror(errno));
@@ -1668,26 +1668,32 @@ local void compress_thread(void *dummy) {
     size_t len;                     // remaining bytes to compress/check
 #if ZLIB_VERNUM >= 0x1260
     int bits;                       // deflate pending bits
-#endif
-#ifndef NOZOPFLI
-    struct space *temp = NULL;      // temporary space for zopfli input
 #endif
     int ret;                        // zlib return code
-    z_stream strm;                  // deflate stream
     ball_t err;                     // error information from throw()
 
     (void)dummy;
 
     try {
-        // initialize the deflate stream for this thread
-        strm.zfree = ZFREE;
-        strm.zalloc = ZALLOC;
-        strm.opaque = OPAQUE;
-        ret = deflateInit2(&strm, 6, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
-        if (ret == Z_MEM_ERROR)
-            throw(ENOMEM, "not enough memory");
-        if (ret != Z_OK)
-            throw(EINVAL, "internal error");
+        z_stream strm;                  // deflate stream
+#ifndef NOZOPFLI
+        struct space *temp = NULL;
+        // get temporary space for zopfli input
+        if (g.level > 9)
+            temp = get_space(&out_pool);
+        else
+#endif
+        {
+            // initialize the deflate stream for this thread
+            strm.zfree = ZFREE;
+            strm.zalloc = ZALLOC;
+            strm.opaque = OPAQUE;
+            ret = deflateInit2(&strm, 6, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
+            if (ret == Z_MEM_ERROR)
+                throw(ENOMEM, "not enough memory");
+            if (ret != Z_OK)
+                throw(EINVAL, "internal error");
+        }
 
         // keep looking for work
         for (;;) {
@@ -1714,11 +1720,8 @@ local void compress_thread(void *dummy) {
                 (void)deflateParams(&strm, g.level, Z_DEFAULT_STRATEGY);
 #ifndef NOZOPFLI
             }
-            else {
-                if (temp == NULL)
-                    temp = get_space(&out_pool);
+            else
                 temp->len = 0;
-            }
 #endif
 
             // set dictionary if provided, release that input or dictionary
@@ -1912,11 +1915,15 @@ local void compress_thread(void *dummy) {
         }
 
         // found job with seq == -1 -- return to join
+        release(compress_have);
 #ifndef NOZOPFLI
-        drop_space(temp);
+        if (g.level > 9)
+            drop_space(temp);
+        else
 #endif
-        release(compress_have);
-        (void)deflateEnd(&strm);
+        {
+            (void)deflateEnd(&strm);
+        }
     }
     catch (err) {
         THREADABORT(err);
@@ -3078,7 +3085,7 @@ local void show_info(int method, unsigned long check, length_t len, int cont) {
         strncpy(tag, "<...>", max + 1);
     else if (g.hname == NULL) {
         n = strlen(g.inf) - compressed_suffix(g.inf);
-        strncpy(tag, g.inf, n > max + 1 ? max + 1 : n);
+        memcpy(tag, g.inf, n > max + 1 ? max + 1 : n);
         if (strcmp(g.inf + n, ".tgz") == 0 && n < max + 1)
             strncpy(tag + n, ".tar", max + 1 - n);
     }
@@ -3802,37 +3809,33 @@ local char *justname(char *path) {
     return p == NULL ? path : p + 1;
 }
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-result"
-
 // Copy file attributes, from -> to, as best we can. This is best effort, so no
 // errors are reported. The mode bits, including suid, sgid, and the sticky bit
 // are copied (if allowed), the owner's user id and group id are copied (again
 // if allowed), and the access and modify times are copied.
-local void copymeta(char *from, char *to) {
+local int copymeta(char *from, char *to) {
     struct stat st;
     struct timeval times[2];
 
     // get all of from's Unix meta data, return if not a regular file
     if (stat(from, &st) != 0 || (st.st_mode & S_IFMT) != S_IFREG)
-        return;
+        return -4;
 
     // set to's mode bits, ignore errors
-    (void)chmod(to, st.st_mode & 07777);
+    int ret = chmod(to, st.st_mode & 07777);
 
     // copy owner's user and group, ignore errors
-    (void)chown(to, st.st_uid, st.st_gid);
+    ret += chown(to, st.st_uid, st.st_gid);
 
     // copy access and modify times, ignore errors
     times[0].tv_sec = st.st_atime;
     times[0].tv_usec = 0;
     times[1].tv_sec = st.st_mtime;
     times[1].tv_usec = 0;
-    (void)utimes(to, times);
+    ret += utimes(to, times);
+    return ret;
 }
 
-#pragma GCC diagnostic pop
-
 // Set the access and modify times of fd to t.
 local void touch(char *path, time_t t) {
     struct timeval times[2];
@@ -4430,6 +4433,7 @@ local int option(char *arg) {
                 puts("Subject to the terms of the zlib license.");
                 puts("No warranty is provided or implied.");
                 exit(0);
+                break;          // avoid warning
             case 'M':  g.headis |= 0xa;  break;
             case 'N':  g.headis = 0xf;  break;
 #ifndef NOZOPFLI
@@ -4443,13 +4447,16 @@ local int option(char *arg) {
                 if (g.verbosity > 1)
                     printf("zlib %s\n", zlibVersion());
                 exit(0);
+                break;          // avoid warning
             case 'Y':  g.sync = 1;  break;
             case 'Z':
                 throw(EINVAL, "invalid option: LZW output not supported: %s",
                       bad);
+                break;          // avoid warning
             case 'a':
                 throw(EINVAL, "invalid option: no ascii conversion: %s",
                       bad);
+                break;          // avoid warning
             case 'b':  get = 1;  break;
             case 'c':  g.pipeout = 1;  break;
             case 'd':  if (!g.decode) g.headis >>= 2;  g.decode = 1;  break;
diff --git a/try.h b/try.h
index 03289dd..3009f7d 100644
--- a/try.h
+++ b/try.h
@@ -304,8 +304,8 @@ struct try_s_ {
 #   define try_stack_ ((try_t_ *)pthread_getspecific(try_key_))
 #   define try_stack_set_(next) \
         do { \
-            int try_ret_ = pthread_setspecific(try_key_, next); \
-            assert(try_ret_ == 0 && "try: pthread_setspecific() failed"); \
+            assert(pthread_setspecific(try_key_, next) == 0 && \
+                   "try: pthread_setspecific() failed"); \
         } while (0)
 #else /* !PTHREAD_ONCE_INIT */
     extern try_t_ *try_stack_;
@@ -320,7 +320,7 @@ struct try_s_ {
 #define TRY_TRY_ \
     do { \
         try_t_ try_this_; \
-        int try_pushed_ = 1; \
+        volatile int try_pushed_ = 1; \
         try_this_.ball.code = 0; \
         try_this_.ball.free = 0; \
         try_this_.ball.why = NULL; \
diff --git a/zopfli/src/zopfli/cache.c b/zopfli/src/zopfli/cache.c
index f5559c3..e5934df 100644
--- a/zopfli/src/zopfli/cache.c
+++ b/zopfli/src/zopfli/cache.c
@@ -33,7 +33,7 @@ void ZopfliInitCache(size_t blocksize, ZopfliLongestMatchCache* lmc) {
   lmc->sublen = (unsigned char*)malloc(ZOPFLI_CACHE_LENGTH * 3 * blocksize);
   if(lmc->sublen == NULL) {
     fprintf(stderr,
-        "Error: Out of memory. Tried allocating %lu bytes of memory.\n",
+        "Error: Out of memory. Tried allocating %zu bytes of memory.\n",
         ZOPFLI_CACHE_LENGTH * 3 * blocksize);
     exit (EXIT_FAILURE);
   }
diff --git a/zopfli/src/zopfli/deflate.c b/zopfli/src/zopfli/deflate.c
index abe7360..f7b62e4 100644
--- a/zopfli/src/zopfli/deflate.c
+++ b/zopfli/src/zopfli/deflate.c
@@ -431,22 +431,23 @@ Changes the population counts in a way that the consequent Huffman tree
 compression, especially its rle-part, will be more likely to compress this data
 more efficiently. length contains the size of the histogram.
 */
-void OptimizeHuffmanForRle(int length, size_t* counts) {
-  int i, k, stride;
+void OptimizeHuffmanForRle(unsigned length, size_t* counts) {
+  unsigned i;
+  int k, stride;
   size_t symbol, sum, limit;
   int* good_for_rle;
 
   /* 1) We don't want to touch the trailing zeros. We may break the
   rules of the format by adding more data in the distance codes. */
-  for (; length >= 0; --length) {
-    if (length == 0) {
-      return;
-    }
+  for (; length > 0; --length) {
     if (counts[length - 1] != 0) {
       /* Now counts[0..length - 1] does not have trailing zeros. */
       break;
     }
   }
+  if (length == 0) {
+    return;
+  }
   /* 2) Let's mark all population counts that already can be encoded
   with an rle code.*/
   good_for_rle = (int*)malloc(length * sizeof(int));