• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Raster error handling for CUPS.
3  *
4  * Copyright 2007-2015 by Apple Inc.
5  * Copyright 2007 by Easy Software Products.
6  *
7  * These coded instructions, statements, and computer programs are the
8  * property of Apple Inc. and are protected by Federal copyright
9  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
10  * which should have been included with this file.  If this file is
11  * missing or damaged, see the license at "http://www.cups.org/".
12  *
13  * This file is subject to the Apple OS-Developed Software exception.
14  */
15 
16 /*
17  * Include necessary headers...
18  */
19 
20 #include <cups/raster-private.h>
21 
22 
23 /*
24  * Local structures...
25  */
26 
27 typedef struct _cups_raster_error_s	/**** Error buffer structure ****/
28 {
29   char	*start,				/* Start of buffer */
30 	*current,			/* Current position in buffer */
31 	*end;				/* End of buffer */
32 } _cups_raster_error_t;
33 
34 
35 /*
36  * Local functions...
37  */
38 
39 static _cups_raster_error_t	*get_error_buffer(void);
40 
41 
42 /*
43  * '_cupsRasterAddError()' - Add an error message to the error buffer.
44  */
45 
46 void
_cupsRasterAddError(const char * f,...)47 _cupsRasterAddError(const char *f,	/* I - Printf-style error message */
48                     ...)		/* I - Additional arguments as needed */
49 {
50   _cups_raster_error_t	*buf = get_error_buffer();
51 					/* Error buffer */
52   va_list	ap;			/* Pointer to additional arguments */
53   char		s[2048];		/* Message string */
54   ssize_t	bytes;			/* Bytes in message string */
55 
56 
57   DEBUG_printf(("_cupsRasterAddError(f=\"%s\", ...)", f));
58 
59   va_start(ap, f);
60   bytes = vsnprintf(s, sizeof(s), f, ap);
61   va_end(ap);
62 
63   if (bytes <= 0)
64     return;
65 
66   DEBUG_printf(("1_cupsRasterAddError: %s", s));
67 
68   bytes ++;
69 
70   if ((size_t)bytes >= sizeof(s))
71     return;
72 
73   if (bytes > (ssize_t)(buf->end - buf->current))
74   {
75    /*
76     * Allocate more memory...
77     */
78 
79     char	*temp;			/* New buffer */
80     size_t	size;			/* Size of buffer */
81 
82 
83     size = (size_t)(buf->end - buf->start + 2 * bytes + 1024);
84 
85     if (buf->start)
86       temp = realloc(buf->start, size);
87     else
88       temp = malloc(size);
89 
90     if (!temp)
91       return;
92 
93    /*
94     * Update pointers...
95     */
96 
97     buf->end     = temp + size;
98     buf->current = temp + (buf->current - buf->start);
99     buf->start   = temp;
100   }
101 
102  /*
103   * Append the message to the end of the current string...
104   */
105 
106   memcpy(buf->current, s, (size_t)bytes);
107   buf->current += bytes - 1;
108 }
109 
110 
111 /*
112  * '_cupsRasterClearError()' - Clear the error buffer.
113  */
114 
115 void
_cupsRasterClearError(void)116 _cupsRasterClearError(void)
117 {
118   _cups_raster_error_t	*buf = get_error_buffer();
119 					/* Error buffer */
120 
121 
122   buf->current = buf->start;
123 
124   if (buf->start)
125     *(buf->start) = '\0';
126 }
127 
128 
129 /*
130  * 'cupsRasterErrorString()' - Return the last error from a raster function.
131  *
132  * If there are no recent errors, NULL is returned.
133  *
134  * @since CUPS 1.3/macOS 10.5@
135  */
136 
137 const char *				/* O - Last error */
cupsRasterErrorString(void)138 cupsRasterErrorString(void)
139 {
140   _cups_raster_error_t	*buf = get_error_buffer();
141 					/* Error buffer */
142 
143 
144   if (buf->current == buf->start)
145     return (NULL);
146   else
147     return (buf->start);
148 }
149 
150 
151 #ifdef HAVE_PTHREAD_H
152 /*
153  * Implement per-thread globals...
154  */
155 
156 #  include <pthread.h>
157 
158 
159 /*
160  * Local globals...
161  */
162 
163 static pthread_key_t	raster_key = 0;	/* Thread local storage key */
164 static pthread_once_t	raster_key_once = PTHREAD_ONCE_INIT;
165 					/* One-time initialization object */
166 
167 
168 /*
169  * Local functions...
170  */
171 
172 static void	raster_init(void);
173 static void	raster_destructor(void *value);
174 
175 
176 /*
177  * 'get_error_buffer()' - Return a pointer to thread local storage.
178  */
179 
180 _cups_raster_error_t *			/* O - Pointer to error buffer */
get_error_buffer(void)181 get_error_buffer(void)
182 {
183   _cups_raster_error_t *buf;		/* Pointer to error buffer */
184 
185 
186  /*
187   * Initialize the global data exactly once...
188   */
189 
190   DEBUG_puts("3get_error_buffer()");
191 
192   pthread_once(&raster_key_once, raster_init);
193 
194  /*
195   * See if we have allocated the data yet...
196   */
197 
198   if ((buf = (_cups_raster_error_t *)pthread_getspecific(raster_key))
199           == NULL)
200   {
201     DEBUG_puts("4get_error_buffer: allocating memory for thread.");
202 
203    /*
204     * No, allocate memory as set the pointer for the key...
205     */
206 
207     buf = calloc(1, sizeof(_cups_raster_error_t));
208     pthread_setspecific(raster_key, buf);
209 
210     DEBUG_printf(("4get_error_buffer: buf=%p", (void *)buf));
211   }
212 
213  /*
214   * Return the pointer to the data...
215   */
216 
217   return (buf);
218 }
219 
220 
221 /*
222  * 'raster_init()' - Initialize error buffer once.
223  */
224 
225 static void
raster_init(void)226 raster_init(void)
227 {
228   pthread_key_create(&raster_key, raster_destructor);
229 
230   DEBUG_printf(("3raster_init(): raster_key=%x(%u)", (unsigned)raster_key, (unsigned)raster_key));
231 }
232 
233 
234 /*
235  * 'raster_destructor()' - Free memory allocated by get_error_buffer().
236  */
237 
238 static void
raster_destructor(void * value)239 raster_destructor(void *value)		/* I - Data to free */
240 {
241   _cups_raster_error_t *buf = (_cups_raster_error_t *)value;
242 					/* Error buffer */
243 
244 
245   DEBUG_printf(("3raster_destructor(value=%p)", value));
246 
247   if (buf->start)
248     free(buf->start);
249 
250   free(value);
251 }
252 
253 
254 #else
255 /*
256  * Implement static globals...
257  */
258 
259 /*
260  * 'get_error_buffer()' - Return a pointer to thread local storage.
261  */
262 
263 _cups_raster_error_t *			/* O - Pointer to error buffer */
get_error_buffer(void)264 get_error_buffer(void)
265 {
266   static _cups_raster_error_t buf = { 0, 0, 0 };
267 					/* Error buffer */
268 
269 
270   return (&buf);
271 }
272 #endif /* HAVE_PTHREAD_H */
273