]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/raster.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / raster.c
1 /*
2 * "$Id: raster.c 6061 2006-10-23 00:26:52Z mike $"
3 *
4 * Raster file routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * This file is part of the CUPS Imaging library.
9 *
10 * These coded instructions, statements, and computer programs are the
11 * property of Easy Software Products and are protected by Federal
12 * copyright law. Distribution and use rights are outlined in the file
13 * "LICENSE.txt" which should have been included with this file. If this
14 * file is missing or damaged please contact Easy Software Products
15 * at:
16 *
17 * Attn: CUPS Licensing Information
18 * Easy Software Products
19 * 44141 Airport View Drive, Suite 204
20 * Hollywood, Maryland 20636 USA
21 *
22 * Voice: (301) 373-9600
23 * EMail: cups-info@cups.org
24 * WWW: http://www.cups.org
25 *
26 * This file is subject to the Apple OS-Developed Software exception.
27 *
28 * Contents:
29 *
30 * cupsRasterClose() - Close a raster stream.
31 * cupsRasterOpen() - Open a raster stream.
32 * cupsRasterReadHeader() - Read a raster page header and store it in a
33 * V1 page header structure.
34 * cupsRasterReadHeader2() - Read a raster page header and store it in a
35 * V2 page header structure.
36 * cupsRasterReadPixels() - Read raster pixels.
37 * cupsRasterWriteHeader() - Write a raster page header from a V1 page
38 * header structure.
39 * cupsRasterWriteHeader2() - Write a raster page header from a V2 page
40 * header structure.
41 * cupsRasterWritePixels() - Write raster pixels.
42 * cups_raster_read() - Read through the raster buffer.
43 * cups_raster_read_header() - Read a raster page header.
44 * cups_raster_update() - Update the raster header and row count for the
45 * current page.
46 * cups_read() - Read bytes from a file.
47 * cups_swap() - Swap bytes in raster data...
48 * cups_write() - Write bytes to a file.
49 */
50
51 /*
52 * Include necessary headers...
53 */
54
55 #include "raster.h"
56 #include <cups/debug.h>
57 #include <stdlib.h>
58 #include <errno.h>
59 #include <cups/string.h>
60
61 #if defined(WIN32) || defined(__EMX__)
62 # include <io.h>
63 #else
64 # include <unistd.h>
65 #endif /* WIN32 || __EMX__ */
66
67
68 /*
69 * Private structures...
70 */
71
72 struct _cups_raster_s /**** Raster stream data ****/
73 {
74 unsigned sync; /* Sync word from start of stream */
75 int fd; /* File descriptor */
76 cups_mode_t mode; /* Read/write mode */
77 cups_page_header2_t header; /* Raster header for current page */
78 int count, /* Current row run-length count */
79 remaining, /* Remaining rows in page image */
80 bpp; /* Bytes per pixel/color */
81 unsigned char *pixels, /* Pixels for current row */
82 *pend, /* End of pixel buffer */
83 *pcurrent; /* Current byte in pixel buffer */
84 int compressed, /* Non-zero if data is compressed */
85 swapped; /* Non-zero if data is byte-swapped */
86 unsigned char *buffer, /* Read/write buffer */
87 *bufptr, /* Current (read) position in buffer */
88 *bufend; /* End of current (read) buffer */
89 int bufsize; /* Buffer size */
90 };
91
92
93 /*
94 * Local functions...
95 */
96
97 static unsigned cups_raster_read_header(cups_raster_t *r);
98 static int cups_raster_read(cups_raster_t *r, unsigned char *buf,
99 int bytes);
100 static void cups_raster_update(cups_raster_t *r);
101 static int cups_read(int fd, unsigned char *buf, int bytes);
102 static void cups_swap(unsigned char *buf, int bytes);
103 static int cups_write(int fd, const unsigned char *buf, int bytes);
104
105
106 /*
107 * 'cupsRasterClose()' - Close a raster stream.
108 */
109
110 void
111 cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
112 {
113 if (r != NULL)
114 {
115 if (r->buffer)
116 free(r->buffer);
117
118 if (r->pixels)
119 free(r->pixels);
120
121 free(r);
122 }
123 }
124
125
126 /*
127 * 'cupsRasterOpen()' - Open a raster stream.
128 */
129
130 cups_raster_t * /* O - New stream */
131 cupsRasterOpen(int fd, /* I - File descriptor */
132 cups_mode_t mode) /* I - Mode */
133 {
134 cups_raster_t *r; /* New stream */
135
136
137 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
138 return (NULL);
139
140 r->fd = fd;
141 r->mode = mode;
142
143 if (mode == CUPS_RASTER_READ)
144 {
145 /*
146 * Open for read - get sync word...
147 */
148
149 if (!cups_read(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync)))
150 {
151 free(r);
152 return (NULL);
153 }
154
155 if (r->sync != CUPS_RASTER_SYNC &&
156 r->sync != CUPS_RASTER_REVSYNC &&
157 r->sync != CUPS_RASTER_SYNCv1 &&
158 r->sync != CUPS_RASTER_REVSYNCv1 &&
159 r->sync != CUPS_RASTER_SYNCv2 &&
160 r->sync != CUPS_RASTER_REVSYNCv2)
161 {
162 free(r);
163 return (NULL);
164 }
165
166 if (r->sync == CUPS_RASTER_SYNCv2 ||
167 r->sync == CUPS_RASTER_REVSYNCv2)
168 r->compressed = 1;
169
170 if (r->sync == CUPS_RASTER_REVSYNC ||
171 r->sync == CUPS_RASTER_REVSYNCv1 ||
172 r->sync == CUPS_RASTER_REVSYNCv2)
173 r->swapped = 1;
174 }
175 else
176 {
177 /*
178 * Open for write - put sync word...
179 */
180
181 r->sync = CUPS_RASTER_SYNC;
182
183 if (cups_write(r->fd, (unsigned char *)&(r->sync), sizeof(r->sync))
184 < sizeof(r->sync))
185 {
186 free(r);
187 return (NULL);
188 }
189 }
190
191 return (r);
192 }
193
194
195 /*
196 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
197 * V1 page header structure.
198 */
199
200 unsigned /* O - 1 on success, 0 on fail */
201 cupsRasterReadHeader(
202 cups_raster_t *r, /* I - Raster stream */
203 cups_page_header_t *h) /* I - Pointer to header data */
204 {
205 /*
206 * Get the raster header...
207 */
208
209 if (!cups_raster_read_header(r))
210 return (0);
211
212 /*
213 * Copy the header to the user-supplied buffer...
214 */
215
216 memcpy(h, &(r->header), sizeof(cups_page_header_t));
217
218 return (1);
219 }
220
221
222 /*
223 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
224 * V2 page header structure.
225 *
226 * @since CUPS 1.2@
227 */
228
229 unsigned /* O - 1 on success, 0 on fail */
230 cupsRasterReadHeader2(
231 cups_raster_t *r, /* I - Raster stream */
232 cups_page_header2_t *h) /* I - Pointer to header data */
233 {
234 /*
235 * Get the raster header...
236 */
237
238 if (!cups_raster_read_header(r))
239 return (0);
240
241 /*
242 * Copy the header to the user-supplied buffer...
243 */
244
245 memcpy(h, &(r->header), sizeof(cups_page_header2_t));
246
247 return (1);
248 }
249
250
251 /*
252 * 'cupsRasterReadPixels()' - Read raster pixels.
253 */
254
255 unsigned /* O - Number of bytes read */
256 cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */
257 unsigned char *p, /* I - Pointer to pixel buffer */
258 unsigned len) /* I - Number of bytes to read */
259 {
260 int bytes; /* Bytes read */
261 unsigned cupsBytesPerLine; /* cupsBytesPerLine value */
262 unsigned remaining; /* Bytes remaining */
263 unsigned char *ptr, /* Pointer to read buffer */
264 byte, /* Byte from file */
265 *temp; /* Pointer into buffer */
266 int count; /* Repetition count */
267
268
269 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0)
270 return (0);
271
272 if (!r->compressed)
273 {
274 /*
275 * Read without compression...
276 */
277
278 r->remaining -= len / r->header.cupsBytesPerLine;
279
280 if (!cups_read(r->fd, p, len))
281 return (0);
282
283 /*
284 * Swap bytes as needed...
285 */
286
287 if ((r->header.cupsBitsPerColor == 16 ||
288 r->header.cupsBitsPerPixel == 12 ||
289 r->header.cupsBitsPerPixel == 16) &&
290 r->swapped)
291 cups_swap(p, len);
292
293 /*
294 * Return...
295 */
296
297 return (len);
298 }
299
300 /*
301 * Read compressed data...
302 */
303
304 remaining = len;
305 cupsBytesPerLine = r->header.cupsBytesPerLine;
306
307 while (remaining > 0 && r->remaining > 0)
308 {
309 if (r->count == 0)
310 {
311 /*
312 * Need to read a new row...
313 */
314
315 if (remaining == cupsBytesPerLine)
316 ptr = p;
317 else
318 ptr = r->pixels;
319
320 /*
321 * Read using a modified TIFF "packbits" compression...
322 */
323
324 if (!cups_raster_read(r, &byte, 1))
325 return (0);
326
327 r->count = byte + 1;
328
329 if (r->count > 1)
330 ptr = r->pixels;
331
332 temp = ptr;
333 bytes = cupsBytesPerLine;
334
335 while (bytes > 0)
336 {
337 /*
338 * Get a new repeat count...
339 */
340
341 if (!cups_raster_read(r, &byte, 1))
342 return (0);
343
344 if (byte & 128)
345 {
346 /*
347 * Copy N literal pixels...
348 */
349
350 count = (257 - byte) * r->bpp;
351
352 if (count > bytes)
353 count = bytes;
354
355 if (!cups_raster_read(r, temp, count))
356 return (0);
357
358 temp += count;
359 bytes -= count;
360 }
361 else
362 {
363 /*
364 * Repeat the next N bytes...
365 */
366
367 count = (byte + 1) * r->bpp;
368 if (count > bytes)
369 count = bytes;
370
371 if (count < r->bpp)
372 break;
373
374 bytes -= count;
375
376 if (!cups_raster_read(r, temp, r->bpp))
377 return (0);
378
379 temp += r->bpp;
380 count -= r->bpp;
381
382 while (count > 0)
383 {
384 memcpy(temp, temp - r->bpp, r->bpp);
385 temp += r->bpp;
386 count -= r->bpp;
387 }
388 }
389 }
390
391 /*
392 * Swap bytes as needed...
393 */
394
395 if ((r->header.cupsBitsPerColor == 16 ||
396 r->header.cupsBitsPerPixel == 12 ||
397 r->header.cupsBitsPerPixel == 16) &&
398 r->swapped)
399 cups_swap(ptr, bytes);
400
401 /*
402 * Update pointers...
403 */
404
405 if (remaining >= cupsBytesPerLine)
406 {
407 bytes = cupsBytesPerLine;
408 r->pcurrent = r->pixels;
409 r->count --;
410 r->remaining --;
411 }
412 else
413 {
414 bytes = remaining;
415 r->pcurrent = r->pixels + bytes;
416 }
417
418 /*
419 * Copy data as needed...
420 */
421
422 if (ptr != p)
423 memcpy(p, ptr, bytes);
424 }
425 else
426 {
427 /*
428 * Copy fragment from buffer...
429 */
430
431 if ((bytes = r->pend - r->pcurrent) > remaining)
432 bytes = remaining;
433
434 memcpy(p, r->pcurrent, bytes);
435 r->pcurrent += bytes;
436
437 if (r->pcurrent >= r->pend)
438 {
439 r->pcurrent = r->pixels;
440 r->count --;
441 r->remaining --;
442 }
443 }
444
445 remaining -= bytes;
446 p += bytes;
447 }
448
449 return (len);
450 }
451
452
453 /*
454 * 'cupsRasterWriteHeader()' - Write a raster page header from a V1 page
455 * header structure.
456 */
457
458 unsigned /* O - 1 on success, 0 on failure */
459 cupsRasterWriteHeader(
460 cups_raster_t *r, /* I - Raster stream */
461 cups_page_header_t *h) /* I - Raster page header */
462 {
463 if (r == NULL || r->mode != CUPS_RASTER_WRITE)
464 return (0);
465
466 /*
467 * Make a copy of the header, and compute the number of raster
468 * lines in the page image...
469 */
470
471 memset(&(r->header), 0, sizeof(r->header));
472 memcpy(&(r->header), h, sizeof(cups_page_header_t));
473
474 cups_raster_update(r);
475
476 /*
477 * Write the raster header...
478 */
479
480 return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header))
481 > 0);
482 }
483
484
485 /*
486 * 'cupsRasterWriteHeader2()' - Write a raster page header from a V2 page
487 * header structure.
488 *
489 * @since CUPS 1.2@
490 */
491
492 unsigned /* O - 1 on success, 0 on failure */
493 cupsRasterWriteHeader2(
494 cups_raster_t *r, /* I - Raster stream */
495 cups_page_header2_t *h) /* I - Raster page header */
496 {
497 if (r == NULL || r->mode != CUPS_RASTER_WRITE)
498 return (0);
499
500 /*
501 * Make a copy of the header, and compute the number of raster
502 * lines in the page image...
503 */
504
505 memcpy(&(r->header), h, sizeof(cups_page_header2_t));
506
507 cups_raster_update(r);
508
509 /*
510 * Write the raster header...
511 */
512
513 return (cups_write(r->fd, (unsigned char *)&(r->header), sizeof(r->header))
514 > 0);
515 }
516
517
518 /*
519 * 'cupsRasterWritePixels()' - Write raster pixels.
520 */
521
522 unsigned /* O - Number of bytes written */
523 cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
524 unsigned char *p, /* I - Bytes to write */
525 unsigned len)/* I - Number of bytes to write */
526 {
527 #ifdef DEBUG
528 fprintf(stderr, "cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
529 r, p, len, r->remaining);
530 #endif /* DEBUG */
531
532 if (r == NULL || r->mode != CUPS_RASTER_WRITE || r->remaining == 0)
533 return (0);
534
535 /*
536 * No write compression, just write the raster data raw...
537 */
538
539 r->remaining -= len / r->header.cupsBytesPerLine;
540
541 return (cups_write(r->fd, p, len));
542 }
543
544
545 /*
546 * 'cups_raster_read_header()' - Read a raster page header.
547 */
548
549 static unsigned /* O - 1 on success, 0 on fail */
550 cups_raster_read_header(
551 cups_raster_t *r) /* I - Raster stream */
552 {
553 int len; /* Number of words to swap */
554 union swap_s /* Swapping structure */
555 {
556 unsigned char b[4];
557 unsigned v;
558 } *s;
559
560
561 if (r == NULL || r->mode != CUPS_RASTER_READ)
562 return (0);
563
564 /*
565 * Get the length of the raster header...
566 */
567
568 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
569 len = sizeof(cups_page_header_t);
570 else
571 len = sizeof(cups_page_header2_t);
572
573 /*
574 * Read the header...
575 */
576
577 memset(&(r->header), 0, sizeof(r->header));
578
579 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < len)
580 return (0);
581
582 /*
583 * Swap bytes as needed...
584 */
585
586 if (r->swapped)
587 for (len = 81, s = (union swap_s *)&(r->header.AdvanceDistance);
588 len > 0;
589 len --, s ++)
590 s->v = (((((s->b[3] << 8) | s->b[2]) << 8) | s->b[1]) << 8) | s->b[0];
591
592 /*
593 * Update the header and row count...
594 */
595
596 cups_raster_update(r);
597
598 return (1);
599 }
600
601
602 /*
603 * 'cups_raster_read()' - Read through the raster buffer.
604 */
605
606 static int /* O - Number of bytes read */
607 cups_raster_read(cups_raster_t *r, /* I - Raster stream */
608 unsigned char *buf, /* I - Buffer */
609 int bytes) /* I - Number of bytes to read */
610 {
611 int count, /* Number of bytes read */
612 remaining, /* Remaining bytes in buffer */
613 total; /* Total bytes read */
614
615
616 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r, buf, bytes));
617
618 if (!r->compressed)
619 return (cups_read(r->fd, buf, bytes));
620
621 /*
622 * Allocate a read buffer as needed...
623 */
624
625 count = 2 * r->header.cupsBytesPerLine;
626
627 if (count > r->bufsize)
628 {
629 int offset = r->bufptr - r->buffer; /* Offset to current start of buffer */
630 int end = r->bufend - r->buffer; /* Offset to current end of buffer */
631 unsigned char *rptr; /* Pointer in read buffer */
632
633 if (r->buffer)
634 rptr = realloc(r->buffer, count);
635 else
636 rptr = malloc(count);
637
638 if (!rptr)
639 return (0);
640
641 r->buffer = rptr;
642 r->bufptr = rptr + offset;
643 r->bufend = rptr + end;
644 r->bufsize = count;
645 }
646
647 /*
648 * Loop until we have read everything...
649 */
650
651 for (total = 0, remaining = r->bufend - r->bufptr;
652 total < bytes;
653 total += count, buf += count)
654 {
655 count = bytes - total;
656
657 DEBUG_printf(("count=%d, remaining=%d, buf=%p, bufptr=%p, bufend=%p...\n",
658 count, remaining, buf, r->bufptr, r->bufend));
659
660 if (remaining == 0)
661 {
662 if (count < 16)
663 {
664 /*
665 * Read into the raster buffer and then copy...
666 */
667
668 remaining = cups_read(r->fd, r->buffer, r->bufsize);
669 if (remaining <= 0)
670 return (0);
671
672 r->bufptr = r->buffer;
673 r->bufend = r->buffer + remaining;
674 }
675 else
676 {
677 /*
678 * Read directly into "buf"...
679 */
680
681 count = cups_read(r->fd, buf, count);
682
683 if (count <= 0)
684 return (0);
685
686 continue;
687 }
688 }
689
690 /*
691 * Copy bytes from raster buffer to "buf"...
692 */
693
694 if (count > remaining)
695 count = remaining;
696
697 if (count == 1)
698 {
699 /*
700 * Copy 1 byte...
701 */
702
703 *buf = *(r->bufptr)++;
704 remaining --;
705 }
706 else if (count < 128)
707 {
708 /*
709 * Copy up to 127 bytes without using memcpy(); this is
710 * faster because it avoids an extra function call and is
711 * often further optimized by the compiler...
712 */
713
714 unsigned char *bufptr; /* Temporary buffer pointer */
715
716
717 remaining -= count;
718
719 for (bufptr = r->bufptr; count > 0; count --, total ++)
720 *buf++ = *bufptr++;
721
722 r->bufptr = bufptr;
723 }
724 else
725 {
726 /*
727 * Use memcpy() for a large read...
728 */
729
730 memcpy(buf, r->bufptr, count);
731 r->bufptr += count;
732 remaining -= count;
733 }
734 }
735
736 return (total);
737 }
738
739
740 /*
741 * 'cups_raster_update()' - Update the raster header and row count for the
742 * current page.
743 */
744
745 static void
746 cups_raster_update(cups_raster_t *r) /* I - Raster stream */
747 {
748 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
749 r->header.cupsNumColors == 0)
750 {
751 /*
752 * Set the "cupsNumColors" field according to the colorspace...
753 */
754
755 switch (r->header.cupsColorSpace)
756 {
757 case CUPS_CSPACE_W :
758 case CUPS_CSPACE_K :
759 case CUPS_CSPACE_WHITE :
760 case CUPS_CSPACE_GOLD :
761 case CUPS_CSPACE_SILVER :
762 r->header.cupsNumColors = 1;
763 break;
764
765 case CUPS_CSPACE_RGB :
766 case CUPS_CSPACE_CMY :
767 case CUPS_CSPACE_YMC :
768 case CUPS_CSPACE_CIEXYZ :
769 case CUPS_CSPACE_CIELab :
770 case CUPS_CSPACE_ICC1 :
771 case CUPS_CSPACE_ICC2 :
772 case CUPS_CSPACE_ICC3 :
773 case CUPS_CSPACE_ICC4 :
774 case CUPS_CSPACE_ICC5 :
775 case CUPS_CSPACE_ICC6 :
776 case CUPS_CSPACE_ICC7 :
777 case CUPS_CSPACE_ICC8 :
778 case CUPS_CSPACE_ICC9 :
779 case CUPS_CSPACE_ICCA :
780 case CUPS_CSPACE_ICCB :
781 case CUPS_CSPACE_ICCC :
782 case CUPS_CSPACE_ICCD :
783 case CUPS_CSPACE_ICCE :
784 case CUPS_CSPACE_ICCF :
785 r->header.cupsNumColors = 3;
786 break;
787
788 case CUPS_CSPACE_RGBA :
789 case CUPS_CSPACE_RGBW :
790 case CUPS_CSPACE_CMYK :
791 case CUPS_CSPACE_YMCK :
792 case CUPS_CSPACE_KCMY :
793 case CUPS_CSPACE_GMCK :
794 case CUPS_CSPACE_GMCS :
795 r->header.cupsNumColors = 4;
796 break;
797
798 case CUPS_CSPACE_KCMYcm :
799 if (r->header.cupsBitsPerPixel < 8)
800 r->header.cupsNumColors = 6;
801 else
802 r->header.cupsNumColors = 4;
803 break;
804 }
805 }
806
807 /*
808 * Set the number of bytes per pixel/color...
809 */
810
811 if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
812 r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
813 else
814 r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
815
816 /*
817 * Set the number of remaining rows...
818 */
819
820 if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
821 r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
822 else
823 r->remaining = r->header.cupsHeight;
824
825 /*
826 * Allocate the compression buffer...
827 */
828
829 if (r->compressed)
830 {
831 if (r->pixels != NULL)
832 free(r->pixels);
833
834 r->pixels = calloc(r->header.cupsBytesPerLine, 1);
835 r->pcurrent = r->pixels;
836 r->pend = r->pixels + r->header.cupsBytesPerLine;
837 r->count = 0;
838 }
839 }
840
841
842 /*
843 * 'cups_read()' - Read bytes from a file.
844 */
845
846 static int /* O - Bytes read or -1 */
847 cups_read(int fd, /* I - File descriptor */
848 unsigned char *buf, /* I - Buffer for read */
849 int bytes) /* I - Number of bytes to read */
850 {
851 int count, /* Number of bytes read */
852 total; /* Total bytes read */
853
854
855 for (total = 0; total < bytes; total += count, buf += count)
856 {
857 count = read(fd, buf, bytes - total);
858
859 if (count == 0)
860 return (0);
861 else if (count < 0)
862 {
863 if (errno == EINTR)
864 count = 0;
865 else
866 return (-1);
867 }
868 }
869
870 return (total);
871 }
872
873
874 /*
875 * 'cups_swap()' - Swap bytes in raster data...
876 */
877
878 static void
879 cups_swap(unsigned char *buf, /* I - Buffer to swap */
880 int bytes) /* I - Number of bytes to swap */
881 {
882 unsigned char even, odd; /* Temporary variables */
883
884
885 bytes /= 2;
886
887 while (bytes > 0)
888 {
889 even = buf[0];
890 odd = buf[1];
891 buf[0] = odd;
892 buf[1] = even;
893
894 buf += 2;
895 bytes --;
896 }
897 }
898
899
900 /*
901 * 'cups_write()' - Write bytes to a file.
902 */
903
904 static int /* O - Bytes written or -1 */
905 cups_write(int fd, /* I - File descriptor */
906 const unsigned char *buf, /* I - Bytes to write */
907 int bytes) /* I - Number of bytes to write */
908 {
909 int count, /* Number of bytes written */
910 total; /* Total bytes written */
911
912
913 for (total = 0; total < bytes; total += count, buf += count)
914 {
915 count = write(fd, buf, bytes - total);
916
917 if (count < 0)
918 {
919 if (errno == EINTR)
920 count = 0;
921 else
922 return (-1);
923 }
924 }
925
926 return (total);
927 }
928
929
930 /*
931 * End of "$Id: raster.c 6061 2006-10-23 00:26:52Z mike $".
932 */