]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/file.c
81f43a97d0f9a6a0d3e3d41bfa5a8ef41c756dd3
4 * File functions for the Common UNIX Printing System (CUPS).
6 * Since stdio files max out at 256 files on many systems, we have to
7 * write similar functions without this limit. At the same time, using
8 * our own file functions allows us to provide transparent support of
9 * gzip'd print files, PPD files, etc.
11 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
13 * These coded instructions, statements, and computer programs are the
14 * property of Easy Software Products and are protected by Federal
15 * copyright law. Distribution and use rights are outlined in the file
16 * "LICENSE.txt" which should have been included with this file. If this
17 * file is missing or damaged please contact Easy Software Products
20 * Attn: CUPS Licensing Information
21 * Easy Software Products
22 * 44141 Airport View Drive, Suite 204
23 * Hollywood, Maryland 20636 USA
25 * Voice: (301) 373-9600
26 * EMail: cups-info@cups.org
27 * WWW: http://www.cups.org
31 * cupsFileClose() - Close a CUPS file.
32 * cupsFileCompression() - Return whether a file is compressed.
33 * cupsFileEOF() - Return the end-of-file status.
34 * cupsFileFlush() - Flush pending output.
35 * cupsFileGetChar() - Get a single character from a file.
36 * cupsFileGetConf() - Get a line from a configuration file...
37 * cupsFileGets() - Get a CR and/or LF-terminated line.
38 * cupsFileLock() - Temporarily lock access to a file.
39 * cupsFileNumber() - Return the file descriptor associated with a CUPS file.
40 * cupsFileOpen() - Open a CUPS file.
41 * cupsFileOpenFd() - Open a CUPS file using a file descriptor.
42 * cupsFilePeekChar() - Peek at the next character from a file.
43 * cupsFilePrintf() - Write a formatted string.
44 * cupsFilePutChar() - Write a character.
45 * cupsFilePuts() - Write a string.
46 * cupsFileRead() - Read from a file.
47 * cupsFileRewind() - Rewind a file.
48 * cupsFileSeek() - Seek in a file.
49 * cupsFileTell() - Return the current file position.
50 * cupsFileUnlock() - Unlock access to a file.
51 * cupsFileWrite() - Write to a file.
52 * cups_compress() - Compress a buffer of data...
53 * cups_fill() - Fill the input buffer...
54 * cups_read() - Read from a file descriptor.
55 * cups_write() - Write to a file descriptor.
59 * Include necessary headers...
67 #include <cups/debug.h>
68 #include <sys/types.h>
72 # include <winsock2.h>
76 # include <sys/socket.h>
77 # define closesocket(f) close(f)
83 #endif /* HAVE_LIBZ */
84 #include "http-private.h"
88 * Types and structures...
90 struct _cups_file_s
/**** CUPS file structure... ****/
93 int fd
; /* File descriptor */
94 char mode
, /* Mode ('r' or 'w') */
95 compressed
, /* Compression used? */
96 eof
, /* End of file? */
97 buf
[2048], /* Buffer */
98 *ptr
, /* Pointer into buffer */
99 *end
; /* End of buffer data */
100 off_t pos
; /* File position for start of buffer */
103 z_stream stream
; /* (De)compression stream */
104 Bytef cbuf
[1024]; /* (De)compression buffer */
105 uLong crc
; /* (De)compression CRC */
106 #endif /* HAVE_LIBZ */
115 static ssize_t
cups_compress(cups_file_t
*fp
, const char *buf
, size_t bytes
);
116 #endif /* HAVE_LIBZ */
117 static ssize_t
cups_fill(cups_file_t
*fp
);
118 static ssize_t
cups_read(cups_file_t
*fp
, char *buf
, size_t bytes
);
119 static ssize_t
cups_write(cups_file_t
*fp
, const char *buf
, size_t bytes
);
123 * 'cupsFileClose()' - Close a CUPS file.
126 int /* O - 0 on success, -1 on error */
127 cupsFileClose(cups_file_t
*fp
) /* I - CUPS file */
129 int fd
; /* File descriptor */
130 char mode
; /* Open mode */
131 int status
; /* Return status */
134 DEBUG_printf(("cupsFileClose(fp=%p)\n", fp
));
144 * Flush pending write data...
148 status
= cupsFileFlush(fp
);
153 if (fp
->compressed
&& status
>= 0)
158 * Free decompression data...
161 inflateEnd(&fp
->stream
);
166 * Flush any remaining compressed data...
169 unsigned char trailer
[8]; /* Trailer CRC and length */
170 int done
; /* Done writing... */
173 fp
->stream
.avail_in
= 0;
177 if (fp
->stream
.next_out
> fp
->cbuf
)
179 if (cups_write(fp
, (char *)fp
->cbuf
,
180 fp
->stream
.next_out
- fp
->cbuf
) < 0)
183 fp
->stream
.next_out
= fp
->cbuf
;
184 fp
->stream
.avail_out
= sizeof(fp
->cbuf
);
187 if (done
|| status
< 0)
190 done
= deflate(&fp
->stream
, Z_FINISH
) == Z_STREAM_END
&&
191 fp
->stream
.next_out
== fp
->cbuf
;
195 * Write the CRC and length...
198 trailer
[0] = fp
->crc
;
199 trailer
[1] = fp
->crc
>> 8;
200 trailer
[2] = fp
->crc
>> 16;
201 trailer
[3] = fp
->crc
>> 24;
202 trailer
[4] = fp
->pos
;
203 trailer
[5] = fp
->pos
>> 8;
204 trailer
[6] = fp
->pos
>> 16;
205 trailer
[7] = fp
->pos
>> 24;
207 if (cups_write(fp
, (char *)trailer
, 8) < 0)
211 * Free all memory used by the compression stream...
214 deflateEnd(&(fp
->stream
));
217 #endif /* HAVE_LIBZ */
220 * Save the file descriptor we used and free memory...
229 * Close the file, returning the close status...
234 if (closesocket(fd
) < 0)
248 * 'cupsFileCompression()' - Return whether a file is compressed.
251 int /* O - CUPS_FILE_NONE or CUPS_FILE_GZIP */
252 cupsFileCompression(cups_file_t
*fp
) /* I - CUPS file */
254 return (fp
->compressed
);
259 * 'cupsFileEOF()' - Return the end-of-file status.
262 int /* O - 1 on EOF, 0 otherwise */
263 cupsFileEOF(cups_file_t
*fp
) /* I - CUPS file */
270 * 'cupsFileFlush()' - Flush pending output.
273 int /* O - 0 on success, -1 on error */
274 cupsFileFlush(cups_file_t
*fp
) /* I - CUPS file */
276 size_t bytes
; /* Bytes to write */
279 DEBUG_printf(("cupsFileFlush(fp=%p)\n", fp
));
282 * Range check input...
285 if (!fp
|| fp
->mode
!= 'w')
287 DEBUG_puts(" Attempt to flush a read-only file...");
291 bytes
= fp
->ptr
- fp
->buf
;
296 bytes
= cups_compress(fp
, fp
->buf
, bytes
);
298 bytes
= cups_write(fp
, fp
->buf
, bytes
);
311 * 'cupsFileGetChar()' - Get a single character from a file.
314 int /* O - Character or -1 on EOF */
315 cupsFileGetChar(cups_file_t
*fp
) /* I - CUPS file */
318 * Range check input...
321 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's'))
325 * If the input buffer is empty, try to read more data...
328 if (fp
->ptr
>= fp
->end
)
329 if (cups_fill(fp
) < 0)
333 * Return the next character in the buffer...
336 return (*(fp
->ptr
)++ & 255);
341 * 'cupsFileGetConf()' - Get a line from a configuration file...
344 char * /* O - Line read of NULL on eof/error */
345 cupsFileGetConf(cups_file_t
*fp
, /* I - CUPS file */
346 char *buf
, /* O - String buffer */
347 size_t buflen
, /* I - Size of string buffer */
348 char **value
, /* O - Pointer to value */
349 int *linenum
) /* IO - Current line number */
351 char *ptr
; /* Pointer into line */
355 * Range check input...
358 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's') ||
359 !buf
|| buflen
< 2 || !value
)
368 * Read the next non-comment line...
373 while (cupsFileGets(fp
, buf
, buflen
))
378 * Strip any comments...
381 if ((ptr
= strchr(buf
, '#')) != NULL
)
385 if (!isspace(ptr
[-1] & 255))
395 * Strip leading whitespace...
398 for (ptr
= buf
; isspace(*ptr
& 255); ptr
++);
401 _cups_strcpy(buf
, ptr
);
404 * See if there is anything left...
410 * Yes, grab any value and return...
413 for (ptr
= buf
; *ptr
; ptr
++)
414 if (isspace(*ptr
& 255))
420 * Have a value, skip any other spaces...
423 while (isspace(*ptr
& 255))
430 * Strip trailing whitespace and > for lines that begin with <...
433 ptr
+= strlen(ptr
) - 1;
435 if (buf
[0] == '<' && *ptr
== '>')
437 else if (buf
[0] == '<' && *ptr
!= '>')
447 while (ptr
> *value
&& isspace(*ptr
& 255))
464 * 'cupsFileGets()' - Get a CR and/or LF-terminated line.
467 char * /* O - Line read or NULL on eof/error */
468 cupsFileGets(cups_file_t
*fp
, /* I - CUPS file */
469 char *buf
, /* O - String buffer */
470 size_t buflen
) /* I - Size of string buffer */
472 int ch
; /* Character from file */
473 char *ptr
, /* Current position in line buffer */
474 *end
; /* End of line buffer */
478 * Range check input...
481 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's') || !buf
|| buflen
< 2)
485 * Now loop until we have a valid line...
488 for (ptr
= buf
, end
= buf
+ buflen
- 1; ptr
< end
;)
490 if (fp
->ptr
>= fp
->end
)
491 if (cups_fill(fp
) <= 0)
507 if (fp
->ptr
>= fp
->end
)
508 if (cups_fill(fp
) <= 0)
511 if (*(fp
->ptr
) == '\n')
519 * Line feed ends a line...
535 * 'cupsFileLock()' - Temporarily lock access to a file.
538 int /* O - 0 on success, -1 on error */
539 cupsFileLock(cups_file_t
*fp
, /* I - File to lock */
540 int block
) /* I - 1 to wait for the lock, 0 to fail right away */
546 if (!fp
|| fp
->mode
== 's')
553 return (lockf(fp
->fd
, block
? F_LOCK
: F_TLOCK
, 0));
558 * 'cupsFileNumber()' - Return the file descriptor associated with a CUPS file.
561 int /* O - File descriptor */
562 cupsFileNumber(cups_file_t
*fp
) /* I - CUPS file */
569 * 'cupsFileOpen()' - Open a CUPS file.
572 cups_file_t
* /* O - CUPS file or NULL */
573 cupsFileOpen(const char *filename
, /* I - Name of file */
574 const char *mode
) /* I - Open mode */
576 cups_file_t
*fp
; /* New CUPS file */
577 int fd
; /* File descriptor */
578 char hostname
[1024], /* Hostname */
579 *portname
; /* Port "name" (number or service) */
580 int port
; /* Port number */
581 struct servent
*service
; /* Service */
582 int i
; /* Looping var */
583 int val
; /* Socket value */
584 struct hostent
*hostaddr
; /* Host address data */
585 http_addr_t sockaddr
; /* Socket address */
589 * Range check input...
592 if (!filename
|| !mode
||
593 (*mode
!= 'r' && *mode
!= 'w' && *mode
!= 'a' && *mode
!= 's'))
602 case 'a' : /* Append file */
603 fd
= open(filename
, O_RDWR
| O_CREAT
| O_APPEND
, 0666);
606 case 'r' : /* Read file */
607 fd
= open(filename
, O_RDONLY
, 0);
610 case 'w' : /* Write file */
611 fd
= open(filename
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
614 case 's' : /* Read/write socket */
615 strlcpy(hostname
, filename
, sizeof(hostname
));
616 if ((portname
= strrchr(hostname
, ':')) != NULL
)
621 if ((hostaddr
= httpGetHostByName(hostname
)) == NULL
)
624 if (isdigit(portname
[0] & 255))
625 port
= atoi(portname
);
626 else if ((service
= getservbyname(portname
, NULL
)) != NULL
)
627 port
= ntohs(service
->s_port
);
631 for (i
= 0, fd
= -1; hostaddr
->h_addr_list
[i
]; i
++)
634 * Load the address...
637 httpAddrLoad(hostaddr
, port
, i
, &sockaddr
);
643 if ((fd
= socket(sockaddr
.addr
.sa_family
, SOCK_STREAM
, 0)) < 0)
647 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(val
));
651 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &val
, sizeof(val
));
652 #endif /* SO_REUSEPORT */
655 * Using TCP_NODELAY improves responsiveness, especially on systems
656 * with a slow loopback interface... Since we write large buffers
657 * when sending print files and requests, there shouldn't be any
658 * performance penalty for this...
662 setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &val
, sizeof(val
));
665 * Connect to the server...
669 if (sockaddr
.addr
.sa_family
== AF_INET6
)
671 if (connect(fd
, (struct sockaddr
*)&sockaddr
,
672 sizeof(sockaddr
.ipv6
)) < 0)
679 #endif /* AF_INET6 */
680 if (connect(fd
, (struct sockaddr
*)&sockaddr
,
681 sizeof(sockaddr
.ipv4
)) < 0)
689 default : /* Remove bogus compiler warning... */
697 * Create the CUPS file structure...
700 if ((fp
= cupsFileOpenFd(fd
, mode
)) == NULL
)
716 * 'cupsFileOpenFd()' - Open a CUPS file using a file descriptor.
719 cups_file_t
* /* O - CUPS file or NULL */
720 cupsFileOpenFd(int fd
, /* I - File descriptor */
721 const char *mode
) /* I - Open mode */
723 cups_file_t
*fp
; /* New CUPS file */
727 * Range check input...
730 if (fd
< 0 || !mode
||
731 (*mode
!= 'r' && *mode
!= 'w' && *mode
!= 'a' && *mode
!= 's'))
738 if ((fp
= calloc(1, sizeof(cups_file_t
))) == NULL
)
753 fp
->end
= fp
->buf
+ sizeof(fp
->buf
);
756 if (mode
[1] >= '1' && mode
[1] <= '9')
759 * Open a compressed stream, so write the standard gzip file
763 unsigned char header
[10]; /* gzip file header */
764 time_t curtime
; /* Current time */
767 curtime
= time(NULL
);
770 header
[2] = Z_DEFLATED
;
773 header
[5] = curtime
>> 8;
774 header
[6] = curtime
>> 16;
775 header
[7] = curtime
>> 24;
779 cups_write(fp
, (char *)header
, 10);
782 * Initialize the compressor...
785 deflateInit2(&(fp
->stream
), mode
[1] - '0', Z_DEFLATED
, -15, 8,
788 fp
->stream
.next_out
= fp
->cbuf
;
789 fp
->stream
.avail_out
= sizeof(fp
->cbuf
);
791 fp
->crc
= crc32(0L, Z_NULL
, 0);
793 #endif /* HAVE_LIBZ */
804 default : /* Remove bogus compiler warning... */
809 * Don't pass this file to child processes...
812 fcntl(fp
->fd
, F_SETFD
, fcntl(fp
->fd
, F_GETFD
) | FD_CLOEXEC
);
819 * 'cupsFilePeekChar()' - Peek at the next character from a file.
822 int /* O - Character or -1 on EOF */
823 cupsFilePeekChar(cups_file_t
*fp
) /* I - CUPS file */
826 * Range check input...
829 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's'))
833 * If the input buffer is empty, try to read more data...
836 if (fp
->ptr
>= fp
->end
)
837 if (cups_fill(fp
) < 0)
841 * Return the next character in the buffer...
844 return (*(fp
->ptr
) & 255);
849 * 'cupsFilePrintf()' - Write a formatted string.
852 int /* O - Number of bytes written or -1 */
853 cupsFilePrintf(cups_file_t
*fp
, /* I - CUPS file */
854 const char *format
, /* I - Printf-style format string */
855 ...) /* I - Additional args as necessary */
857 va_list ap
; /* Argument list */
858 size_t bytes
; /* Formatted size */
859 char buf
[2048]; /* Formatted text */
862 if (!fp
|| !format
|| (fp
->mode
!= 'w' && fp
->mode
!= 's'))
865 va_start(ap
, format
);
866 bytes
= vsnprintf(buf
, sizeof(buf
), format
, ap
);
870 return (cups_write(fp
, buf
, bytes
));
872 if ((fp
->ptr
+ bytes
) > fp
->end
)
873 if (cupsFileFlush(fp
))
878 if (bytes
> sizeof(fp
->buf
))
881 return (cups_compress(fp
, buf
, bytes
));
883 return (cups_write(fp
, buf
, bytes
));
887 memcpy(fp
->ptr
, buf
, bytes
);
895 * 'cupsFilePutChar()' - Write a character.
898 int /* O - 0 on success, -1 on error */
899 cupsFilePutChar(cups_file_t
*fp
, /* I - CUPS file */
900 int c
) /* I - Character to write */
903 * Range check input...
906 if (!fp
|| (fp
->mode
!= 'w' && fp
->mode
!= 's'))
912 * Send character immediately over socket...
915 char ch
; /* Output character */
920 if (send(fp
->fd
, &ch
, 1, 0) < 1)
929 if (fp
->ptr
>= fp
->end
)
930 if (cupsFileFlush(fp
))
943 * 'cupsFilePuts()' - Write a string.
946 int /* O - Number of bytes written or -1 */
947 cupsFilePuts(cups_file_t
*fp
, /* I - CUPS file */
948 const char *s
) /* I - String to write */
950 size_t bytes
; /* Bytes to write */
954 * Range check input...
957 if (!fp
|| !s
|| (fp
->mode
!= 'w' && fp
->mode
!= 's'))
961 * Write the string...
968 if (cups_write(fp
, s
, bytes
) < 0)
976 if ((fp
->ptr
+ bytes
) > fp
->end
)
977 if (cupsFileFlush(fp
))
982 if (bytes
> sizeof(fp
->buf
))
985 return (cups_compress(fp
, s
, bytes
));
987 return (cups_write(fp
, s
, bytes
));
991 memcpy(fp
->ptr
, s
, bytes
);
999 * 'cupsFileRead()' - Read from a file.
1002 ssize_t
/* O - Number of bytes read or -1 */
1003 cupsFileRead(cups_file_t
*fp
, /* I - CUPS file */
1004 char *buf
, /* O - Buffer */
1005 size_t bytes
) /* I - Number of bytes to read */
1007 size_t total
, /* Total bytes read */
1008 count
; /* Bytes read */
1011 DEBUG_printf(("cupsFileRead(fp=%p, buf=%p, bytes=%ld)\n", fp
, buf
,
1015 * Range check input...
1018 if (!fp
|| !buf
|| bytes
< 0 || (fp
->mode
!= 'r' && fp
->mode
!= 's'))
1025 * Loop until all bytes are read...
1031 if (fp
->ptr
>= fp
->end
)
1032 if (cups_fill(fp
) <= 0)
1034 DEBUG_printf((" cups_fill() returned -1, total=%d\n", total
));
1042 count
= fp
->end
- fp
->ptr
;
1046 memcpy(buf
, fp
->ptr
, count
);
1050 * Update the counts for the last read...
1059 * Return the total number of bytes read...
1062 DEBUG_printf((" total=%d\n", total
));
1069 * 'cupsFileRewind()' - Rewind a file.
1072 off_t
/* O - New file position or -1 */
1073 cupsFileRewind(cups_file_t
*fp
) /* I - CUPS file */
1075 return (cupsFileSeek(fp
, 0L));
1080 * 'cupsFileSeek()' - Seek in a file.
1083 off_t
/* O - New file position or -1 */
1084 cupsFileSeek(cups_file_t
*fp
, /* I - CUPS file */
1085 off_t pos
) /* I - Position in file */
1087 size_t bytes
; /* Number bytes in buffer */
1090 DEBUG_printf(("cupsFileSeek(fp=%p, pos=%ld)\n", fp
, (long)pos
));
1091 DEBUG_printf((" fp->pos=%ld\n", (long)fp
->pos
));
1094 * Range check input...
1097 if (!fp
|| pos
< 0 || fp
->mode
!= 'r')
1101 * Figure out the number of bytes in the current buffer, and then
1102 * see if we are outside of it...
1105 bytes
= fp
->end
- fp
->buf
;
1111 * Need to seek backwards...
1117 inflateEnd(&fp
->stream
);
1119 lseek(fp
->fd
, 0, SEEK_SET
);
1124 while ((bytes
= cups_fill(fp
)) > 0)
1125 if (pos
>= fp
->pos
&& pos
< (fp
->pos
+ bytes
))
1132 #endif /* HAVE_LIBZ */
1134 fp
->pos
= lseek(fp
->fd
, pos
, SEEK_SET
);
1135 DEBUG_printf((" lseek() returned %ld...\n", (long)fp
->pos
));
1140 else if (pos
>= (fp
->pos
+ bytes
))
1143 * Need to seek forwards...
1149 while ((bytes
= cups_fill(fp
)) > 0)
1150 if (pos
>= fp
->pos
&& pos
< (fp
->pos
+ bytes
))
1157 #endif /* HAVE_LIBZ */
1159 fp
->pos
= lseek(fp
->fd
, pos
, SEEK_SET
);
1160 DEBUG_printf((" lseek() returned %ld...\n", (long)fp
->pos
));
1168 * Just reposition the current pointer, since we have the right
1172 fp
->ptr
= fp
->buf
+ pos
- fp
->pos
;
1173 DEBUG_puts((" seek inside buffer..."));
1181 * 'cupsFileTell()' - Return the current file position.
1184 off_t
/* O - File position */
1185 cupsFileTell(cups_file_t
*fp
) /* I - CUPS file */
1192 * 'cupsFileUnlock()' - Unlock access to a file.
1195 int /* O - 0 on success, -1 on error */
1196 cupsFileUnlock(cups_file_t
*fp
) /* I - File to lock */
1202 if (!fp
|| fp
->mode
== 's')
1209 return (lockf(fp
->fd
, F_ULOCK
, 0));
1214 * 'cupsFileWrite()' - Write to a file.
1217 ssize_t
/* O - Number of bytes written */
1218 cupsFileWrite(cups_file_t
*fp
, /* I - CUPS file */
1219 const char *buf
, /* I - Buffer */
1220 size_t bytes
) /* I - Number of bytes to write */
1223 * Range check input...
1226 if (!fp
|| !buf
|| bytes
< 0 || (fp
->mode
!= 'w' && fp
->mode
!= 's'))
1233 * Write the buffer...
1236 if (fp
->mode
== 's')
1238 if (cups_write(fp
, buf
, bytes
) < 0)
1246 if ((fp
->ptr
+ bytes
) > fp
->end
)
1247 if (cupsFileFlush(fp
))
1252 if (bytes
> sizeof(fp
->buf
))
1255 return (cups_compress(fp
, buf
, bytes
));
1257 return (cups_write(fp
, buf
, bytes
));
1261 memcpy(fp
->ptr
, buf
, bytes
);
1270 * 'cups_compress()' - Compress a buffer of data...
1273 static ssize_t
/* O - Number of bytes written or -1 */
1274 cups_compress(cups_file_t
*fp
, /* I - CUPS file */
1275 const char *buf
, /* I - Buffer */
1276 size_t bytes
) /* I - Number bytes */
1282 fp
->crc
= crc32(fp
->crc
, (const Bytef
*)buf
, bytes
);
1285 * Deflate the bytes...
1288 fp
->stream
.next_in
= (Bytef
*)buf
;
1289 fp
->stream
.avail_in
= bytes
;
1291 while (fp
->stream
.avail_in
> 0)
1294 * Flush the current buffer...
1297 if (fp
->stream
.avail_out
< (int)(sizeof(fp
->cbuf
) / 8))
1299 if (cups_write(fp
, (char *)fp
->cbuf
, fp
->stream
.next_out
- fp
->cbuf
) < 0)
1303 deflate(&(fp
->stream
), Z_NO_FLUSH
);
1308 #endif /* HAVE_LIBZ */
1312 * 'cups_fill()' - Fill the input buffer...
1315 static ssize_t
/* O - Number of bytes or -1 */
1316 cups_fill(cups_file_t
*fp
) /* I - CUPS file */
1318 ssize_t bytes
; /* Number of bytes read */
1320 const unsigned char *ptr
, /* Pointer into buffer */
1321 *end
; /* End of buffer */
1322 #endif /* HAVE_LIBZ */
1325 DEBUG_printf(("cups_fill(fp=%p)\n", fp
));
1326 DEBUG_printf((" fp->ptr=%p, fp->end=%p, fp->buf=%p, fp->pos=%ld\n",
1327 fp
->ptr
, fp
->end
, fp
->buf
, (long)fp
->pos
));
1330 * Update the "pos" element as needed...
1333 if (fp
->ptr
&& fp
->end
)
1334 fp
->pos
+= fp
->end
- fp
->buf
;
1337 while (!fp
->ptr
|| fp
->compressed
)
1340 * Check to see if we have read any data yet; if not, see if we have a
1341 * compressed file...
1347 * Reset the file position in case we are seeking...
1354 * Read the first bytes in the file to determine if we have a gzip'd
1358 if ((bytes
= cups_read(fp
, (char *)fp
->cbuf
, sizeof(fp
->cbuf
))) < 0)
1361 * Can't read from file!
1367 if (bytes
< 10 || fp
->cbuf
[0] != 0x1f || fp
->cbuf
[1] != 0x8b ||
1368 fp
->cbuf
[2] != 8 || (fp
->cbuf
[3] & 0xe0) != 0)
1371 * Not a gzip'd file!
1374 memcpy(fp
->buf
, fp
->cbuf
, bytes
);
1377 fp
->end
= fp
->buf
+ bytes
;
1383 * Parse header junk: extra data, original name, and comment...
1386 ptr
= (unsigned char *)fp
->cbuf
+ 10;
1387 end
= (unsigned char *)fp
->cbuf
+ bytes
;
1389 if (fp
->cbuf
[3] & 0x04)
1392 * Skip extra data...
1395 if ((ptr
+ 2) > end
)
1398 * Can't read from file!
1404 bytes
= ((unsigned char)ptr
[1] << 8) | (unsigned char)ptr
[0];
1410 * Can't read from file!
1417 if (fp
->cbuf
[3] & 0x08)
1420 * Skip original name data...
1423 while (ptr
< end
&& *ptr
)
1431 * Can't read from file!
1438 if (fp
->cbuf
[3] & 0x10)
1441 * Skip comment data...
1444 while (ptr
< end
&& *ptr
)
1452 * Can't read from file!
1459 if (fp
->cbuf
[3] & 0x02)
1462 * Skip header CRC data...
1470 * Can't read from file!
1478 * Setup the decompressor data...
1481 fp
->stream
.zalloc
= (alloc_func
)0;
1482 fp
->stream
.zfree
= (free_func
)0;
1483 fp
->stream
.opaque
= (voidpf
)0;
1484 fp
->stream
.next_in
= (Bytef
*)ptr
;
1485 fp
->stream
.next_out
= NULL
;
1486 fp
->stream
.avail_in
= end
- ptr
;
1487 fp
->stream
.avail_out
= 0;
1488 fp
->crc
= crc32(0L, Z_NULL
, 0);
1490 if (inflateInit2(&(fp
->stream
), -15) != Z_OK
)
1499 * If we have reached end-of-file, return immediately...
1506 * Fill the decompression buffer as needed...
1509 if (fp
->stream
.avail_in
== 0)
1511 if ((bytes
= cups_read(fp
, (char *)fp
->cbuf
, sizeof(fp
->cbuf
))) <= 0)
1514 fp
->stream
.next_in
= fp
->cbuf
;
1515 fp
->stream
.avail_in
= bytes
;
1519 * Decompress data from the buffer...
1522 fp
->stream
.next_out
= (Bytef
*)fp
->buf
;
1523 fp
->stream
.avail_out
= sizeof(fp
->buf
);
1525 if (inflate(&(fp
->stream
), Z_NO_FLUSH
) == Z_STREAM_END
)
1528 * Read the CRC and length...
1531 unsigned char trailer
[8]; /* Trailer bytes */
1532 uLong tcrc
; /* Trailer CRC */
1535 if (read(fp
->fd
, trailer
, sizeof(trailer
)) < sizeof(trailer
))
1538 * Can't get it, so mark end-of-file...
1545 tcrc
= (((((trailer
[3] << 8) | trailer
[2]) << 8) | trailer
[1]) << 8) |
1548 if (tcrc
!= fp
->crc
)
1551 * Bad CRC, mark end-of-file...
1559 * Otherwise, reset the current pointer so that we re-read the
1567 bytes
= sizeof(fp
->buf
) - fp
->stream
.avail_out
;
1570 * Return the decompressed data...
1574 fp
->end
= fp
->buf
+ bytes
;
1579 #endif /* HAVE_LIBZ */
1582 * Read a buffer's full of data...
1585 if ((bytes
= cups_read(fp
, fp
->buf
, sizeof(fp
->buf
))) <= 0)
1588 * Can't read from file!
1599 * Return the bytes we read...
1604 fp
->end
= fp
->buf
+ bytes
;
1611 * 'cups_read()' - Read from a file descriptor.
1614 static ssize_t
/* O - Number of bytes read or -1 */
1615 cups_read(cups_file_t
*fp
, /* I - CUPS file */
1616 char *buf
, /* I - Buffer */
1617 size_t bytes
) /* I - Number bytes */
1619 ssize_t total
; /* Total bytes read */
1623 * Loop until we read at least 0 bytes...
1628 if (fp
->mode
== 's')
1629 total
= recv(fp
->fd
, buf
, bytes
, 0);
1631 total
= read(fp
->fd
, buf
, bytes
);
1637 * Reads can be interrupted by signals and unavailable resources...
1640 if (errno
== EAGAIN
|| errno
== EINTR
)
1647 * Return the total number of bytes read...
1655 * 'cups_write()' - Write to a file descriptor.
1658 static ssize_t
/* O - Number of bytes written or -1 */
1659 cups_write(cups_file_t
*fp
, /* I - CUPS file */
1660 const char *buf
, /* I - Buffer */
1661 size_t bytes
) /* I - Number bytes */
1663 size_t total
, /* Total bytes written */
1664 count
; /* Count this time */
1668 * Loop until all bytes are written...
1674 if (fp
->mode
== 's')
1675 count
= send(fp
->fd
, buf
, bytes
, 0);
1677 count
= write(fp
->fd
, buf
, bytes
);
1682 * Writes can be interrupted by signals and unavailable resources...
1685 if (errno
== EAGAIN
|| errno
== EINTR
)
1692 * Update the counts for the last write call...
1701 * Return the total number of bytes written...