]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/file.c
2 * "$Id: file.c 6962 2007-09-17 20:35:47Z mike $"
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 2007-2008 by Apple Inc.
12 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
14 * These coded instructions, statements, and computer programs are the
15 * property of Apple Inc. and are protected by Federal copyright
16 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
17 * which should have been included with this file. If this file is
18 * file is missing or damaged, see the license at "http://www.cups.org/".
22 * cupsFileClose() - Close a CUPS file.
23 * cupsFileCompression() - Return whether a file is compressed.
24 * cupsFileEOF() - Return the end-of-file status.
25 * cupsFileFind() - Find a file using the specified path.
26 * cupsFileFlush() - Flush pending output.
27 * cupsFileGetChar() - Get a single character from a file.
28 * cupsFileGetConf() - Get a line from a configuration file...
29 * cupsFileGetLine() - Get a CR and/or LF-terminated line that may contain
31 * cupsFileGets() - Get a CR and/or LF-terminated line.
32 * cupsFileLock() - Temporarily lock access to a file.
33 * cupsFileNumber() - Return the file descriptor associated with a CUPS
35 * cupsFileOpen() - Open a CUPS file.
36 * cupsFileOpenFd() - Open a CUPS file using a file descriptor.
37 * cupsFilePeekChar() - Peek at the next character from a file.
38 * cupsFilePrintf() - Write a formatted string.
39 * cupsFilePutChar() - Write a character.
40 * cupsFilePuts() - Write a string.
41 * cupsFileRead() - Read from a file.
42 * cupsFileRewind() - Set the current file position to the beginning of
44 * cupsFileSeek() - Seek in a file.
45 * cupsFileStderr() - Return a CUPS file associated with stderr.
46 * cupsFileStdin() - Return a CUPS file associated with stdin.
47 * cupsFileStdout() - Return a CUPS file associated with stdout.
48 * cupsFileTell() - Return the current file position.
49 * cupsFileUnlock() - Unlock access to a file.
50 * cupsFileWrite() - Write to a file.
51 * cups_compress() - Compress a buffer of data...
52 * cups_fill() - Fill the input buffer...
53 * cups_read() - Read from a file descriptor.
54 * cups_write() - Write to a file descriptor.
58 * Include necessary headers...
65 #include <sys/types.h>
67 #include "http-private.h"
73 #endif /* HAVE_LIBZ */
76 # include <sys/locking.h>
81 * Some operating systems support large files via open flag O_LARGEFILE...
85 # define O_LARGEFILE 0
86 #endif /* !O_LARGEFILE */
90 * Some operating systems don't define O_BINARY, which is used by Microsoft
91 * and IBM to flag binary files...
96 #endif /* !O_BINARY */
100 * Types and structures...
103 struct _cups_file_s
/**** CUPS file structure... ****/
106 int fd
; /* File descriptor */
107 char mode
, /* Mode ('r' or 'w') */
108 compressed
, /* Compression used? */
109 is_stdio
, /* stdin/out/err? */
110 eof
, /* End of file? */
111 buf
[4096], /* Buffer */
112 *ptr
, /* Pointer into buffer */
113 *end
; /* End of buffer data */
114 off_t pos
; /* File position for start of buffer */
117 z_stream stream
; /* (De)compression stream */
118 Bytef cbuf
[4096]; /* (De)compression buffer */
119 uLong crc
; /* (De)compression CRC */
120 #endif /* HAVE_LIBZ */
129 static ssize_t
cups_compress(cups_file_t
*fp
, const char *buf
, size_t bytes
);
130 #endif /* HAVE_LIBZ */
131 static ssize_t
cups_fill(cups_file_t
*fp
);
132 static ssize_t
cups_read(cups_file_t
*fp
, char *buf
, size_t bytes
);
133 static ssize_t
cups_write(cups_file_t
*fp
, const char *buf
, size_t bytes
);
137 * 'cupsFileClose()' - Close a CUPS file.
142 int /* O - 0 on success, -1 on error */
143 cupsFileClose(cups_file_t
*fp
) /* I - CUPS file */
145 int fd
; /* File descriptor */
146 char mode
; /* Open mode */
147 int status
; /* Return status */
148 int is_stdio
; /* Is a stdio file? */
151 DEBUG_printf(("cupsFileClose(fp=%p)\n", fp
));
161 * Flush pending write data...
165 status
= cupsFileFlush(fp
);
170 if (fp
->compressed
&& status
>= 0)
175 * Free decompression data...
178 inflateEnd(&fp
->stream
);
183 * Flush any remaining compressed data...
186 unsigned char trailer
[8]; /* Trailer CRC and length */
187 int done
; /* Done writing... */
190 fp
->stream
.avail_in
= 0;
194 if (fp
->stream
.next_out
> fp
->cbuf
)
196 if (cups_write(fp
, (char *)fp
->cbuf
,
197 fp
->stream
.next_out
- fp
->cbuf
) < 0)
200 fp
->stream
.next_out
= fp
->cbuf
;
201 fp
->stream
.avail_out
= sizeof(fp
->cbuf
);
204 if (done
|| status
< 0)
207 done
= deflate(&fp
->stream
, Z_FINISH
) == Z_STREAM_END
&&
208 fp
->stream
.next_out
== fp
->cbuf
;
212 * Write the CRC and length...
215 trailer
[0] = fp
->crc
;
216 trailer
[1] = fp
->crc
>> 8;
217 trailer
[2] = fp
->crc
>> 16;
218 trailer
[3] = fp
->crc
>> 24;
219 trailer
[4] = fp
->pos
;
220 trailer
[5] = fp
->pos
>> 8;
221 trailer
[6] = fp
->pos
>> 16;
222 trailer
[7] = fp
->pos
>> 24;
224 if (cups_write(fp
, (char *)trailer
, 8) < 0)
228 * Free all memory used by the compression stream...
231 deflateEnd(&(fp
->stream
));
234 #endif /* HAVE_LIBZ */
237 * Save the file descriptor we used and free memory...
242 is_stdio
= fp
->is_stdio
;
247 * Close the file, returning the close status...
252 if (closesocket(fd
) < 0)
266 * 'cupsFileCompression()' - Return whether a file is compressed.
271 int /* O - @code CUPS_FILE_NONE@ or @code CUPS_FILE_GZIP@ */
272 cupsFileCompression(cups_file_t
*fp
) /* I - CUPS file */
274 return (fp
? fp
->compressed
: CUPS_FILE_NONE
);
279 * 'cupsFileEOF()' - Return the end-of-file status.
284 int /* O - 1 on end of file, 0 otherwise */
285 cupsFileEOF(cups_file_t
*fp
) /* I - CUPS file */
287 return (fp
? fp
->eof
: 1);
292 * 'cupsFileFind()' - Find a file using the specified path.
294 * This function allows the paths in the path string to be separated by
295 * colons (UNIX standard) or semicolons (Windows standard) and stores the
296 * result in the buffer supplied. If the file cannot be found in any of
297 * the supplied paths, @code NULL@ is returned. A @code NULL@ path only
298 * matches the current directory.
303 const char * /* O - Full path to file or @code NULL@ if not found */
304 cupsFileFind(const char *filename
, /* I - File to find */
305 const char *path
, /* I - Colon/semicolon-separated path */
306 int executable
, /* I - 1 = executable files, 0 = any file/dir */
307 char *buffer
, /* I - Filename buffer */
308 int bufsize
) /* I - Size of filename buffer */
310 char *bufptr
, /* Current position in buffer */
311 *bufend
; /* End of buffer */
315 * Range check input...
318 if (!filename
|| !buffer
|| bufsize
< 2)
324 * No path, so check current directory...
327 if (!access(filename
, 0))
329 strlcpy(buffer
, filename
, bufsize
);
337 * Now check each path and return the first match...
340 bufend
= buffer
+ bufsize
- 1;
346 if (*path
== ';' || (*path
== ':' && ((bufptr
- buffer
) > 1 || !isalpha(buffer
[0] & 255))))
348 if (*path
== ';' || *path
== ':')
351 if (bufptr
> buffer
&& bufptr
[-1] != '/' && bufptr
< bufend
)
354 strlcpy(bufptr
, filename
, bufend
- bufptr
);
357 if (!access(buffer
, 0))
359 if (!access(buffer
, executable
? X_OK
: 0))
362 DEBUG_printf(("cupsFileFind: Returning \"%s\"\n", buffer
));
368 else if (bufptr
< bufend
)
375 * Check the last path...
378 if (bufptr
> buffer
&& bufptr
[-1] != '/' && bufptr
< bufend
)
381 strlcpy(bufptr
, filename
, bufend
- bufptr
);
383 if (!access(buffer
, 0))
385 DEBUG_printf(("cupsFileFind: Returning \"%s\"\n", buffer
));
390 DEBUG_puts("cupsFileFind: Returning NULL");
397 * 'cupsFileFlush()' - Flush pending output.
402 int /* O - 0 on success, -1 on error */
403 cupsFileFlush(cups_file_t
*fp
) /* I - CUPS file */
405 ssize_t bytes
; /* Bytes to write */
408 DEBUG_printf(("cupsFileFlush(fp=%p)\n", fp
));
411 * Range check input...
414 if (!fp
|| fp
->mode
!= 'w')
416 DEBUG_puts(" Attempt to flush a read-only file...");
420 bytes
= (ssize_t
)(fp
->ptr
- fp
->buf
);
422 DEBUG_printf((" Flushing %ld bytes...\n", (long)bytes
));
428 bytes
= cups_compress(fp
, fp
->buf
, bytes
);
430 #endif /* HAVE_LIBZ */
431 bytes
= cups_write(fp
, fp
->buf
, bytes
);
444 * 'cupsFileGetChar()' - Get a single character from a file.
449 int /* O - Character or -1 on end of file */
450 cupsFileGetChar(cups_file_t
*fp
) /* I - CUPS file */
453 * Range check input...
456 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's'))
458 DEBUG_puts("cupsFileGetChar: Bad arguments!");
463 * If the input buffer is empty, try to read more data...
466 if (fp
->ptr
>= fp
->end
)
467 if (cups_fill(fp
) < 0)
469 DEBUG_puts("cupsFileGetChar: Unable to fill buffer!");
474 * Return the next character in the buffer...
477 DEBUG_printf(("cupsFileGetChar: Returning %d...\n", *(fp
->ptr
) & 255));
479 return (*(fp
->ptr
)++ & 255);
484 * 'cupsFileGetConf()' - Get a line from a configuration file...
489 char * /* O - Line read or @code NULL@ on end of file or error */
490 cupsFileGetConf(cups_file_t
*fp
, /* I - CUPS file */
491 char *buf
, /* O - String buffer */
492 size_t buflen
, /* I - Size of string buffer */
493 char **value
, /* O - Pointer to value */
494 int *linenum
) /* IO - Current line number */
496 char *ptr
; /* Pointer into line */
500 * Range check input...
503 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's') ||
504 !buf
|| buflen
< 2 || !value
)
513 * Read the next non-comment line...
518 while (cupsFileGets(fp
, buf
, buflen
))
523 * Strip any comments...
526 if ((ptr
= strchr(buf
, '#')) != NULL
)
528 if (ptr
> buf
&& ptr
[-1] == '\\')
531 _cups_strcpy(ptr
- 1, ptr
);
535 // Strip the comment and any trailing whitespace...
538 if (!isspace(ptr
[-1] & 255))
549 * Strip leading whitespace...
552 for (ptr
= buf
; isspace(*ptr
& 255); ptr
++);
555 _cups_strcpy(buf
, ptr
);
558 * See if there is anything left...
564 * Yes, grab any value and return...
567 for (ptr
= buf
; *ptr
; ptr
++)
568 if (isspace(*ptr
& 255))
574 * Have a value, skip any other spaces...
577 while (isspace(*ptr
& 255))
584 * Strip trailing whitespace and > for lines that begin with <...
587 ptr
+= strlen(ptr
) - 1;
589 if (buf
[0] == '<' && *ptr
== '>')
591 else if (buf
[0] == '<' && *ptr
!= '>')
601 while (ptr
> *value
&& isspace(*ptr
& 255))
618 * 'cupsFileGetLine()' - Get a CR and/or LF-terminated line that may
619 * contain binary data.
621 * This function differs from @link cupsFileGets@ in that the trailing CR
622 * and LF are preserved, as is any binary data on the line. The buffer is
623 * nul-terminated, however you should use the returned length to determine
624 * the number of bytes on the line.
629 size_t /* O - Number of bytes on line or 0 on end of file */
630 cupsFileGetLine(cups_file_t
*fp
, /* I - File to read from */
631 char *buf
, /* I - Buffer */
632 size_t buflen
) /* I - Size of buffer */
634 int ch
; /* Character from file */
635 char *ptr
, /* Current position in line buffer */
636 *end
; /* End of line buffer */
640 * Range check input...
643 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's') || !buf
|| buflen
< 3)
647 * Now loop until we have a valid line...
650 for (ptr
= buf
, end
= buf
+ buflen
- 2; ptr
< end
;)
652 if (fp
->ptr
>= fp
->end
)
653 if (cups_fill(fp
) <= 0)
656 *ptr
++ = ch
= *(fp
->ptr
)++;
664 if (fp
->ptr
>= fp
->end
)
665 if (cups_fill(fp
) <= 0)
668 if (*(fp
->ptr
) == '\n')
669 *ptr
++ = *(fp
->ptr
)++;
676 * Line feed ends a line...
690 * 'cupsFileGets()' - Get a CR and/or LF-terminated line.
695 char * /* O - Line read or @code NULL@ on end of file or error */
696 cupsFileGets(cups_file_t
*fp
, /* I - CUPS file */
697 char *buf
, /* O - String buffer */
698 size_t buflen
) /* I - Size of string buffer */
700 int ch
; /* Character from file */
701 char *ptr
, /* Current position in line buffer */
702 *end
; /* End of line buffer */
706 * Range check input...
709 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's') || !buf
|| buflen
< 2)
713 * Now loop until we have a valid line...
716 for (ptr
= buf
, end
= buf
+ buflen
- 1; ptr
< end
;)
718 if (fp
->ptr
>= fp
->end
)
719 if (cups_fill(fp
) <= 0)
735 if (fp
->ptr
>= fp
->end
)
736 if (cups_fill(fp
) <= 0)
739 if (*(fp
->ptr
) == '\n')
747 * Line feed ends a line...
763 * 'cupsFileLock()' - Temporarily lock access to a file.
768 int /* O - 0 on success, -1 on error */
769 cupsFileLock(cups_file_t
*fp
, /* I - CUPS file */
770 int block
) /* I - 1 to wait for the lock, 0 to fail right away */
776 if (!fp
|| fp
->mode
== 's')
784 return (locking(fp
->fd
, block
? _LK_LOCK
: _LK_NBLCK
, 0));
786 return (lockf(fp
->fd
, block
? F_LOCK
: F_TLOCK
, 0));
792 * 'cupsFileNumber()' - Return the file descriptor associated with a CUPS file.
797 int /* O - File descriptor */
798 cupsFileNumber(cups_file_t
*fp
) /* I - CUPS file */
808 * 'cupsFileOpen()' - Open a CUPS file.
810 * The "mode" parameter can be "r" to read, "w" to write, overwriting any
811 * existing file, "a" to append to an existing file or create a new file,
812 * or "s" to open a socket connection.
814 * When opening for writing ("w") or appending ("a"), an optional number from
815 * 1 to 9 can be supplied which enables Flate compression of the file.
817 * When opening a socket connection, the filename is a string of the form
818 * "address:port" or "hostname:port". The socket will make an IPv4 or IPv6
819 * connection as needed, generally preferring IPv6 connections when there is
825 cups_file_t
* /* O - CUPS file or @code NULL@ if the file or socket cannot be opened */
826 cupsFileOpen(const char *filename
, /* I - Name of file */
827 const char *mode
) /* I - Open mode */
829 cups_file_t
*fp
; /* New CUPS file */
830 int fd
; /* File descriptor */
831 char hostname
[1024], /* Hostname */
832 *portname
; /* Port "name" (number or service) */
833 http_addrlist_t
*addrlist
; /* Host address list */
836 DEBUG_printf(("cupsFileOpen(filename=\"%s\", mode=\"%s\")\n", filename
,
840 * Range check input...
843 if (!filename
|| !mode
||
844 (*mode
!= 'r' && *mode
!= 'w' && *mode
!= 'a' && *mode
!= 's'))
853 case 'a' : /* Append file */
854 fd
= open(filename
, O_RDWR
| O_CREAT
| O_APPEND
| O_LARGEFILE
| O_BINARY
, 0666);
857 case 'r' : /* Read file */
858 fd
= open(filename
, O_RDONLY
| O_LARGEFILE
| O_BINARY
, 0);
861 case 'w' : /* Write file */
862 fd
= open(filename
, O_WRONLY
| O_TRUNC
| O_CREAT
| O_LARGEFILE
| O_BINARY
, 0666);
865 case 's' : /* Read/write socket */
866 strlcpy(hostname
, filename
, sizeof(hostname
));
867 if ((portname
= strrchr(hostname
, ':')) != NULL
)
873 * Lookup the hostname and service...
876 if ((addrlist
= httpAddrGetList(hostname
, AF_UNSPEC
, portname
)) == NULL
)
880 * Connect to the server...
883 if (!httpAddrConnect(addrlist
, &fd
))
885 httpAddrFreeList(addrlist
);
889 httpAddrFreeList(addrlist
);
892 default : /* Remove bogus compiler warning... */
900 * Create the CUPS file structure...
903 if ((fp
= cupsFileOpenFd(fd
, mode
)) == NULL
)
919 * 'cupsFileOpenFd()' - Open a CUPS file using a file descriptor.
921 * The "mode" parameter can be "r" to read, "a" or "w" to write, or "s"
922 * to treat the file descriptor as a bidirectional socket connection.
924 * When opening for writing ("w") or appending ("a"), an optional number from
925 * 1 to 9 can be supplied which enables Flate compression of the file.
930 cups_file_t
* /* O - CUPS file or @code NULL@ if the file could not be opened */
931 cupsFileOpenFd(int fd
, /* I - File descriptor */
932 const char *mode
) /* I - Open mode */
934 cups_file_t
*fp
; /* New CUPS file */
937 DEBUG_printf(("cupsFileOpenFd(fd=%d, mode=\"%s\")\n", fd
, mode
));
940 * Range check input...
943 if (fd
< 0 || !mode
||
944 (*mode
!= 'r' && *mode
!= 'w' && *mode
!= 'a' && *mode
!= 's'))
951 if ((fp
= calloc(1, sizeof(cups_file_t
))) == NULL
)
966 fp
->end
= fp
->buf
+ sizeof(fp
->buf
);
969 if (mode
[1] >= '1' && mode
[1] <= '9')
972 * Open a compressed stream, so write the standard gzip file
976 unsigned char header
[10]; /* gzip file header */
977 time_t curtime
; /* Current time */
980 curtime
= time(NULL
);
983 header
[2] = Z_DEFLATED
;
986 header
[5] = curtime
>> 8;
987 header
[6] = curtime
>> 16;
988 header
[7] = curtime
>> 24;
992 cups_write(fp
, (char *)header
, 10);
995 * Initialize the compressor...
998 deflateInit2(&(fp
->stream
), mode
[1] - '0', Z_DEFLATED
, -15, 8,
1001 fp
->stream
.next_out
= fp
->cbuf
;
1002 fp
->stream
.avail_out
= sizeof(fp
->cbuf
);
1004 fp
->crc
= crc32(0L, Z_NULL
, 0);
1006 #endif /* HAVE_LIBZ */
1017 default : /* Remove bogus compiler warning... */
1022 * Don't pass this file to child processes...
1026 fcntl(fp
->fd
, F_SETFD
, fcntl(fp
->fd
, F_GETFD
) | FD_CLOEXEC
);
1034 * 'cupsFilePeekChar()' - Peek at the next character from a file.
1039 int /* O - Character or -1 on end of file */
1040 cupsFilePeekChar(cups_file_t
*fp
) /* I - CUPS file */
1043 * Range check input...
1046 if (!fp
|| (fp
->mode
!= 'r' && fp
->mode
!= 's'))
1050 * If the input buffer is empty, try to read more data...
1053 if (fp
->ptr
>= fp
->end
)
1054 if (cups_fill(fp
) < 0)
1058 * Return the next character in the buffer...
1061 return (*(fp
->ptr
) & 255);
1066 * 'cupsFilePrintf()' - Write a formatted string.
1071 int /* O - Number of bytes written or -1 on error */
1072 cupsFilePrintf(cups_file_t
*fp
, /* I - CUPS file */
1073 const char *format
, /* I - Printf-style format string */
1074 ...) /* I - Additional args as necessary */
1076 va_list ap
; /* Argument list */
1077 ssize_t bytes
; /* Formatted size */
1078 char buf
[8192]; /* Formatted text */
1081 DEBUG_printf(("cupsFilePrintf(fp=%p, format=\"%s\", ...)\n", fp
, format
));
1083 if (!fp
|| !format
|| (fp
->mode
!= 'w' && fp
->mode
!= 's'))
1086 va_start(ap
, format
);
1087 bytes
= vsnprintf(buf
, sizeof(buf
), format
, ap
);
1090 if (bytes
>= sizeof(buf
))
1093 if (fp
->mode
== 's')
1094 return (cups_write(fp
, buf
, bytes
));
1096 if ((fp
->ptr
+ bytes
) > fp
->end
)
1097 if (cupsFileFlush(fp
))
1102 if (bytes
> sizeof(fp
->buf
))
1106 return (cups_compress(fp
, buf
, bytes
));
1108 #endif /* HAVE_LIBZ */
1109 return (cups_write(fp
, buf
, bytes
));
1113 memcpy(fp
->ptr
, buf
, bytes
);
1121 * 'cupsFilePutChar()' - Write a character.
1126 int /* O - 0 on success, -1 on error */
1127 cupsFilePutChar(cups_file_t
*fp
, /* I - CUPS file */
1128 int c
) /* I - Character to write */
1131 * Range check input...
1134 if (!fp
|| (fp
->mode
!= 'w' && fp
->mode
!= 's'))
1137 if (fp
->mode
== 's')
1140 * Send character immediately over socket...
1143 char ch
; /* Output character */
1148 if (send(fp
->fd
, &ch
, 1, 0) < 1)
1157 if (fp
->ptr
>= fp
->end
)
1158 if (cupsFileFlush(fp
))
1171 * 'cupsFilePuts()' - Write a string.
1173 * Like the @code fputs@ function, no newline is appended to the string.
1178 int /* O - Number of bytes written or -1 on error */
1179 cupsFilePuts(cups_file_t
*fp
, /* I - CUPS file */
1180 const char *s
) /* I - String to write */
1182 ssize_t bytes
; /* Bytes to write */
1186 * Range check input...
1189 if (!fp
|| !s
|| (fp
->mode
!= 'w' && fp
->mode
!= 's'))
1193 * Write the string...
1196 bytes
= (int)strlen(s
);
1198 if (fp
->mode
== 's')
1200 if (cups_write(fp
, s
, bytes
) < 0)
1208 if ((fp
->ptr
+ bytes
) > fp
->end
)
1209 if (cupsFileFlush(fp
))
1214 if (bytes
> sizeof(fp
->buf
))
1218 return (cups_compress(fp
, s
, bytes
));
1220 #endif /* HAVE_LIBZ */
1221 return (cups_write(fp
, s
, bytes
));
1225 memcpy(fp
->ptr
, s
, bytes
);
1233 * 'cupsFileRead()' - Read from a file.
1238 ssize_t
/* O - Number of bytes read or -1 on error */
1239 cupsFileRead(cups_file_t
*fp
, /* I - CUPS file */
1240 char *buf
, /* O - Buffer */
1241 size_t bytes
) /* I - Number of bytes to read */
1243 size_t total
; /* Total bytes read */
1244 ssize_t count
; /* Bytes read */
1247 DEBUG_printf(("cupsFileRead(fp=%p, buf=%p, bytes=%ld)\n", fp
, buf
,
1251 * Range check input...
1254 if (!fp
|| !buf
|| bytes
< 0 || (fp
->mode
!= 'r' && fp
->mode
!= 's'))
1261 * Loop until all bytes are read...
1267 if (fp
->ptr
>= fp
->end
)
1268 if (cups_fill(fp
) <= 0)
1270 DEBUG_printf((" cups_fill() returned -1, total=%d\n", (int)total
));
1273 return ((ssize_t
)total
);
1278 count
= (ssize_t
)(fp
->end
- fp
->ptr
);
1279 if (count
> (ssize_t
)bytes
)
1280 count
= (ssize_t
)bytes
;
1282 memcpy(buf
, fp
->ptr
, count
);
1286 * Update the counts for the last read...
1295 * Return the total number of bytes read...
1298 DEBUG_printf((" total=%d\n", (int)total
));
1300 return ((ssize_t
)total
);
1305 * 'cupsFileRewind()' - Set the current file position to the beginning of the
1311 off_t
/* O - New file position or -1 on error */
1312 cupsFileRewind(cups_file_t
*fp
) /* I - CUPS file */
1315 * Range check input...
1318 if (!fp
|| fp
->mode
!= 'r')
1322 * Handle special cases...
1328 * No seeking necessary...
1341 * Otherwise, seek in the file and cleanup any compression buffers...
1347 inflateEnd(&fp
->stream
);
1350 #endif /* HAVE_LIBZ */
1352 lseek(fp
->fd
, 0, SEEK_SET
);
1364 * 'cupsFileSeek()' - Seek in a file.
1369 off_t
/* O - New file position or -1 on error */
1370 cupsFileSeek(cups_file_t
*fp
, /* I - CUPS file */
1371 off_t pos
) /* I - Position in file */
1373 ssize_t bytes
; /* Number bytes in buffer */
1376 DEBUG_printf(("cupsFileSeek(fp=%p, pos=" CUPS_LLFMT
")\n", fp
, pos
));
1377 DEBUG_printf((" fp->pos=" CUPS_LLFMT
"\n", fp
->pos
));
1378 DEBUG_printf((" fp->ptr=%p, fp->end=%p\n", fp
->ptr
, fp
->end
));
1381 * Range check input...
1384 if (!fp
|| pos
< 0 || fp
->mode
!= 'r')
1388 * Handle special cases...
1392 return (cupsFileRewind(fp
));
1397 * No seeking necessary...
1410 if (!fp
->compressed
&& !fp
->ptr
)
1413 * Preload a buffer to determine whether the file is compressed...
1416 if (cups_fill(fp
) < 0)
1419 #endif /* HAVE_LIBZ */
1422 * Figure out the number of bytes in the current buffer, and then
1423 * see if we are outside of it...
1427 bytes
= (ssize_t
)(fp
->end
- fp
->buf
);
1433 DEBUG_printf((" bytes=" CUPS_LLFMT
"\n", CUPS_LLCAST bytes
));
1438 * Need to seek backwards...
1441 DEBUG_puts(" SEEK BACKWARDS");
1446 inflateEnd(&fp
->stream
);
1448 lseek(fp
->fd
, 0, SEEK_SET
);
1453 while ((bytes
= cups_fill(fp
)) > 0)
1454 if (pos
>= fp
->pos
&& pos
< (fp
->pos
+ bytes
))
1460 fp
->ptr
= fp
->buf
+ pos
- fp
->pos
;
1463 #endif /* HAVE_LIBZ */
1465 fp
->pos
= lseek(fp
->fd
, pos
, SEEK_SET
);
1469 DEBUG_printf((" lseek() returned %ld...\n", (long)fp
->pos
));
1472 else if (pos
>= (fp
->pos
+ bytes
))
1475 * Need to seek forwards...
1478 DEBUG_puts(" SEEK FORWARDS");
1483 while ((bytes
= cups_fill(fp
)) > 0)
1485 if (pos
>= fp
->pos
&& pos
< (fp
->pos
+ bytes
))
1492 fp
->ptr
= fp
->buf
+ pos
- fp
->pos
;
1495 #endif /* HAVE_LIBZ */
1497 fp
->pos
= lseek(fp
->fd
, pos
, SEEK_SET
);
1501 DEBUG_printf((" lseek() returned " CUPS_LLFMT
"...\n", fp
->pos
));
1507 * Just reposition the current pointer, since we have the right
1511 DEBUG_puts(" SEEK INSIDE BUFFER");
1513 fp
->ptr
= fp
->buf
+ pos
- fp
->pos
;
1521 * 'cupsFileStderr()' - Return a CUPS file associated with stderr.
1526 cups_file_t
* /* O - CUPS file */
1527 cupsFileStderr(void)
1529 _cups_globals_t
*cg
= _cupsGlobals(); /* Pointer to library globals... */
1533 * Open file descriptor 2 as needed...
1536 if (!cg
->stdio_files
[2])
1539 * Flush any pending output on the stdio file...
1545 * Open file descriptor 2...
1548 if ((cg
->stdio_files
[2] = cupsFileOpenFd(2, "w")) != NULL
)
1549 cg
->stdio_files
[2]->is_stdio
= 1;
1552 return (cg
->stdio_files
[2]);
1557 * 'cupsFileStdin()' - Return a CUPS file associated with stdin.
1562 cups_file_t
* /* O - CUPS file */
1565 _cups_globals_t
*cg
= _cupsGlobals(); /* Pointer to library globals... */
1569 * Open file descriptor 0 as needed...
1572 if (!cg
->stdio_files
[0])
1575 * Open file descriptor 0...
1578 if ((cg
->stdio_files
[0] = cupsFileOpenFd(0, "r")) != NULL
)
1579 cg
->stdio_files
[0]->is_stdio
= 1;
1582 return (cg
->stdio_files
[0]);
1587 * 'cupsFileStdout()' - Return a CUPS file associated with stdout.
1592 cups_file_t
* /* O - CUPS file */
1593 cupsFileStdout(void)
1595 _cups_globals_t
*cg
= _cupsGlobals(); /* Pointer to library globals... */
1599 * Open file descriptor 1 as needed...
1602 if (!cg
->stdio_files
[1])
1605 * Flush any pending output on the stdio file...
1611 * Open file descriptor 1...
1614 if ((cg
->stdio_files
[1] = cupsFileOpenFd(1, "w")) != NULL
)
1615 cg
->stdio_files
[1]->is_stdio
= 1;
1618 return (cg
->stdio_files
[1]);
1623 * 'cupsFileTell()' - Return the current file position.
1628 off_t
/* O - File position */
1629 cupsFileTell(cups_file_t
*fp
) /* I - CUPS file */
1631 return (fp
? fp
->pos
: 0);
1636 * 'cupsFileUnlock()' - Unlock access to a file.
1641 int /* O - 0 on success, -1 on error */
1642 cupsFileUnlock(cups_file_t
*fp
) /* I - CUPS file */
1648 if (!fp
|| fp
->mode
== 's')
1656 return (locking(fp
->fd
, _LK_UNLCK
, 0));
1658 return (lockf(fp
->fd
, F_ULOCK
, 0));
1664 * 'cupsFileWrite()' - Write to a file.
1669 ssize_t
/* O - Number of bytes written or -1 on error */
1670 cupsFileWrite(cups_file_t
*fp
, /* I - CUPS file */
1671 const char *buf
, /* I - Buffer */
1672 size_t bytes
) /* I - Number of bytes to write */
1675 * Range check input...
1678 if (!fp
|| !buf
|| bytes
< 0 || (fp
->mode
!= 'w' && fp
->mode
!= 's'))
1685 * Write the buffer...
1688 if (fp
->mode
== 's')
1690 if (cups_write(fp
, buf
, bytes
) < 0)
1693 fp
->pos
+= (off_t
)bytes
;
1695 return ((ssize_t
)bytes
);
1698 if ((fp
->ptr
+ bytes
) > fp
->end
)
1699 if (cupsFileFlush(fp
))
1702 fp
->pos
+= (off_t
)bytes
;
1704 if (bytes
> sizeof(fp
->buf
))
1708 return (cups_compress(fp
, buf
, bytes
));
1710 #endif /* HAVE_LIBZ */
1711 return (cups_write(fp
, buf
, bytes
));
1715 memcpy(fp
->ptr
, buf
, bytes
);
1717 return ((ssize_t
)bytes
);
1724 * 'cups_compress()' - Compress a buffer of data...
1727 static ssize_t
/* O - Number of bytes written or -1 */
1728 cups_compress(cups_file_t
*fp
, /* I - CUPS file */
1729 const char *buf
, /* I - Buffer */
1730 size_t bytes
) /* I - Number bytes */
1732 DEBUG_printf(("cups_compress(fp=%p, buf=%p, bytes=%ld)\n", fp
, buf
,
1739 fp
->crc
= crc32(fp
->crc
, (const Bytef
*)buf
, bytes
);
1742 * Deflate the bytes...
1745 fp
->stream
.next_in
= (Bytef
*)buf
;
1746 fp
->stream
.avail_in
= bytes
;
1748 while (fp
->stream
.avail_in
> 0)
1751 * Flush the current buffer...
1754 DEBUG_printf((" avail_in=%d, avail_out=%d\n", fp
->stream
.avail_in
,
1755 fp
->stream
.avail_out
));
1757 if (fp
->stream
.avail_out
< (int)(sizeof(fp
->cbuf
) / 8))
1759 if (cups_write(fp
, (char *)fp
->cbuf
, fp
->stream
.next_out
- fp
->cbuf
) < 0)
1762 fp
->stream
.next_out
= fp
->cbuf
;
1763 fp
->stream
.avail_out
= sizeof(fp
->cbuf
);
1766 deflate(&(fp
->stream
), Z_NO_FLUSH
);
1771 #endif /* HAVE_LIBZ */
1775 * 'cups_fill()' - Fill the input buffer...
1778 static ssize_t
/* O - Number of bytes or -1 */
1779 cups_fill(cups_file_t
*fp
) /* I - CUPS file */
1781 ssize_t bytes
; /* Number of bytes read */
1783 int status
; /* Decompression status */
1784 const unsigned char *ptr
, /* Pointer into buffer */
1785 *end
; /* End of buffer */
1786 #endif /* HAVE_LIBZ */
1789 DEBUG_printf(("cups_fill(fp=%p)\n", fp
));
1790 DEBUG_printf((" fp->ptr=%p, fp->end=%p, fp->buf=%p, "
1791 "fp->pos=" CUPS_LLFMT
", fp->eof=%d\n",
1792 fp
->ptr
, fp
->end
, fp
->buf
, fp
->pos
, fp
->eof
));
1795 * Update the "pos" element as needed...
1798 if (fp
->ptr
&& fp
->end
)
1799 fp
->pos
+= (off_t
)(fp
->end
- fp
->buf
);
1802 DEBUG_printf((" fp->compressed=%d\n", fp
->compressed
));
1804 while (!fp
->ptr
|| fp
->compressed
)
1807 * Check to see if we have read any data yet; if not, see if we have a
1808 * compressed file...
1814 * Reset the file position in case we are seeking...
1820 * Read the first bytes in the file to determine if we have a gzip'd
1824 if ((bytes
= cups_read(fp
, (char *)fp
->buf
, sizeof(fp
->buf
))) < 0)
1827 * Can't read from file!
1830 DEBUG_printf((" cups_read() returned " CUPS_LLFMT
"!\n",
1831 CUPS_LLCAST bytes
));
1836 if (bytes
< 10 || fp
->buf
[0] != 0x1f ||
1837 (fp
->buf
[1] & 255) != 0x8b ||
1838 fp
->buf
[2] != 8 || (fp
->buf
[3] & 0xe0) != 0)
1841 * Not a gzip'd file!
1845 fp
->end
= fp
->buf
+ bytes
;
1847 DEBUG_printf((" returning " CUPS_LLFMT
"!\n", CUPS_LLCAST bytes
));
1853 * Parse header junk: extra data, original name, and comment...
1856 ptr
= (unsigned char *)fp
->buf
+ 10;
1857 end
= (unsigned char *)fp
->buf
+ bytes
;
1859 if (fp
->buf
[3] & 0x04)
1862 * Skip extra data...
1865 if ((ptr
+ 2) > end
)
1868 * Can't read from file!
1874 bytes
= ((unsigned char)ptr
[1] << 8) | (unsigned char)ptr
[0];
1880 * Can't read from file!
1887 if (fp
->buf
[3] & 0x08)
1890 * Skip original name data...
1893 while (ptr
< end
&& *ptr
)
1901 * Can't read from file!
1908 if (fp
->buf
[3] & 0x10)
1911 * Skip comment data...
1914 while (ptr
< end
&& *ptr
)
1922 * Can't read from file!
1929 if (fp
->buf
[3] & 0x02)
1932 * Skip header CRC data...
1940 * Can't read from file!
1948 * Copy the flate-compressed data to the compression buffer...
1951 if ((bytes
= end
- ptr
) > 0)
1952 memcpy(fp
->cbuf
, ptr
, bytes
);
1955 * Setup the decompressor data...
1958 fp
->stream
.zalloc
= (alloc_func
)0;
1959 fp
->stream
.zfree
= (free_func
)0;
1960 fp
->stream
.opaque
= (voidpf
)0;
1961 fp
->stream
.next_in
= (Bytef
*)fp
->cbuf
;
1962 fp
->stream
.next_out
= NULL
;
1963 fp
->stream
.avail_in
= bytes
;
1964 fp
->stream
.avail_out
= 0;
1965 fp
->crc
= crc32(0L, Z_NULL
, 0);
1967 if (inflateInit2(&(fp
->stream
), -15) != Z_OK
)
1976 * If we have reached end-of-file, return immediately...
1983 * Fill the decompression buffer as needed...
1986 if (fp
->stream
.avail_in
== 0)
1988 if ((bytes
= cups_read(fp
, (char *)fp
->cbuf
, sizeof(fp
->cbuf
))) <= 0)
1991 fp
->stream
.next_in
= fp
->cbuf
;
1992 fp
->stream
.avail_in
= bytes
;
1996 * Decompress data from the buffer...
1999 fp
->stream
.next_out
= (Bytef
*)fp
->buf
;
2000 fp
->stream
.avail_out
= sizeof(fp
->buf
);
2002 status
= inflate(&(fp
->stream
), Z_NO_FLUSH
);
2004 if (fp
->stream
.next_out
> (Bytef
*)fp
->buf
)
2005 fp
->crc
= crc32(fp
->crc
, (Bytef
*)fp
->buf
,
2006 fp
->stream
.next_out
- (Bytef
*)fp
->buf
);
2008 if (status
== Z_STREAM_END
)
2011 * Read the CRC and length...
2014 unsigned char trailer
[8]; /* Trailer bytes */
2015 uLong tcrc
; /* Trailer CRC */
2018 if (read(fp
->fd
, trailer
, sizeof(trailer
)) < sizeof(trailer
))
2021 * Can't get it, so mark end-of-file...
2028 tcrc
= (((((trailer
[3] << 8) | trailer
[2]) << 8) | trailer
[1]) << 8) |
2031 if (tcrc
!= fp
->crc
)
2034 * Bad CRC, mark end-of-file...
2037 DEBUG_printf(("cups_fill: tcrc=%08x, fp->crc=%08x\n",
2038 (unsigned int)tcrc
, (unsigned int)fp
->crc
));
2046 * Otherwise, reset the compressed flag so that we re-read the
2054 bytes
= sizeof(fp
->buf
) - fp
->stream
.avail_out
;
2057 * Return the decompressed data...
2061 fp
->end
= fp
->buf
+ bytes
;
2067 #endif /* HAVE_LIBZ */
2070 * Read a buffer's full of data...
2073 if ((bytes
= cups_read(fp
, fp
->buf
, sizeof(fp
->buf
))) <= 0)
2076 * Can't read from file!
2087 * Return the bytes we read...
2092 fp
->end
= fp
->buf
+ bytes
;
2099 * 'cups_read()' - Read from a file descriptor.
2102 static ssize_t
/* O - Number of bytes read or -1 */
2103 cups_read(cups_file_t
*fp
, /* I - CUPS file */
2104 char *buf
, /* I - Buffer */
2105 size_t bytes
) /* I - Number bytes */
2107 ssize_t total
; /* Total bytes read */
2111 * Loop until we read at least 0 bytes...
2117 if (fp
->mode
== 's')
2118 total
= (ssize_t
)recv(fp
->fd
, buf
, (unsigned)bytes
, 0);
2120 total
= (ssize_t
)read(fp
->fd
, buf
, (unsigned)bytes
);
2122 if (fp
->mode
== 's')
2123 total
= recv(fp
->fd
, buf
, bytes
, 0);
2125 total
= read(fp
->fd
, buf
, bytes
);
2132 * Reads can be interrupted by signals and unavailable resources...
2135 if (errno
== EAGAIN
|| errno
== EINTR
)
2142 * Return the total number of bytes read...
2150 * 'cups_write()' - Write to a file descriptor.
2153 static ssize_t
/* O - Number of bytes written or -1 */
2154 cups_write(cups_file_t
*fp
, /* I - CUPS file */
2155 const char *buf
, /* I - Buffer */
2156 size_t bytes
) /* I - Number bytes */
2158 size_t total
; /* Total bytes written */
2159 ssize_t count
; /* Count this time */
2162 DEBUG_printf(("cups_write(fp=%p, buf=%p, bytes=%ld)\n", fp
, buf
,
2166 * Loop until all bytes are written...
2173 if (fp
->mode
== 's')
2174 count
= (ssize_t
)send(fp
->fd
, buf
, (unsigned)bytes
, 0);
2176 count
= (ssize_t
)write(fp
->fd
, buf
, (unsigned)bytes
);
2178 if (fp
->mode
== 's')
2179 count
= send(fp
->fd
, buf
, bytes
, 0);
2181 count
= write(fp
->fd
, buf
, bytes
);
2187 * Writes can be interrupted by signals and unavailable resources...
2190 if (errno
== EAGAIN
|| errno
== EINTR
)
2196 DEBUG_printf((" count=%ld\n", (long)count
));
2199 * Update the counts for the last write call...
2208 * Return the total number of bytes written...
2211 return ((ssize_t
)total
);
2216 * End of "$Id: file.c 6962 2007-09-17 20:35:47Z mike $".