X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Ffile.c;h=e6e1f5b826f9d91d130891ab30c5036b45db3a75;hb=ffbf1e61ffbb56b95018ef4301e4ddb230b88468;hp=03d0f33e447061876fed5cd5c37df080ba1ca860;hpb=f7b064491c9a070105575fef5eb35988a0583f36;p=thirdparty%2Fcups.git diff --git a/cups/file.c b/cups/file.c index 03d0f33e4..e6e1f5b82 100644 --- a/cups/file.c +++ b/cups/file.c @@ -4,18 +4,13 @@ * 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. + * different line endings, gzip'd print files, PPD files, etc. * - * Copyright 2007-2015 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright © 2007-2019 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/". - * - * This file is subject to the Apple OS-Developed Software exception. + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ /* @@ -23,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... @@ -40,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. */ @@ -306,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 */ @@ -321,7 +350,6 @@ 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)", (void *)fp)); @@ -410,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); @@ -431,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); } @@ -444,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@ */ @@ -457,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 */ @@ -476,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 */ @@ -523,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); @@ -577,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 */ @@ -625,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 */ @@ -643,6 +675,12 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */ return (-1); } + if (fp->eof) + { + DEBUG_puts("5cupsFileGetChar: End-of-file!"); + return (-1); + } + /* * If the input buffer is empty, try to read more data... */ @@ -673,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 */ @@ -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 */ @@ -890,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 */ @@ -971,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 */ @@ -989,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 */ @@ -1029,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 */ @@ -1081,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 */ @@ -1151,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 */ @@ -1252,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 */ @@ -1295,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 */ @@ -1384,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); } } @@ -1392,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 */ @@ -1446,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 */ @@ -1507,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 */ @@ -1563,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); } } @@ -1571,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 */ @@ -1595,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... */ @@ -1647,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 */ @@ -1719,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 */ @@ -1871,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 */ @@ -1907,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 */ @@ -1937,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 */ @@ -1973,7 +2037,7 @@ 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 */ @@ -1989,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 */ @@ -2008,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 */ @@ -2466,6 +2530,8 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */ * file header... */ + inflateEnd(&fp->stream); + fp->compressed = 0; } else if (status < Z_OK) @@ -2540,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 */ /* @@ -2570,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... */ @@ -2609,7 +2675,7 @@ cups_open(const char *filename, /* I - Filename */ errno = EPERM; return (-1); } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ return (fd); } @@ -2635,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 @@ -2645,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)); @@ -2692,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 @@ -2702,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));