]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/file.c
Fix some build issues with the "core" component selection (rdar://47394086)
[thirdparty/cups.git] / cups / file.c
index a96ef564bb0791f154a9b3556a3a55d14b08c847..e6e1f5b826f9d91d130891ab30c5036b45db3a75 100644 (file)
@@ -1,23 +1,16 @@
 /*
- * "$Id$"
- *
  * File functions for CUPS.
  *
  * Since stdio files max out at 256 files on many systems, we have to
  * write similar functions without this limit.  At the same time, using
  * our own file functions allows us to provide transparent support of
- * gzip'd print files, PPD files, etc.
- *
- * Copyright 2007-2014 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * different line endings, gzip'd print files, PPD files, etc.
  *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file.  If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
+ * Copyright © 2007-2019 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
  *
- * This file is subject to the Apple OS-Developed Software exception.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
  */
 
 #include "file-private.h"
+#include "debug-internal.h"
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#  ifdef HAVE_LIBZ
+#    include <zlib.h>
+#  endif /* HAVE_LIBZ */
+
+
+/*
+ * Internal structures...
+ */
+
+struct _cups_file_s                    /**** CUPS file structure... ****/
+
+{
+  int          fd;                     /* File descriptor */
+  char         mode,                   /* Mode ('r' or 'w') */
+               compressed,             /* Compression used? */
+               is_stdio,               /* stdin/out/err? */
+               eof,                    /* End of file? */
+               buf[4096],              /* Buffer */
+               *ptr,                   /* Pointer into buffer */
+               *end;                   /* End of buffer data */
+  off_t                pos,                    /* Position in file */
+               bufpos;                 /* File position for start of buffer */
+
+#ifdef HAVE_LIBZ
+  z_stream     stream;                 /* (De)compression stream */
+  Bytef                cbuf[4096];             /* (De)compression buffer */
+  uLong                crc;                    /* (De)compression CRC */
+#endif /* HAVE_LIBZ */
+
+  char         *printf_buffer;         /* cupsFilePrintf buffer */
+  size_t       printf_size;            /* Size of cupsFilePrintf buffer */
+};
+
 
 /*
  * Local functions...
@@ -42,7 +69,7 @@ static ssize_t        cups_read(cups_file_t *fp, char *buf, size_t bytes);
 static ssize_t cups_write(cups_file_t *fp, const char *buf, size_t bytes);
 
 
-#ifndef WIN32
+#ifndef _WIN32
 /*
  * '_cupsFileCheck()' - Check the permissions of the given filename.
  */
@@ -288,6 +315,7 @@ _cupsFileCheckFilter(
 
   switch (result)
   {
+    default :
     case _CUPS_FILE_CHECK_OK :
         prefix = "DEBUG2";
        break;
@@ -307,13 +335,13 @@ _cupsFileCheckFilter(
 
   fprintf(stderr, "%s: %s\n", prefix, message);
 }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 
 /*
  * 'cupsFileClose()' - Close a CUPS file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on error */
@@ -322,10 +350,9 @@ cupsFileClose(cups_file_t *fp)             /* I - CUPS file */
   int  fd;                             /* File descriptor */
   char mode;                           /* Open mode */
   int  status;                         /* Return status */
-  int  is_stdio;                       /* Is a stdio file? */
 
 
-  DEBUG_printf(("cupsFileClose(fp=%p)", fp));
+  DEBUG_printf(("cupsFileClose(fp=%p)", (void *)fp));
 
  /*
   * Range check...
@@ -411,12 +438,19 @@ cupsFileClose(cups_file_t *fp)            /* I - CUPS file */
 #endif /* HAVE_LIBZ */
 
  /*
+  * If this is one of the cupsFileStdin/out/err files, return now and don't
+  * actually free memory or close (these last the life of the process...)
+  */
+
+  if (fp->is_stdio)
+    return (status);
+
+/*
   * Save the file descriptor we used and free memory...
   */
 
-  fd       = fp->fd;
-  mode     = fp->mode;
-  is_stdio = fp->is_stdio;
+  fd   = fp->fd;
+  mode = fp->mode;
 
   if (fp->printf_buffer)
     free(fp->printf_buffer);
@@ -432,11 +466,8 @@ cupsFileClose(cups_file_t *fp)             /* I - CUPS file */
     if (httpAddrClose(NULL, fd) < 0)
       status = -1;
   }
-  else if (!is_stdio)
-  {
-    if (close(fd) < 0)
-      status = -1;
-  }
+  else if (close(fd) < 0)
+    status = -1;
 
   return (status);
 }
@@ -445,7 +476,7 @@ cupsFileClose(cups_file_t *fp)              /* I - CUPS file */
 /*
  * 'cupsFileCompression()' - Return whether a file is compressed.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - @code CUPS_FILE_NONE@ or @code CUPS_FILE_GZIP@ */
@@ -458,7 +489,7 @@ cupsFileCompression(cups_file_t *fp)        /* I - CUPS file */
 /*
  * 'cupsFileEOF()' - Return the end-of-file status.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 1 on end of file, 0 otherwise */
@@ -477,7 +508,7 @@ cupsFileEOF(cups_file_t *fp)                /* I - CUPS file */
  * the supplied paths, @code NULL@ is returned. A @code NULL@ path only
  * matches the current directory.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 const char *                           /* O - Full path to file or @code NULL@ if not found */
@@ -495,9 +526,7 @@ cupsFileFind(const char *filename,  /* I - File to find */
   * Range check input...
   */
 
-  DEBUG_printf(("cupsFileFind(filename=\"%s\", path=\"%s\", executable=%d, "
-                "buffer=%p, bufsize=%d)", filename, path, executable, buffer,
-               bufsize));
+  DEBUG_printf(("cupsFileFind(filename=\"%s\", path=\"%s\", executable=%d, buffer=%p, bufsize=%d)", filename, path, executable, (void *)buffer, bufsize));
 
   if (!filename || !buffer || bufsize < 2)
     return (NULL);
@@ -526,22 +555,22 @@ cupsFileFind(const char *filename,        /* I - File to find */
 
   while (*path)
   {
-#ifdef WIN32
+#ifdef _WIN32
     if (*path == ';' || (*path == ':' && ((bufptr - buffer) > 1 || !isalpha(buffer[0] & 255))))
 #else
     if (*path == ';' || *path == ':')
-#endif /* WIN32 */
+#endif /* _WIN32 */
     {
       if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend)
         *bufptr++ = '/';
 
       strlcpy(bufptr, filename, (size_t)(bufend - bufptr));
 
-#ifdef WIN32
+#ifdef _WIN32
       if (!access(buffer, 0))
 #else
       if (!access(buffer, executable ? X_OK : 0))
-#endif /* WIN32 */
+#endif /* _WIN32 */
       {
         DEBUG_printf(("1cupsFileFind: Returning \"%s\"", buffer));
         return (buffer);
@@ -580,7 +609,7 @@ cupsFileFind(const char *filename,  /* I - File to find */
 /*
  * 'cupsFileFlush()' - Flush pending output.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on error */
@@ -589,7 +618,7 @@ cupsFileFlush(cups_file_t *fp)              /* I - CUPS file */
   ssize_t      bytes;                  /* Bytes to write */
 
 
-  DEBUG_printf(("cupsFileFlush(fp=%p)", fp));
+  DEBUG_printf(("cupsFileFlush(fp=%p)", (void *)fp));
 
  /*
   * Range check input...
@@ -628,7 +657,7 @@ cupsFileFlush(cups_file_t *fp)              /* I - CUPS file */
 /*
  * 'cupsFileGetChar()' - Get a single character from a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - Character or -1 on end of file */
@@ -638,18 +667,28 @@ cupsFileGetChar(cups_file_t *fp)  /* I - CUPS file */
   * Range check input...
   */
 
+  DEBUG_printf(("4cupsFileGetChar(fp=%p)", (void *)fp));
+
   if (!fp || (fp->mode != 'r' && fp->mode != 's'))
   {
     DEBUG_puts("5cupsFileGetChar: Bad arguments!");
     return (-1);
   }
 
+  if (fp->eof)
+  {
+    DEBUG_puts("5cupsFileGetChar: End-of-file!");
+    return (-1);
+  }
+
  /*
   * If the input buffer is empty, try to read more data...
   */
 
+  DEBUG_printf(("5cupsFileGetChar: fp->eof=%d, fp->ptr=%p, fp->end=%p", fp->eof, (void *)fp->ptr, (void *)fp->end));
+
   if (fp->ptr >= fp->end)
-    if (cups_fill(fp) < 0)
+    if (cups_fill(fp) <= 0)
     {
       DEBUG_puts("5cupsFileGetChar: Unable to fill buffer!");
       return (-1);
@@ -672,7 +711,7 @@ cupsFileGetChar(cups_file_t *fp)    /* I - CUPS file */
 /*
  * 'cupsFileGetConf()' - Get a line from a configuration file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 char *                                 /* O  - Line read or @code NULL@ on end of file or error */
@@ -690,8 +729,7 @@ cupsFileGetConf(cups_file_t *fp,    /* I  - CUPS file */
   */
 
   DEBUG_printf(("2cupsFileGetConf(fp=%p, buf=%p, buflen=" CUPS_LLFMT
-                ", value=%p, linenum=%p)", fp, buf, CUPS_LLCAST buflen,
-               value, linenum));
+                ", value=%p, linenum=%p)", (void *)fp, (void *)buf, CUPS_LLCAST buflen, (void *)value, (void *)linenum));
 
   if (!fp || (fp->mode != 'r' && fp->mode != 's') ||
       !buf || buflen < 2 || !value)
@@ -816,7 +854,7 @@ cupsFileGetConf(cups_file_t *fp,    /* I  - CUPS file */
  * nul-terminated, however you should use the returned length to determine
  * the number of bytes on the line.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 size_t                                 /* O - Number of bytes on line or 0 on end of file */
@@ -833,8 +871,7 @@ cupsFileGetLine(cups_file_t *fp,    /* I - File to read from */
   * Range check input...
   */
 
-  DEBUG_printf(("2cupsFileGetLine(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")",
-                fp, buf, CUPS_LLCAST buflen));
+  DEBUG_printf(("2cupsFileGetLine(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST buflen));
 
   if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 3)
     return (0);
@@ -891,7 +928,7 @@ cupsFileGetLine(cups_file_t *fp,    /* I - File to read from */
 /*
  * 'cupsFileGets()' - Get a CR and/or LF-terminated line.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 char *                                 /* O - Line read or @code NULL@ on end of file or error */
@@ -908,8 +945,7 @@ cupsFileGets(cups_file_t *fp,               /* I - CUPS file */
   * Range check input...
   */
 
-  DEBUG_printf(("2cupsFileGets(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")", fp, buf,
-                CUPS_LLCAST buflen));
+  DEBUG_printf(("2cupsFileGets(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST buflen));
 
   if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 2)
     return (NULL);
@@ -973,7 +1009,7 @@ cupsFileGets(cups_file_t *fp,              /* I - CUPS file */
 /*
  * 'cupsFileLock()' - Temporarily lock access to a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on error */
@@ -991,18 +1027,18 @@ cupsFileLock(cups_file_t *fp,            /* I - CUPS file */
   * Try the lock...
   */
 
-#ifdef WIN32
+#ifdef _WIN32
   return (_locking(fp->fd, block ? _LK_LOCK : _LK_NBLCK, 0));
 #else
   return (lockf(fp->fd, block ? F_LOCK : F_TLOCK, 0));
-#endif /* WIN32 */
+#endif /* _WIN32 */
 }
 
 
 /*
  * 'cupsFileNumber()' - Return the file descriptor associated with a CUPS file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - File descriptor */
@@ -1031,7 +1067,7 @@ cupsFileNumber(cups_file_t *fp)           /* I - CUPS file */
  * connection as needed, generally preferring IPv6 connections when there is
  * a choice.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 cups_file_t *                          /* O - CUPS file or @code NULL@ if the file or socket cannot be opened */
@@ -1083,11 +1119,11 @@ cupsFileOpen(const char *filename,      /* I - Name of file */
        }
 
        if (fd >= 0)
-#ifdef WIN32
+#ifdef _WIN32
          _chsize(fd, 0);
 #else
          ftruncate(fd, 0);
-#endif /* WIN32 */
+#endif /* _WIN32 */
         break;
 
     case 's' : /* Read/write socket */
@@ -1153,7 +1189,7 @@ cupsFileOpen(const char *filename,        /* I - Name of file */
  * supplied which enables Flate compression of the file.  Compression is
  * not supported for the "a" (append) mode.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 cups_file_t *                          /* O - CUPS file or @code NULL@ if the file could not be opened */
@@ -1254,18 +1290,30 @@ cupsFileOpenFd(int        fd,           /* I - File descriptor */
   * Don't pass this file to child processes...
   */
 
-#ifndef WIN32
+#ifndef _WIN32
   fcntl(fp->fd, F_SETFD, fcntl(fp->fd, F_GETFD) | FD_CLOEXEC);
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
   return (fp);
 }
 
 
+/*
+ * '_cupsFilePeekAhead()' - See if the requested character is buffered up.
+ */
+
+int                                    /* O - 1 if present, 0 otherwise */
+_cupsFilePeekAhead(cups_file_t *fp,    /* I - CUPS file */
+                   int         ch)     /* I - Character */
+{
+  return (fp && fp->ptr && memchr(fp->ptr, ch, (size_t)(fp->end - fp->ptr)));
+}
+
+
 /*
  * 'cupsFilePeekChar()' - Peek at the next character from a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - Character or -1 on end of file */
@@ -1283,7 +1331,7 @@ cupsFilePeekChar(cups_file_t *fp) /* I - CUPS file */
   */
 
   if (fp->ptr >= fp->end)
-    if (cups_fill(fp) < 0)
+    if (cups_fill(fp) <= 0)
       return (-1);
 
  /*
@@ -1297,7 +1345,7 @@ cupsFilePeekChar(cups_file_t *fp) /* I - CUPS file */
 /*
  * 'cupsFilePrintf()' - Write a formatted string.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - Number of bytes written or -1 on error */
@@ -1309,7 +1357,7 @@ cupsFilePrintf(cups_file_t *fp,           /* I - CUPS file */
   ssize_t      bytes;                  /* Formatted size */
 
 
-  DEBUG_printf(("2cupsFilePrintf(fp=%p, format=\"%s\", ...)", fp, format));
+  DEBUG_printf(("2cupsFilePrintf(fp=%p, format=\"%s\", ...)", (void *)fp, format));
 
   if (!fp || !format || (fp->mode != 'w' && fp->mode != 's'))
     return (-1);
@@ -1386,7 +1434,11 @@ cupsFilePrintf(cups_file_t *fp,          /* I - CUPS file */
   {
     memcpy(fp->ptr, fp->printf_buffer, (size_t)bytes);
     fp->ptr += bytes;
-    return ((int)bytes);
+
+    if (fp->is_stdio && cupsFileFlush(fp))
+      return (-1);
+    else
+      return ((int)bytes);
   }
 }
 
@@ -1394,7 +1446,7 @@ cupsFilePrintf(cups_file_t *fp,           /* I - CUPS file */
 /*
  * 'cupsFilePutChar()' - Write a character.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on error */
@@ -1448,7 +1500,7 @@ cupsFilePutChar(cups_file_t *fp,  /* I - CUPS file */
  *
  * This function handles any comment escaping of the value.
  *
- * @since CUPS 1.4/OS X 10.6@
+ * @since CUPS 1.4/macOS 10.6@
  */
 
 ssize_t                                        /* O - Number of bytes written or -1 on error */
@@ -1509,7 +1561,7 @@ cupsFilePutConf(cups_file_t *fp,  /* I - CUPS file */
  *
  * Like the @code fputs@ function, no newline is appended to the string.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - Number of bytes written or -1 on error */
@@ -1565,7 +1617,11 @@ cupsFilePuts(cups_file_t *fp,            /* I - CUPS file */
   {
     memcpy(fp->ptr, s, (size_t)bytes);
     fp->ptr += bytes;
-    return ((int)bytes);
+
+    if (fp->is_stdio && cupsFileFlush(fp))
+      return (-1);
+    else
+      return ((int)bytes);
   }
 }
 
@@ -1573,7 +1629,7 @@ cupsFilePuts(cups_file_t *fp,             /* I - CUPS file */
 /*
  * 'cupsFileRead()' - Read from a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 ssize_t                                        /* O - Number of bytes read or -1 on error */
@@ -1585,8 +1641,7 @@ cupsFileRead(cups_file_t *fp,             /* I - CUPS file */
   ssize_t      count;                  /* Bytes read */
 
 
-  DEBUG_printf(("2cupsFileRead(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", fp, buf,
-                CUPS_LLCAST bytes));
+  DEBUG_printf(("2cupsFileRead(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST bytes));
 
  /*
   * Range check input...
@@ -1598,6 +1653,12 @@ cupsFileRead(cups_file_t *fp,            /* I - CUPS file */
   if (bytes == 0)
     return (0);
 
+  if (fp->eof)
+  {
+    DEBUG_puts("5cupsFileRead: End-of-file!");
+    return (-1);
+  }
+
  /*
   * Loop until all bytes are read...
   */
@@ -1650,7 +1711,7 @@ cupsFileRead(cups_file_t *fp,             /* I - CUPS file */
  * 'cupsFileRewind()' - Set the current file position to the beginning of the
  *                      file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 off_t                                  /* O - New file position or -1 on error */
@@ -1660,7 +1721,7 @@ cupsFileRewind(cups_file_t *fp)           /* I - CUPS file */
   * Range check input...
   */
 
-  DEBUG_printf(("cupsFileRewind(fp=%p)", fp));
+  DEBUG_printf(("cupsFileRewind(fp=%p)", (void *)fp));
   DEBUG_printf(("2cupsFileRewind: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos));
 
   if (!fp || fp->mode != 'r')
@@ -1722,7 +1783,7 @@ cupsFileRewind(cups_file_t *fp)           /* I - CUPS file */
 /*
  * 'cupsFileSeek()' - Seek in a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 off_t                                  /* O - New file position or -1 on error */
@@ -1732,10 +1793,9 @@ cupsFileSeek(cups_file_t *fp,            /* I - CUPS file */
   ssize_t      bytes;                  /* Number bytes in buffer */
 
 
-  DEBUG_printf(("cupsFileSeek(fp=%p, pos=" CUPS_LLFMT ")", fp,
-                CUPS_LLCAST pos));
+  DEBUG_printf(("cupsFileSeek(fp=%p, pos=" CUPS_LLFMT ")", (void *)fp, CUPS_LLCAST pos));
   DEBUG_printf(("2cupsFileSeek: fp->pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos));
-  DEBUG_printf(("2cupsFileSeek: fp->ptr=%p, fp->end=%p", fp->ptr, fp->end));
+  DEBUG_printf(("2cupsFileSeek: fp->ptr=%p, fp->end=%p", (void *)fp->ptr, (void *)fp->end));
 
  /*
   * Range check input...
@@ -1778,7 +1838,7 @@ cupsFileSeek(cups_file_t *fp,             /* I - CUPS file */
     * Preload a buffer to determine whether the file is compressed...
     */
 
-    if (cups_fill(fp) < 0)
+    if (cups_fill(fp) <= 0)
       return (-1);
   }
 #endif /* HAVE_LIBZ */
@@ -1875,7 +1935,7 @@ cupsFileSeek(cups_file_t *fp,             /* I - CUPS file */
 /*
  * 'cupsFileStderr()' - Return a CUPS file associated with stderr.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 cups_file_t *                          /* O - CUPS file */
@@ -1911,7 +1971,7 @@ cupsFileStderr(void)
 /*
  * 'cupsFileStdin()' - Return a CUPS file associated with stdin.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 cups_file_t *                          /* O - CUPS file */
@@ -1941,7 +2001,7 @@ cupsFileStdin(void)
 /*
  * 'cupsFileStdout()' - Return a CUPS file associated with stdout.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 cups_file_t *                          /* O - CUPS file */
@@ -1977,15 +2037,14 @@ cupsFileStdout(void)
 /*
  * 'cupsFileTell()' - Return the current file position.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 off_t                                  /* O - File position */
 cupsFileTell(cups_file_t *fp)          /* I - CUPS file */
 {
-  DEBUG_printf(("2cupsFileTell(fp=%p)", fp));
-  DEBUG_printf(("3cupsFileTell: pos=" CUPS_LLFMT,
-               CUPS_LLCAST (fp ? fp->pos : -1)));
+  DEBUG_printf(("2cupsFileTell(fp=%p)", (void *)fp));
+  DEBUG_printf(("3cupsFileTell: pos=" CUPS_LLFMT, CUPS_LLCAST (fp ? fp->pos : -1)));
 
   return (fp ? fp->pos : 0);
 }
@@ -1994,7 +2053,7 @@ cupsFileTell(cups_file_t *fp)             /* I - CUPS file */
 /*
  * 'cupsFileUnlock()' - Unlock access to a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 int                                    /* O - 0 on success, -1 on error */
@@ -2004,7 +2063,7 @@ cupsFileUnlock(cups_file_t *fp)           /* I - CUPS file */
   * Range check...
   */
 
-  DEBUG_printf(("cupsFileUnlock(fp=%p)", fp));
+  DEBUG_printf(("cupsFileUnlock(fp=%p)", (void *)fp));
 
   if (!fp || fp->mode == 's')
     return (-1);
@@ -2013,18 +2072,18 @@ cupsFileUnlock(cups_file_t *fp)         /* I - CUPS file */
   * Unlock...
   */
 
-#ifdef WIN32
+#ifdef _WIN32
   return (_locking(fp->fd, _LK_UNLCK, 0));
 #else
   return (lockf(fp->fd, F_ULOCK, 0));
-#endif /* WIN32 */
+#endif /* _WIN32 */
 }
 
 
 /*
  * 'cupsFileWrite()' - Write to a file.
  *
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
  */
 
 ssize_t                                        /* O - Number of bytes written or -1 on error */
@@ -2036,8 +2095,7 @@ cupsFileWrite(cups_file_t *fp,            /* I - CUPS file */
   * Range check input...
   */
 
-  DEBUG_printf(("2cupsFileWrite(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")",
-                fp, buf, CUPS_LLCAST bytes));
+  DEBUG_printf(("2cupsFileWrite(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST bytes));
 
   if (!fp || !buf || (fp->mode != 'w' && fp->mode != 's'))
     return (-1);
@@ -2097,8 +2155,7 @@ cups_compress(cups_file_t *fp,            /* I - CUPS file */
               const char  *buf,                /* I - Buffer */
              size_t      bytes)        /* I - Number bytes */
 {
-  DEBUG_printf(("7cups_compress(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", fp, buf,
-                CUPS_LLCAST bytes));
+  DEBUG_printf(("7cups_compress(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST bytes));
 
  /*
   * Update the CRC...
@@ -2154,10 +2211,8 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
 #endif /* HAVE_LIBZ */
 
 
-  DEBUG_printf(("7cups_fill(fp=%p)", fp));
-  DEBUG_printf(("9cups_fill: fp->ptr=%p, fp->end=%p, fp->buf=%p, "
-                "fp->bufpos=" CUPS_LLFMT ", fp->eof=%d",
-                fp->ptr, fp->end, fp->buf, CUPS_LLCAST fp->bufpos, fp->eof));
+  DEBUG_printf(("7cups_fill(fp=%p)", (void *)fp));
+  DEBUG_printf(("9cups_fill: fp->ptr=%p, fp->end=%p, fp->buf=%p, fp->bufpos=" CUPS_LLFMT ", fp->eof=%d", (void *)fp->ptr, (void *)fp->end, (void *)fp->buf, CUPS_LLCAST fp->bufpos, fp->eof));
 
   if (fp->ptr && fp->end)
     fp->bufpos += fp->end - fp->buf;
@@ -2194,6 +2249,8 @@ cups_fill(cups_file_t *fp)                /* I - CUPS file */
         DEBUG_printf(("9cups_fill: cups_read() returned " CUPS_LLFMT,
                      CUPS_LLCAST bytes));
 
+        fp->eof = 1;
+
        return (-1);
       }
 
@@ -2233,6 +2290,11 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
          * Can't read from file!
          */
 
+         DEBUG_puts("9cups_fill: Extra gzip header data missing, returning -1.");
+
+          fp->eof = 1;
+         errno   = EIO;
+
          return (-1);
        }
 
@@ -2245,6 +2307,11 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
          * Can't read from file!
          */
 
+         DEBUG_puts("9cups_fill: Extra gzip header data does not fit in initial buffer, returning -1.");
+
+          fp->eof = 1;
+         errno   = EIO;
+
          return (-1);
        }
       }
@@ -2266,6 +2333,11 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
          * Can't read from file!
          */
 
+         DEBUG_puts("9cups_fill: Original filename in gzip header data does not fit in initial buffer, returning -1.");
+
+          fp->eof = 1;
+         errno   = EIO;
+
          return (-1);
        }
       }
@@ -2287,6 +2359,11 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
          * Can't read from file!
          */
 
+         DEBUG_puts("9cups_fill: Comment in gzip header data does not fit in initial buffer, returning -1.");
+
+          fp->eof = 1;
+         errno   = EIO;
+
          return (-1);
        }
       }
@@ -2305,6 +2382,11 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
          * Can't read from file!
          */
 
+         DEBUG_puts("9cups_fill: Header CRC in gzip header data does not fit in initial buffer, returning -1.");
+
+          fp->eof = 1;
+         errno   = EIO;
+
          return (-1);
        }
       }
@@ -2329,8 +2411,15 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
       fp->stream.avail_out = 0;
       fp->crc              = crc32(0L, Z_NULL, 0);
 
-      if (inflateInit2(&(fp->stream), -15) != Z_OK)
+      if ((status = inflateInit2(&(fp->stream), -15)) != Z_OK)
+      {
+       DEBUG_printf(("9cups_fill: inflateInit2 returned %d, returning -1.", status));
+
+        fp->eof = 1;
+        errno   = EIO;
+
        return (-1);
+      }
 
       fp->compressed = 1;
     }
@@ -2342,7 +2431,11 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
       */
 
       if (fp->eof)
-       return (-1);
+      {
+        DEBUG_puts("9cups_fill: EOF, returning 0.");
+
+       return (0);
+      }
 
      /*
       * Fill the decompression buffer as needed...
@@ -2351,7 +2444,13 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
       if (fp->stream.avail_in == 0)
       {
        if ((bytes = cups_read(fp, (char *)fp->cbuf, sizeof(fp->cbuf))) <= 0)
-          return (-1);
+       {
+         DEBUG_printf(("9cups_fill: cups_read error, returning %d.", (int)bytes));
+
+         fp->eof = 1;
+
+          return (bytes);
+       }
 
        fp->stream.next_in  = fp->cbuf;
        fp->stream.avail_in = (uInt)bytes;
@@ -2378,42 +2477,71 @@ cups_fill(cups_file_t *fp)              /* I - CUPS file */
 
        unsigned char   trailer[8];     /* Trailer bytes */
        uLong           tcrc;           /* Trailer CRC */
+       ssize_t         tbytes = 0;     /* Number of bytes */
 
-
-       if (read(fp->fd, trailer, sizeof(trailer)) < (ssize_t)sizeof(trailer))
+       if (fp->stream.avail_in > 0)
        {
-        /*
-          * Can't get it, so mark end-of-file...
-         */
+         if (fp->stream.avail_in > sizeof(trailer))
+           tbytes = (ssize_t)sizeof(trailer);
+         else
+           tbytes = (ssize_t)fp->stream.avail_in;
 
-          fp->eof = 1;
+         memcpy(trailer, fp->stream.next_in, (size_t)tbytes);
+         fp->stream.next_in  += tbytes;
+         fp->stream.avail_in -= (size_t)tbytes;
        }
-       else
-       {
-         tcrc = ((((((uLong)trailer[3] << 8) | (uLong)trailer[2]) << 8) |
-                 (uLong)trailer[1]) << 8) | (uLong)trailer[0];
 
-         if (tcrc != fp->crc)
+        if (tbytes < (ssize_t)sizeof(trailer))
+       {
+         if (read(fp->fd, trailer + tbytes, sizeof(trailer) - (size_t)tbytes) < ((ssize_t)sizeof(trailer) - tbytes))
          {
           /*
-            * Bad CRC, mark end-of-file...
+           * Can't get it, so mark end-of-file...
            */
 
-            DEBUG_printf(("9cups_fill: tcrc=%08x != fp->crc=%08x",
-                         (unsigned int)tcrc, (unsigned int)fp->crc));
+           DEBUG_puts("9cups_fill: Unable to read gzip CRC trailer, returning -1.");
 
            fp->eof = 1;
+           errno   = EIO;
 
            return (-1);
          }
+       }
+
+       tcrc = ((((((uLong)trailer[3] << 8) | (uLong)trailer[2]) << 8) |
+               (uLong)trailer[1]) << 8) | (uLong)trailer[0];
 
+       if (tcrc != fp->crc)
+       {
         /*
-         * Otherwise, reset the compressed flag so that we re-read the
-         * file header...
+         * Bad CRC, mark end-of-file...
          */
 
-         fp->compressed = 0;
+         DEBUG_printf(("9cups_fill: tcrc=%08x != fp->crc=%08x, returning -1.", (unsigned int)tcrc, (unsigned int)fp->crc));
+
+         fp->eof = 1;
+         errno   = EIO;
+
+         return (-1);
        }
+
+       /*
+       * Otherwise, reset the compressed flag so that we re-read the
+       * file header...
+       */
+
+        inflateEnd(&fp->stream);
+
+       fp->compressed = 0;
+      }
+      else if (status < Z_OK)
+      {
+       DEBUG_printf(("9cups_fill: inflate returned %d, returning -1.", status));
+
+        fp->eof = 1;
+        errno   = EIO;
+
+       return (-1);
       }
 
       bytes = (ssize_t)sizeof(fp->buf) - (ssize_t)fp->stream.avail_out;
@@ -2426,7 +2554,10 @@ cups_fill(cups_file_t *fp)               /* I - CUPS file */
       fp->end = fp->buf + bytes;
 
       if (bytes)
+      {
+        DEBUG_printf(("9cups_fill: Returning %d.", (int)bytes));
        return (bytes);
+      }
     }
   }
 #endif /* HAVE_LIBZ */
@@ -2444,17 +2575,19 @@ cups_fill(cups_file_t *fp)              /* I - CUPS file */
     fp->eof = 1;
     fp->ptr = fp->buf;
     fp->end = fp->buf;
-
-    return (-1);
   }
+  else
+  {
+   /*
+    * Return the bytes we read...
+    */
 
- /*
-  * Return the bytes we read...
-  */
+    fp->eof = 0;
+    fp->ptr = fp->buf;
+    fp->end = fp->buf + bytes;
+  }
 
-  fp->eof = 0;
-  fp->ptr = fp->buf;
-  fp->end = fp->buf + bytes;
+  DEBUG_printf(("9cups_fill: Not gzip, returning %d.", (int)bytes));
 
   return (bytes);
 }
@@ -2473,9 +2606,9 @@ cups_open(const char *filename,           /* I - Filename */
 {
   int          fd;                     /* File descriptor */
   struct stat  fileinfo;               /* File information */
-#ifndef WIN32
+#ifndef _WIN32
   struct stat  linkinfo;               /* Link information */
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 
  /*
@@ -2503,18 +2636,18 @@ cups_open(const char *filename,         /* I - Filename */
     return (-1);
   }
 
-#ifdef WIN32
+#ifdef _WIN32
   if (fileinfo.st_mode & _S_IFDIR)
 #else
   if (S_ISDIR(fileinfo.st_mode))
-#endif /* WIN32 */
+#endif /* _WIN32 */
   {
     close(fd);
     errno = EISDIR;
     return (-1);
   }
 
-#ifndef WIN32
+#ifndef _WIN32
  /*
   * Then use lstat to determine whether the filename is a symlink...
   */
@@ -2542,7 +2675,7 @@ cups_open(const char *filename,           /* I - Filename */
     errno = EPERM;
     return (-1);
   }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
   return (fd);
 }
@@ -2560,8 +2693,7 @@ cups_read(cups_file_t *fp,                /* I - CUPS file */
   ssize_t      total;                  /* Total bytes read */
 
 
-  DEBUG_printf(("7cups_read(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", fp, buf,
-                CUPS_LLCAST bytes));
+  DEBUG_printf(("7cups_read(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST bytes));
 
  /*
   * Loop until we read at least 0 bytes...
@@ -2569,7 +2701,7 @@ cups_read(cups_file_t *fp,                /* I - CUPS file */
 
   for (;;)
   {
-#ifdef WIN32
+#ifdef _WIN32
     if (fp->mode == 's')
       total = (ssize_t)recv(fp->fd, buf, (unsigned)bytes, 0);
     else
@@ -2579,7 +2711,7 @@ cups_read(cups_file_t *fp,                /* I - CUPS file */
       total = recv(fp->fd, buf, bytes, 0);
     else
       total = read(fp->fd, buf, bytes);
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
     DEBUG_printf(("9cups_read: total=" CUPS_LLFMT, CUPS_LLCAST total));
 
@@ -2617,8 +2749,7 @@ cups_write(cups_file_t *fp,               /* I - CUPS file */
   ssize_t      count;                  /* Count this time */
 
 
-  DEBUG_printf(("7cups_write(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", fp, buf,
-                CUPS_LLCAST bytes));
+  DEBUG_printf(("7cups_write(fp=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)fp, (void *)buf, CUPS_LLCAST bytes));
 
  /*
   * Loop until all bytes are written...
@@ -2627,7 +2758,7 @@ cups_write(cups_file_t *fp,               /* I - CUPS file */
   total = 0;
   while (bytes > 0)
   {
-#ifdef WIN32
+#ifdef _WIN32
     if (fp->mode == 's')
       count = (ssize_t)send(fp->fd, buf, (unsigned)bytes, 0);
     else
@@ -2637,7 +2768,7 @@ cups_write(cups_file_t *fp,               /* I - CUPS file */
       count = send(fp->fd, buf, bytes, 0);
     else
       count = write(fp->fd, buf, bytes);
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
     DEBUG_printf(("9cups_write: count=" CUPS_LLFMT, CUPS_LLCAST count));
 
@@ -2668,8 +2799,3 @@ cups_write(cups_file_t *fp,               /* I - CUPS file */
 
   return ((ssize_t)total);
 }
-
-
-/*
- * End of "$Id$".
- */