1 /* Error functions.
2 *
3 * Copyright 2010, Michael Cohen <sucdette@gmail.com>.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 #include <string.h>
18
19 #if !defined( WIN32 )
20 #include <pthread.h>
21 #endif
22
23 #include "aff4_errors.h"
24 #include "class.h"
25
26 #define ERROR_BUFF_SIZE 10240
27
28 // Windows version not truely threadsafe for now
29 #if defined( WIN32 )
30 static char global_error_buffer[ERROR_BUFF_SIZE];
31 static int global_error_type = 0;
32 #else
33 /** These slots carry the TLS error keys */
34 static pthread_key_t error_str_slot;
35 static pthread_once_t error_once = PTHREAD_ONCE_INIT;
36
37 static pthread_key_t error_value_slot;
38 #endif
39
40 #if defined( WIN32 )
error_init(void)41 static void error_init(void) {
42 memset(global_error_buffer, 0, sizeof(global_error_buffer));
43 };
44
45 #else
46 static void error_init(void);
47
error_dest(void * slot)48 void error_dest(void *slot) {
49 if(slot) talloc_free(slot);
50 };
51
error_init(void)52 void error_init(void) {
53 // We create the error buffer slots
54 if(pthread_key_create(&error_str_slot, error_dest) ||
55 pthread_key_create(&error_value_slot, error_dest)) {
56 printf("Unable to set up TLS variables\n");
57 abort();
58 };
59 };
60 #endif
61
aff4_raise_errors(int t,const char * reason,...)62 DLL_PUBLIC void *aff4_raise_errors(int t, const char *reason, ...) {
63 char *error_buffer;
64 char tmp[ERROR_BUFF_SIZE];
65 // This has to succeed:
66 int *type = aff4_get_current_error(&error_buffer);
67
68 if(reason) {
69 va_list ap;
70 va_start(ap, reason);
71
72 vsnprintf(tmp, ERROR_BUFF_SIZE-1, reason,ap);
73 tmp[ERROR_BUFF_SIZE-1]=0;
74 va_end(ap);
75 };
76
77 if(*type == EZero) {
78 *error_buffer = 0;
79
80 //update the error type
81 *type = t;
82 } else {
83 strncat(error_buffer, "\n", ERROR_BUFF_SIZE -1 );
84 };
85
86 strncat(error_buffer, tmp, ERROR_BUFF_SIZE-1);
87
88 return NULL;
89 };
90
91 #if defined( WIN32 )
aff4_get_current_error(char ** error_buffer)92 DLL_PUBLIC int *aff4_get_current_error(char **error_buffer) {
93 if(error_buffer != NULL) {
94 *error_buffer = global_error_buffer;
95 };
96 return &global_error_type;
97 };
98
99 #else
aff4_get_current_error(char ** error_buffer)100 DLL_PUBLIC int *aff4_get_current_error(char **error_buffer) {
101 int *type;
102
103 (void) pthread_once(&error_once, error_init);
104 type = (int *) pthread_getspecific(error_value_slot);
105
106 // This is optional
107 if(error_buffer != NULL) {
108 *error_buffer = (char *) pthread_getspecific(error_str_slot);
109
110 // If TLS buffers are not set we need to create them
111 // TODO: the TLS buffers need to be freed on exit.
112 if(*error_buffer == NULL) {
113 *error_buffer = (char *) talloc_size(NULL, ERROR_BUFF_SIZE);
114 pthread_setspecific(error_str_slot, *error_buffer);
115 };
116 };
117
118 if(!type) {
119 type = (int *) talloc_size(NULL, ERROR_BUFF_SIZE);
120 pthread_setspecific(error_value_slot, type);
121 };
122
123 return type;
124 };
125 #endif
126