]> git.saurik.com Git - apt.git/blob - apt-pkg/contrib/error.cc
run-parts. Closes: #94286
[apt.git] / apt-pkg / contrib / error.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: error.cc,v 1.9 2001/02/20 07:03:17 jgg Exp $
4 /* ######################################################################
5
6 Global Erorr Class - Global error mechanism
7
8 We use a simple STL vector to store each error record. A PendingFlag
9 is kept which indicates when the vector contains a Sever error.
10
11 This source is placed in the Public Domain, do with it what you will
12 It was originally written by Jason Gunthorpe.
13
14 ##################################################################### */
15 /*}}}*/
16 // Include Files /*{{{*/
17 #ifdef __GNUG__
18 #pragma implementation "apt-pkg/error.h"
19 #endif
20
21 #include <apt-pkg/error.h>
22
23 #include <errno.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <unistd.h>
28
29 #include "config.h"
30 /*}}}*/
31
32 // Global Error Object /*{{{*/
33 /* If the implementation supports posix threads then the accessor function
34 is compiled to be thread safe otherwise a non-safe version is used. A
35 Per-Thread error object is maintained in much the same manner as libc
36 manages errno */
37 #if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
38 #include <pthread.h>
39
40 static pthread_key_t ErrorKey;
41 static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
42 static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
43
44 GlobalError *_GetErrorObj()
45 {
46 static pthread_once_t Once = PTHREAD_ONCE_INIT;
47 pthread_once(&Once,KeyAlloc);
48
49 void *Res = pthread_getspecific(ErrorKey);
50 if (Res == 0)
51 pthread_setspecific(ErrorKey,Res = new GlobalError);
52 return (GlobalError *)Res;
53 }
54 #else
55 GlobalError *_GetErrorObj()
56 {
57 static GlobalError *Obj = new GlobalError;
58 return Obj;
59 }
60 #endif
61 /*}}}*/
62
63 // GlobalError::GlobalError - Constructor /*{{{*/
64 // ---------------------------------------------------------------------
65 /* */
66 GlobalError::GlobalError() : List(0), PendingFlag(false)
67 {
68 }
69 /*}}}*/
70 // GlobalError::Errno - Get part of the error string from errno /*{{{*/
71 // ---------------------------------------------------------------------
72 /* Function indicates the stdlib function that failed and Description is
73 a user string that leads the text. Form is:
74 Description - Function (errno: strerror)
75 Carefull of the buffer overrun, sprintf.
76 */
77 bool GlobalError::Errno(const char *Function,const char *Description,...)
78 {
79 va_list args;
80 va_start(args,Description);
81
82 // sprintf the description
83 char S[400];
84 vsnprintf(S,sizeof(S),Description,args);
85 snprintf(S + strlen(S),sizeof(S) - strlen(S),
86 " - %s (%i %s)",Function,errno,strerror(errno));
87
88 // Put it on the list
89 Item *Itm = new Item;
90 Itm->Text = S;
91 Itm->Error = true;
92 Insert(Itm);
93
94 PendingFlag = true;
95
96 return false;
97 }
98 /*}}}*/
99 // GlobalError::WarningE - Get part of the warn string from errno /*{{{*/
100 // ---------------------------------------------------------------------
101 /* Function indicates the stdlib function that failed and Description is
102 a user string that leads the text. Form is:
103 Description - Function (errno: strerror)
104 Carefull of the buffer overrun, sprintf.
105 */
106 bool GlobalError::WarningE(const char *Function,const char *Description,...)
107 {
108 va_list args;
109 va_start(args,Description);
110
111 // sprintf the description
112 char S[400];
113 vsnprintf(S,sizeof(S),Description,args);
114 snprintf(S + strlen(S),sizeof(S) - strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
115
116 // Put it on the list
117 Item *Itm = new Item;
118 Itm->Text = S;
119 Itm->Error = false;
120 Insert(Itm);
121
122 return false;
123 }
124 /*}}}*/
125 // GlobalError::Error - Add an error to the list /*{{{*/
126 // ---------------------------------------------------------------------
127 /* Just vsprintfs and pushes */
128 bool GlobalError::Error(const char *Description,...)
129 {
130 va_list args;
131 va_start(args,Description);
132
133 // sprintf the description
134 char S[400];
135 vsnprintf(S,sizeof(S),Description,args);
136
137 // Put it on the list
138 Item *Itm = new Item;
139 Itm->Text = S;
140 Itm->Error = true;
141 Insert(Itm);
142
143 PendingFlag = true;
144
145 return false;
146 }
147 /*}}}*/
148 // GlobalError::Warning - Add a warning to the list /*{{{*/
149 // ---------------------------------------------------------------------
150 /* This doesn't set the pending error flag */
151 bool GlobalError::Warning(const char *Description,...)
152 {
153 va_list args;
154 va_start(args,Description);
155
156 // sprintf the description
157 char S[400];
158 vsnprintf(S,sizeof(S),Description,args);
159
160 // Put it on the list
161 Item *Itm = new Item;
162 Itm->Text = S;
163 Itm->Error = false;
164 Insert(Itm);
165
166 return false;
167 }
168 /*}}}*/
169 // GlobalError::PopMessage - Pulls a single message out /*{{{*/
170 // ---------------------------------------------------------------------
171 /* This should be used in a loop checking empty() each cycle. It returns
172 true if the message is an error. */
173 bool GlobalError::PopMessage(string &Text)
174 {
175 if (List == 0)
176 return false;
177
178 bool Ret = List->Error;
179 Text = List->Text;
180 Item *Old = List;
181 List = List->Next;
182 delete Old;
183
184 // This really should check the list to see if only warnings are left..
185 if (List == 0)
186 PendingFlag = false;
187
188 return Ret;
189 }
190 /*}}}*/
191 // GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/
192 // ---------------------------------------------------------------------
193 /* */
194 void GlobalError::DumpErrors()
195 {
196 // Print any errors or warnings found
197 string Err;
198 while (empty() == false)
199 {
200 bool Type = PopMessage(Err);
201 if (Type == true)
202 cerr << "E: " << Err << endl;
203 else
204 cerr << "W: " << Err << endl;
205 }
206 }
207 /*}}}*/
208 // GlobalError::Discard - Discard /*{{{*/
209 // ---------------------------------------------------------------------
210 /* */
211 void GlobalError::Discard()
212 {
213 while (List != 0)
214 {
215 Item *Old = List;
216 List = List->Next;
217 delete Old;
218 }
219
220 PendingFlag = false;
221 };
222 /*}}}*/
223 // GlobalError::Insert - Insert a new item at the end /*{{{*/
224 // ---------------------------------------------------------------------
225 /* */
226 void GlobalError::Insert(Item *Itm)
227 {
228 Item **End = &List;
229 for (Item *I = List; I != 0; I = I->Next)
230 End = &I->Next;
231 Itm->Next = *End;
232 *End = Itm;
233 }
234 /*}}}*/