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