]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/error.cc
* apt-pkg/acquire-item.cc:
[apt.git] / apt-pkg / contrib / error.cc
index 59d2b8c8bdfe38a881845816061fd9693fe34ffe..8c2d6cb19a8a33ae3427dbfe87d68f8f117f0ea9 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: error.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $
+// $Id: error.cc,v 1.11 2002/03/26 07:38:58 jgg Exp $
 /* ######################################################################
    
    Global Erorr Class - Global error mechanism
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
+#include <apt-pkg/error.h>
+
+#include <iostream>
 #include <errno.h>
 #include <stdio.h>
-#include <string.h>
+#include <string>
 #include <stdarg.h>
+#include <unistd.h>
 
-#include <pkglib/error.h>
+#include "config.h"
                                                                        /*}}}*/
 
-GlobalError *_error = new GlobalError;
+using namespace std;
+
+// Global Error Object                                                 /*{{{*/
+/* If the implementation supports posix threads then the accessor function
+   is compiled to be thread safe otherwise a non-safe version is used. A
+   Per-Thread error object is maintained in much the same manner as libc
+   manages errno */
+#if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
+ #include <pthread.h>
+
+ static pthread_key_t ErrorKey;
+ static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
+ static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
+
+ GlobalError *_GetErrorObj()
+ {
+    static pthread_once_t Once = PTHREAD_ONCE_INIT;
+    pthread_once(&Once,KeyAlloc);
+    
+    void *Res = pthread_getspecific(ErrorKey);
+    if (Res == 0)
+       pthread_setspecific(ErrorKey,Res = new GlobalError);
+    return (GlobalError *)Res;
+ }
+#else
+ GlobalError *_GetErrorObj()
+ {
+    static GlobalError *Obj = new GlobalError;
+    return Obj;
+ }
+#endif
+                                                                       /*}}}*/
 
 // GlobalError::GlobalError - Constructor                              /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-GlobalError::GlobalError() : PendingFlag(false)
+GlobalError::GlobalError() : List(0), PendingFlag(false)
 {
 }
                                                                        /*}}}*/
@@ -45,17 +80,44 @@ bool GlobalError::Errno(const char *Function,const char *Description,...)
 
    // sprintf the description
    char S[400];
-   vsprintf(S,Description,args);
-   sprintf(S + strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
+   vsnprintf(S,sizeof(S),Description,args);
+   snprintf(S + strlen(S),sizeof(S) - strlen(S),
+           " - %s (%i %s)",Function,errno,strerror(errno));
 
    // Put it on the list
-   Item Itm;
-   Itm.Text = S;
-   Itm.Error = true;
-   List.push_back(Itm);
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = true;
+   Insert(Itm);
    
    PendingFlag = true;
 
+   return false;   
+}
+                                                                       /*}}}*/
+// GlobalError::WarningE - Get part of the warn string from errno      /*{{{*/
+// ---------------------------------------------------------------------
+/* Function indicates the stdlib function that failed and Description is
+   a user string that leads the text. Form is:
+     Description - Function (errno: strerror)
+   Carefull of the buffer overrun, sprintf.
+ */
+bool GlobalError::WarningE(const char *Function,const char *Description,...)
+{
+   va_list args;
+   va_start(args,Description);
+
+   // sprintf the description
+   char S[400];
+   vsnprintf(S,sizeof(S),Description,args);
+   snprintf(S + strlen(S),sizeof(S) - strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
+
+   // Put it on the list
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = false;
+   Insert(Itm);
+   
    return false;   
 }
                                                                        /*}}}*/
@@ -69,13 +131,13 @@ bool GlobalError::Error(const char *Description,...)
 
    // sprintf the description
    char S[400];
-   vsprintf(S,Description,args);
+   vsnprintf(S,sizeof(S),Description,args);
 
    // Put it on the list
-   Item Itm;
-   Itm.Text = S;
-   Itm.Error = true;
-   List.push_back(Itm);
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = true;
+   Insert(Itm);
    
    PendingFlag = true;
    
@@ -92,13 +154,13 @@ bool GlobalError::Warning(const char *Description,...)
 
    // sprintf the description
    char S[400];
-   vsprintf(S,Description,args);
+   vsnprintf(S,sizeof(S),Description,args);
 
    // Put it on the list
-   Item Itm;
-   Itm.Text = S;
-   Itm.Error = false;
-   List.push_back(Itm);
+   Item *Itm = new Item;
+   Itm->Text = S;
+   Itm->Error = false;
+   Insert(Itm);
    
    return false;
 }
@@ -109,12 +171,17 @@ bool GlobalError::Warning(const char *Description,...)
    true if the message is an error. */
 bool GlobalError::PopMessage(string &Text)
 {
-   bool Ret = List.front().Error;
-   Text = List.front().Text;
-   List.erase(List.begin());
-
+   if (List == 0)
+      return false;
+      
+   bool Ret = List->Error;
+   Text = List->Text;
+   Item *Old = List;
+   List = List->Next;
+   delete Old;
+   
    // This really should check the list to see if only warnings are left..
-   if (empty())
+   if (List == 0)
       PendingFlag = false;
    
    return Ret;
@@ -137,3 +204,30 @@ void GlobalError::DumpErrors()
    }
 }
                                                                        /*}}}*/
+// GlobalError::Discard - Discard                                                                      /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::Discard()
+{
+   while (List != 0)
+   {
+      Item *Old = List;
+      List = List->Next;
+      delete Old;
+   }
+   
+   PendingFlag = false;
+};
+                                                                       /*}}}*/
+// GlobalError::Insert - Insert a new item at the end                  /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::Insert(Item *Itm)
+{
+   Item **End = &List;
+   for (Item *I = List; I != 0; I = I->Next)
+      End = &I->Next;
+   Itm->Next = *End;
+   *End = Itm;
+}
+                                                                       /*}}}*/