X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Ffile.c;h=e6e1f5b826f9d91d130891ab30c5036b45db3a75;hb=ffbf1e61ffbb56b95018ef4301e4ddb230b88468;hp=68fb118928b1f7da71e38b52e519a1cb554bb019;hpb=c7017eccd21da514f345a5c7a41156b1adf7cb35;p=thirdparty%2Fcups.git diff --git a/cups/file.c b/cups/file.c index 68fb11892..e6e1f5b82 100644 --- a/cups/file.c +++ b/cups/file.c @@ -1,57 +1,16 @@ /* - * "$Id: file.c 7672 2008-06-18 22:03:02Z mike $" + * File functions for CUPS. * - * 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 + * different line endings, gzip'd print files, PPD files, etc. * - * 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-2019 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * 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/". - * - * Contents: - * - * cupsFileClose() - Close a CUPS file. - * cupsFileCompression() - Return whether a file is compressed. - * cupsFileEOF() - Return the end-of-file status. - * cupsFileFind() - Find a file using the specified path. - * cupsFileFlush() - Flush pending output. - * cupsFileGetChar() - Get a single character from a file. - * cupsFileGetConf() - Get a line from a configuration file... - * cupsFileGetLine() - Get a CR and/or LF-terminated line that may contain - * binary data. - * cupsFileGets() - Get a CR and/or LF-terminated line. - * cupsFileLock() - Temporarily lock access to a file. - * cupsFileNumber() - Return the file descriptor associated with a CUPS - * file. - * cupsFileOpen() - Open a CUPS file. - * cupsFileOpenFd() - Open a CUPS file using a file descriptor. - * cupsFilePeekChar() - Peek at the next character from a file. - * cupsFilePrintf() - Write a formatted string. - * cupsFilePutChar() - Write a character. - * cupsFilePuts() - Write a string. - * cupsFileRead() - Read from a file. - * cupsFileRewind() - Set the current file position to the beginning of - * the file. - * cupsFileSeek() - Seek in a file. - * cupsFileStderr() - Return a CUPS file associated with stderr. - * cupsFileStdin() - Return a CUPS file associated with stdin. - * cupsFileStdout() - Return a CUPS file associated with stdout. - * cupsFileTell() - Return the current file position. - * cupsFileUnlock() - Unlock access to a file. - * cupsFileWrite() - Write to a file. - * cups_compress() - Compress a buffer of data... - * cups_fill() - Fill the input buffer... - * cups_read() - Read from a file descriptor. - * cups_write() - Write to a file descriptor. + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ /* @@ -59,9 +18,43 @@ */ #include "file-private.h" +#include "debug-internal.h" #include #include +# ifdef HAVE_LIBZ +# include +# 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... @@ -76,10 +69,279 @@ 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 +/* + * '_cupsFileCheck()' - Check the permissions of the given filename. + */ + +_cups_fc_result_t /* O - Check result */ +_cupsFileCheck( + const char *filename, /* I - Filename to check */ + _cups_fc_filetype_t filetype, /* I - Type of file checks? */ + int dorootchecks, /* I - Check for root permissions? */ + _cups_fc_func_t cb, /* I - Callback function */ + void *context) /* I - Context pointer for callback */ + +{ + struct stat fileinfo; /* File information */ + char message[1024], /* Message string */ + temp[1024], /* Parent directory filename */ + *ptr; /* Pointer into parent directory */ + _cups_fc_result_t result; /* Check result */ + + + /* + * Does the filename contain a relative path ("../")? + */ + + if (strstr(filename, "../")) + { + /* + * Yes, fail it! + */ + + result = _CUPS_FILE_CHECK_RELATIVE_PATH; + goto finishup; + } + + /* + * Does the program even exist and is it accessible? + */ + + if (stat(filename, &fileinfo)) + { + /* + * Nope... + */ + + result = _CUPS_FILE_CHECK_MISSING; + goto finishup; + } + + /* + * Check the execute bit... + */ + + result = _CUPS_FILE_CHECK_OK; + + switch (filetype) + { + case _CUPS_FILE_CHECK_DIRECTORY : + if (!S_ISDIR(fileinfo.st_mode)) + result = _CUPS_FILE_CHECK_WRONG_TYPE; + break; + + default : + if (!S_ISREG(fileinfo.st_mode)) + result = _CUPS_FILE_CHECK_WRONG_TYPE; + break; + } + + if (result) + goto finishup; + + /* + * Are we doing root checks? + */ + + if (!dorootchecks) + { + /* + * Nope, so anything (else) goes... + */ + + goto finishup; + } + + /* + * Verify permission of the file itself: + * + * 1. Must be owned by root + * 2. Must not be writable by group + * 3. Must not be setuid + * 4. Must not be writable by others + */ + + if (fileinfo.st_uid || /* 1. Must be owned by root */ + (fileinfo.st_mode & S_IWGRP) || /* 2. Must not be writable by group */ + (fileinfo.st_mode & S_ISUID) || /* 3. Must not be setuid */ + (fileinfo.st_mode & S_IWOTH)) /* 4. Must not be writable by others */ + { + result = _CUPS_FILE_CHECK_PERMISSIONS; + goto finishup; + } + + if (filetype == _CUPS_FILE_CHECK_DIRECTORY || + filetype == _CUPS_FILE_CHECK_FILE_ONLY) + goto finishup; + + /* + * Now check the containing directory... + */ + + strlcpy(temp, filename, sizeof(temp)); + if ((ptr = strrchr(temp, '/')) != NULL) + { + if (ptr == temp) + ptr[1] = '\0'; + else + *ptr = '\0'; + } + + if (stat(temp, &fileinfo)) + { + /* + * Doesn't exist?!? + */ + + result = _CUPS_FILE_CHECK_MISSING; + filetype = _CUPS_FILE_CHECK_DIRECTORY; + filename = temp; + + goto finishup; + } + + if (fileinfo.st_uid || /* 1. Must be owned by root */ + (fileinfo.st_mode & S_IWGRP) || /* 2. Must not be writable by group */ + (fileinfo.st_mode & S_ISUID) || /* 3. Must not be setuid */ + (fileinfo.st_mode & S_IWOTH)) /* 4. Must not be writable by others */ + { + result = _CUPS_FILE_CHECK_PERMISSIONS; + filetype = _CUPS_FILE_CHECK_DIRECTORY; + filename = temp; + } + + /* + * Common return point... + */ + + finishup: + + if (cb) + { + cups_lang_t *lang = cupsLangDefault(); + /* Localization information */ + + switch (result) + { + case _CUPS_FILE_CHECK_OK : + if (filetype == _CUPS_FILE_CHECK_DIRECTORY) + snprintf(message, sizeof(message), + _cupsLangString(lang, _("Directory \"%s\" permissions OK " + "(0%o/uid=%d/gid=%d).")), + filename, fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + else + snprintf(message, sizeof(message), + _cupsLangString(lang, _("File \"%s\" permissions OK " + "(0%o/uid=%d/gid=%d).")), + filename, fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + break; + + case _CUPS_FILE_CHECK_MISSING : + if (filetype == _CUPS_FILE_CHECK_DIRECTORY) + snprintf(message, sizeof(message), + _cupsLangString(lang, _("Directory \"%s\" not available: " + "%s")), + filename, strerror(errno)); + else + snprintf(message, sizeof(message), + _cupsLangString(lang, _("File \"%s\" not available: %s")), + filename, strerror(errno)); + break; + + case _CUPS_FILE_CHECK_PERMISSIONS : + if (filetype == _CUPS_FILE_CHECK_DIRECTORY) + snprintf(message, sizeof(message), + _cupsLangString(lang, _("Directory \"%s\" has insecure " + "permissions " + "(0%o/uid=%d/gid=%d).")), + filename, fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + else + snprintf(message, sizeof(message), + _cupsLangString(lang, _("File \"%s\" has insecure " + "permissions " + "(0%o/uid=%d/gid=%d).")), + filename, fileinfo.st_mode, (int)fileinfo.st_uid, + (int)fileinfo.st_gid); + break; + + case _CUPS_FILE_CHECK_WRONG_TYPE : + if (filetype == _CUPS_FILE_CHECK_DIRECTORY) + snprintf(message, sizeof(message), + _cupsLangString(lang, _("Directory \"%s\" is a file.")), + filename); + else + snprintf(message, sizeof(message), + _cupsLangString(lang, _("File \"%s\" is a directory.")), + filename); + break; + + case _CUPS_FILE_CHECK_RELATIVE_PATH : + if (filetype == _CUPS_FILE_CHECK_DIRECTORY) + snprintf(message, sizeof(message), + _cupsLangString(lang, _("Directory \"%s\" contains a " + "relative path.")), filename); + else + snprintf(message, sizeof(message), + _cupsLangString(lang, _("File \"%s\" contains a relative " + "path.")), filename); + break; + } + + (*cb)(context, result, message); + } + + return (result); +} + + +/* + * '_cupsFileCheckFilter()' - Report file check results as CUPS filter messages. + */ + +void +_cupsFileCheckFilter( + void *context, /* I - Context pointer (unused) */ + _cups_fc_result_t result, /* I - Result code */ + const char *message) /* I - Message text */ +{ + const char *prefix; /* Messaging prefix */ + + + (void)context; + + switch (result) + { + default : + case _CUPS_FILE_CHECK_OK : + prefix = "DEBUG2"; + break; + + case _CUPS_FILE_CHECK_MISSING : + case _CUPS_FILE_CHECK_WRONG_TYPE : + prefix = "ERROR"; + fputs("STATE: +cups-missing-filter-warning\n", stderr); + break; + + case _CUPS_FILE_CHECK_PERMISSIONS : + case _CUPS_FILE_CHECK_RELATIVE_PATH : + prefix = "ERROR"; + fputs("STATE: +cups-insecure-filter-warning\n", stderr); + break; + } + + fprintf(stderr, "%s: %s\n", prefix, message); +} +#endif /* !_WIN32 */ + + /* * 'cupsFileClose()' - Close a CUPS file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 0 on success, -1 on error */ @@ -88,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... @@ -137,7 +398,7 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */ if (fp->stream.next_out > fp->cbuf) { if (cups_write(fp, (char *)fp->cbuf, - fp->stream.next_out - fp->cbuf) < 0) + (size_t)(fp->stream.next_out - fp->cbuf)) < 0) status = -1; fp->stream.next_out = fp->cbuf; @@ -155,14 +416,14 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */ * Write the CRC and length... */ - trailer[0] = fp->crc; - trailer[1] = fp->crc >> 8; - trailer[2] = fp->crc >> 16; - trailer[3] = fp->crc >> 24; - trailer[4] = fp->pos; - trailer[5] = fp->pos >> 8; - trailer[6] = fp->pos >> 16; - trailer[7] = fp->pos >> 24; + trailer[0] = (unsigned char)fp->crc; + trailer[1] = (unsigned char)(fp->crc >> 8); + trailer[2] = (unsigned char)(fp->crc >> 16); + trailer[3] = (unsigned char)(fp->crc >> 24); + trailer[4] = (unsigned char)fp->pos; + trailer[5] = (unsigned char)(fp->pos >> 8); + trailer[6] = (unsigned char)(fp->pos >> 16); + trailer[7] = (unsigned char)(fp->pos >> 24); if (cups_write(fp, (char *)trailer, 8) < 0) status = -1; @@ -177,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); @@ -195,14 +463,11 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */ if (mode == 's') { - if (closesocket(fd) < 0) - status = -1; - } - else if (!is_stdio) - { - if (close(fd) < 0) + if (httpAddrClose(NULL, fd) < 0) status = -1; } + else if (close(fd) < 0) + status = -1; return (status); } @@ -211,7 +476,7 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */ /* * 'cupsFileCompression()' - Return whether a file is compressed. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - @code CUPS_FILE_NONE@ or @code CUPS_FILE_GZIP@ */ @@ -224,7 +489,7 @@ cupsFileCompression(cups_file_t *fp) /* I - CUPS file */ /* * 'cupsFileEOF()' - Return the end-of-file status. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 on end of file, 0 otherwise */ @@ -243,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/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ const char * /* O - Full path to file or @code NULL@ if not found */ @@ -261,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); @@ -276,7 +539,7 @@ cupsFileFind(const char *filename, /* I - File to find */ if (!access(filename, 0)) { - strlcpy(buffer, filename, bufsize); + strlcpy(buffer, filename, (size_t)bufsize); return (buffer); } else @@ -292,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, 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); @@ -328,7 +591,7 @@ cupsFileFind(const char *filename, /* I - File to find */ if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend) *bufptr++ = '/'; - strlcpy(bufptr, filename, bufend - bufptr); + strlcpy(bufptr, filename, (size_t)(bufend - bufptr)); if (!access(buffer, 0)) { @@ -346,7 +609,7 @@ cupsFileFind(const char *filename, /* I - File to find */ /* * 'cupsFileFlush()' - Flush pending output. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 0 on success, -1 on error */ @@ -355,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... @@ -376,17 +639,17 @@ cupsFileFlush(cups_file_t *fp) /* I - CUPS file */ { #ifdef HAVE_LIBZ if (fp->compressed) - bytes = cups_compress(fp, fp->buf, bytes); + bytes = cups_compress(fp, fp->buf, (size_t)bytes); else #endif /* HAVE_LIBZ */ - bytes = cups_write(fp, fp->buf, bytes); + bytes = cups_write(fp, fp->buf, (size_t)bytes); if (bytes < 0) return (-1); fp->ptr = fp->buf; } - + return (0); } @@ -394,7 +657,7 @@ cupsFileFlush(cups_file_t *fp) /* I - CUPS file */ /* * 'cupsFileGetChar()' - Get a single character from a file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - Character or -1 on end of file */ @@ -404,9 +667,17 @@ 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("3cupsFileGetChar: Bad arguments!"); + DEBUG_puts("5cupsFileGetChar: Bad arguments!"); + return (-1); + } + + if (fp->eof) + { + DEBUG_puts("5cupsFileGetChar: End-of-file!"); return (-1); } @@ -414,10 +685,12 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */ * 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("3cupsFileGetChar: Unable to fill buffer!"); + DEBUG_puts("5cupsFileGetChar: Unable to fill buffer!"); return (-1); } @@ -425,20 +698,20 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */ * Return the next character in the buffer... */ - DEBUG_printf(("3cupsFileGetChar: Returning %d...", *(fp->ptr) & 255)); + DEBUG_printf(("5cupsFileGetChar: Returning %d...", *(fp->ptr) & 255)); fp->pos ++; - DEBUG_printf(("4cupsFileGetChar: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); + DEBUG_printf(("6cupsFileGetChar: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); return (*(fp->ptr)++ & 255); } /* - * 'cupsFileGetConf()' - Get a line from a configuration file... + * 'cupsFileGetConf()' - Get a line from a configuration file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ char * /* O - Line read or @code NULL@ on end of file or error */ @@ -456,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) @@ -494,7 +766,7 @@ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ // Strip the comment and any trailing whitespace... while (ptr > buf) { - if (!isspace(ptr[-1] & 255)) + if (!_cups_isspace(ptr[-1])) break; ptr --; @@ -508,7 +780,7 @@ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ * Strip leading whitespace... */ - for (ptr = buf; isspace(*ptr & 255); ptr ++); + for (ptr = buf; _cups_isspace(*ptr); ptr ++); if (ptr > buf) _cups_strcpy(buf, ptr); @@ -524,7 +796,7 @@ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ */ for (ptr = buf; *ptr; ptr ++) - if (isspace(*ptr & 255)) + if (_cups_isspace(*ptr)) break; if (*ptr) @@ -533,7 +805,7 @@ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ * Have a value, skip any other spaces... */ - while (isspace(*ptr & 255)) + while (_cups_isspace(*ptr)) *ptr++ = '\0'; if (*ptr) @@ -557,7 +829,7 @@ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ return (buf); } - while (ptr > *value && isspace(*ptr & 255)) + while (ptr > *value && _cups_isspace(*ptr)) *ptr-- = '\0'; } @@ -582,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/Mac 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 */ @@ -599,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); @@ -650,14 +921,14 @@ cupsFileGetLine(cups_file_t *fp, /* I - File to read from */ DEBUG_printf(("4cupsFileGetLine: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); - return (ptr - buf); + return ((size_t)(ptr - buf)); } /* * 'cupsFileGets()' - Get a CR and/or LF-terminated line. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ char * /* O - Line read or @code NULL@ on end of file or error */ @@ -674,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); @@ -725,7 +995,7 @@ cupsFileGets(cups_file_t *fp, /* I - CUPS file */ break; } else - *ptr++ = ch; + *ptr++ = (char)ch; } *ptr = '\0'; @@ -739,7 +1009,7 @@ cupsFileGets(cups_file_t *fp, /* I - CUPS file */ /* * 'cupsFileLock()' - Temporarily lock access to a file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 0 on success, -1 on error */ @@ -757,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/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - File descriptor */ @@ -797,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/Mac 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 */ @@ -849,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 */ @@ -897,7 +1167,7 @@ cupsFileOpen(const char *filename, /* I - Name of file */ if ((fp = cupsFileOpenFd(fd, mode)) == NULL) { if (*mode == 's') - closesocket(fd); + httpAddrClose(NULL, fd); else close(fd); } @@ -919,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/Mac 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 */ @@ -980,10 +1250,10 @@ cupsFileOpenFd(int fd, /* I - File descriptor */ header[1] = 0x8b; header[2] = Z_DEFLATED; header[3] = 0; - header[4] = curtime; - header[5] = curtime >> 8; - header[6] = curtime >> 16; - header[7] = curtime >> 24; + header[4] = (unsigned char)curtime; + header[5] = (unsigned char)(curtime >> 8); + header[6] = (unsigned char)(curtime >> 16); + header[7] = (unsigned char)(curtime >> 24); header[8] = 0; header[9] = 0x03; @@ -1020,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/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - Character or -1 on end of file */ @@ -1049,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); /* @@ -1063,7 +1345,7 @@ cupsFilePeekChar(cups_file_t *fp) /* I - CUPS file */ /* * 'cupsFilePrintf()' - Write a formatted string. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - Number of bytes written or -1 on error */ @@ -1075,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); @@ -1108,11 +1390,11 @@ cupsFilePrintf(cups_file_t *fp, /* I - CUPS file */ if (bytes > 65535) return (-1); - if ((temp = realloc(fp->printf_buffer, bytes + 1)) == NULL) + if ((temp = realloc(fp->printf_buffer, (size_t)(bytes + 1))) == NULL) return (-1); fp->printf_buffer = temp; - fp->printf_size = bytes + 1; + fp->printf_size = (size_t)(bytes + 1); va_start(ap, format); bytes = vsnprintf(fp->printf_buffer, fp->printf_size, format, ap); @@ -1121,14 +1403,14 @@ cupsFilePrintf(cups_file_t *fp, /* I - CUPS file */ if (fp->mode == 's') { - if (cups_write(fp, fp->printf_buffer, bytes) < 0) + if (cups_write(fp, fp->printf_buffer, (size_t)bytes) < 0) return (-1); fp->pos += bytes; DEBUG_printf(("4cupsFilePrintf: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); - return (bytes); + return ((int)bytes); } if ((fp->ptr + bytes) > fp->end) @@ -1139,20 +1421,24 @@ cupsFilePrintf(cups_file_t *fp, /* I - CUPS file */ DEBUG_printf(("4cupsFilePrintf: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); - if (bytes > sizeof(fp->buf)) + if ((size_t)bytes > sizeof(fp->buf)) { #ifdef HAVE_LIBZ if (fp->compressed) - return (cups_compress(fp, fp->printf_buffer, bytes)); + return ((int)cups_compress(fp, fp->printf_buffer, (size_t)bytes)); else #endif /* HAVE_LIBZ */ - return (cups_write(fp, fp->printf_buffer, bytes)); + return ((int)cups_write(fp, fp->printf_buffer, (size_t)bytes)); } else { - memcpy(fp->ptr, fp->printf_buffer, bytes); + memcpy(fp->ptr, fp->printf_buffer, (size_t)bytes); fp->ptr += bytes; - return (bytes); + + if (fp->is_stdio && cupsFileFlush(fp)) + return (-1); + else + return ((int)bytes); } } @@ -1160,7 +1446,7 @@ cupsFilePrintf(cups_file_t *fp, /* I - CUPS file */ /* * 'cupsFilePutChar()' - Write a character. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 0 on success, -1 on error */ @@ -1183,7 +1469,7 @@ cupsFilePutChar(cups_file_t *fp, /* I - CUPS file */ char ch; /* Output character */ - ch = c; + ch = (char)c; if (send(fp->fd, &ch, 1, 0) < 1) return (-1); @@ -1198,7 +1484,7 @@ cupsFilePutChar(cups_file_t *fp, /* I - CUPS file */ if (cupsFileFlush(fp)) return (-1); - *(fp->ptr) ++ = c; + *(fp->ptr) ++ = (char)c; } fp->pos ++; @@ -1214,7 +1500,7 @@ cupsFilePutChar(cups_file_t *fp, /* I - CUPS file */ * * This function handles any comment escaping of the value. * - * @since CUPS 1.4/Mac OS X 10.6@ + * @since CUPS 1.4/macOS 10.6@ */ ssize_t /* O - Number of bytes written or -1 on error */ @@ -1245,7 +1531,7 @@ cupsFilePutConf(cups_file_t *fp, /* I - CUPS file */ * Need to quote the first # in the info string... */ - if ((temp = cupsFileWrite(fp, value, ptr - value)) < 0) + if ((temp = cupsFileWrite(fp, value, (size_t)(ptr - value))) < 0) return (-1); bytes += temp; @@ -1275,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/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - Number of bytes written or -1 on error */ @@ -1296,18 +1582,18 @@ cupsFilePuts(cups_file_t *fp, /* I - CUPS file */ * Write the string... */ - bytes = (int)strlen(s); + bytes = (ssize_t)strlen(s); if (fp->mode == 's') { - if (cups_write(fp, s, bytes) < 0) + if (cups_write(fp, s, (size_t)bytes) < 0) return (-1); fp->pos += bytes; DEBUG_printf(("4cupsFilePuts: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); - return (bytes); + return ((int)bytes); } if ((fp->ptr + bytes) > fp->end) @@ -1318,20 +1604,24 @@ cupsFilePuts(cups_file_t *fp, /* I - CUPS file */ DEBUG_printf(("4cupsFilePuts: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); - if (bytes > sizeof(fp->buf)) + if ((size_t)bytes > sizeof(fp->buf)) { #ifdef HAVE_LIBZ if (fp->compressed) - return (cups_compress(fp, s, bytes)); + return ((int)cups_compress(fp, s, (size_t)bytes)); else #endif /* HAVE_LIBZ */ - return (cups_write(fp, s, bytes)); + return ((int)cups_write(fp, s, (size_t)bytes)); } else { - memcpy(fp->ptr, s, bytes); + memcpy(fp->ptr, s, (size_t)bytes); fp->ptr += bytes; - return (bytes); + + if (fp->is_stdio && cupsFileFlush(fp)) + return (-1); + else + return ((int)bytes); } } @@ -1339,7 +1629,7 @@ cupsFilePuts(cups_file_t *fp, /* I - CUPS file */ /* * 'cupsFileRead()' - Read from a file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ ssize_t /* O - Number of bytes read or -1 on error */ @@ -1351,19 +1641,24 @@ 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... */ - if (!fp || !buf || bytes < 0 || (fp->mode != 'r' && fp->mode != 's')) + if (!fp || !buf || (fp->mode != 'r' && fp->mode != 's')) return (-1); if (bytes == 0) return (0); + if (fp->eof) + { + DEBUG_puts("5cupsFileRead: End-of-file!"); + return (-1); + } + /* * Loop until all bytes are read... */ @@ -1387,7 +1682,7 @@ cupsFileRead(cups_file_t *fp, /* I - CUPS file */ if (count > (ssize_t)bytes) count = (ssize_t)bytes; - memcpy(buf, fp->ptr, count); + memcpy(buf, fp->ptr,(size_t) count); fp->ptr += count; fp->pos += count; @@ -1397,8 +1692,8 @@ cupsFileRead(cups_file_t *fp, /* I - CUPS file */ * Update the counts for the last read... */ - bytes -= count; - total += count; + bytes -= (size_t)count; + total += (size_t)count; buf += count; } @@ -1416,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/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ off_t /* O - New file position or -1 on error */ @@ -1426,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') @@ -1488,7 +1783,7 @@ cupsFileRewind(cups_file_t *fp) /* I - CUPS file */ /* * 'cupsFileSeek()' - Seek in a file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ off_t /* O - New file position or -1 on error */ @@ -1498,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... @@ -1544,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 */ @@ -1641,7 +1935,7 @@ cupsFileSeek(cups_file_t *fp, /* I - CUPS file */ /* * 'cupsFileStderr()' - Return a CUPS file associated with stderr. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ cups_file_t * /* O - CUPS file */ @@ -1677,7 +1971,7 @@ cupsFileStderr(void) /* * 'cupsFileStdin()' - Return a CUPS file associated with stdin. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ cups_file_t * /* O - CUPS file */ @@ -1707,7 +2001,7 @@ cupsFileStdin(void) /* * 'cupsFileStdout()' - Return a CUPS file associated with stdout. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ cups_file_t * /* O - CUPS file */ @@ -1743,15 +2037,14 @@ cupsFileStdout(void) /* * 'cupsFileTell()' - Return the current file position. * - * @since CUPS 1.2/Mac 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); } @@ -1760,7 +2053,7 @@ cupsFileTell(cups_file_t *fp) /* I - CUPS file */ /* * 'cupsFileUnlock()' - Unlock access to a file. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 0 on success, -1 on error */ @@ -1770,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); @@ -1779,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/Mac OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ ssize_t /* O - Number of bytes written or -1 on error */ @@ -1802,10 +2095,9 @@ 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 || bytes < 0 || (fp->mode != 'w' && fp->mode != 's')) + if (!fp || !buf || (fp->mode != 'w' && fp->mode != 's')) return (-1); if (bytes == 0) @@ -1855,7 +2147,7 @@ cupsFileWrite(cups_file_t *fp, /* I - CUPS file */ #ifdef HAVE_LIBZ /* - * 'cups_compress()' - Compress a buffer of data... + * 'cups_compress()' - Compress a buffer of data. */ static ssize_t /* O - Number of bytes written or -1 */ @@ -1863,21 +2155,20 @@ 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... */ - fp->crc = crc32(fp->crc, (const Bytef *)buf, bytes); + fp->crc = crc32(fp->crc, (const Bytef *)buf, (uInt)bytes); /* * Deflate the bytes... */ fp->stream.next_in = (Bytef *)buf; - fp->stream.avail_in = bytes; + fp->stream.avail_in = (uInt)bytes; while (fp->stream.avail_in > 0) { @@ -1888,9 +2179,9 @@ cups_compress(cups_file_t *fp, /* I - CUPS file */ DEBUG_printf(("9cups_compress: avail_in=%d, avail_out=%d", fp->stream.avail_in, fp->stream.avail_out)); - if (fp->stream.avail_out < (int)(sizeof(fp->cbuf) / 8)) + if (fp->stream.avail_out < (uInt)(sizeof(fp->cbuf) / 8)) { - if (cups_write(fp, (char *)fp->cbuf, fp->stream.next_out - fp->cbuf) < 0) + if (cups_write(fp, (char *)fp->cbuf, (size_t)(fp->stream.next_out - fp->cbuf)) < 0) return (-1); fp->stream.next_out = fp->cbuf; @@ -1900,13 +2191,13 @@ cups_compress(cups_file_t *fp, /* I - CUPS file */ deflate(&(fp->stream), Z_NO_FLUSH); } - return (bytes); + return ((ssize_t)bytes); } #endif /* HAVE_LIBZ */ /* - * 'cups_fill()' - Fill the input buffer... + * 'cups_fill()' - Fill the input buffer. */ static ssize_t /* O - Number of bytes or -1 */ @@ -1920,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; @@ -1960,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); } @@ -1999,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); } @@ -2011,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); } } @@ -2032,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); } } @@ -2053,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); } } @@ -2071,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); } } @@ -2080,7 +2396,7 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */ */ if ((bytes = end - ptr) > 0) - memcpy(fp->cbuf, ptr, bytes); + memcpy(fp->cbuf, ptr, (size_t)bytes); /* * Setup the decompressor data... @@ -2091,12 +2407,19 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */ fp->stream.opaque = (voidpf)0; fp->stream.next_in = (Bytef *)fp->cbuf; fp->stream.next_out = NULL; - fp->stream.avail_in = bytes; + fp->stream.avail_in = (uInt)bytes; 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; } @@ -2108,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... @@ -2117,10 +2444,16 @@ 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 = bytes; + fp->stream.avail_in = (uInt)bytes; } /* @@ -2134,7 +2467,7 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */ if (fp->stream.next_out > (Bytef *)fp->buf) fp->crc = crc32(fp->crc, (Bytef *)fp->buf, - fp->stream.next_out - (Bytef *)fp->buf); + (uInt)(fp->stream.next_out - (Bytef *)fp->buf)); if (status == Z_STREAM_END) { @@ -2144,45 +2477,74 @@ 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)) < sizeof(trailer)) + if (fp->stream.avail_in > 0) { - /* - * Can't get it, so mark end-of-file... - */ - - fp->eof = 1; + if (fp->stream.avail_in > sizeof(trailer)) + tbytes = (ssize_t)sizeof(trailer); + else + tbytes = (ssize_t)fp->stream.avail_in; + + memcpy(trailer, fp->stream.next_in, (size_t)tbytes); + fp->stream.next_in += tbytes; + fp->stream.avail_in -= (size_t)tbytes; } - else - { - tcrc = (((((trailer[3] << 8) | trailer[2]) << 8) | trailer[1]) << 8) | - 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)); - bytes = sizeof(fp->buf) - fp->stream.avail_out; + fp->eof = 1; + errno = EIO; + + return (-1); + } + + bytes = (ssize_t)sizeof(fp->buf) - (ssize_t)fp->stream.avail_out; /* * Return the decompressed data... @@ -2192,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 */ @@ -2210,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); } @@ -2239,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 */ /* @@ -2269,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... */ @@ -2308,7 +2675,7 @@ cups_open(const char *filename, /* I - Filename */ errno = EPERM; return (-1); } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ return (fd); } @@ -2326,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... @@ -2335,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 @@ -2345,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)); @@ -2383,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... @@ -2393,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 @@ -2403,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)); @@ -2423,8 +2788,8 @@ cups_write(cups_file_t *fp, /* I - CUPS file */ * Update the counts for the last write call... */ - bytes -= count; - total += count; + bytes -= (size_t)count; + total += (size_t)count; buf += count; } @@ -2434,8 +2799,3 @@ cups_write(cups_file_t *fp, /* I - CUPS file */ return ((ssize_t)total); } - - -/* - * End of "$Id: file.c 7672 2008-06-18 22:03:02Z mike $". - */