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