Home | History | Annotate | Download | only in filter
      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
     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
    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 */
    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 */
    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
    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
    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 */
    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