]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/error.cc
test: framework: Ensure copied status files have trailing lines
[apt.git] / apt-pkg / contrib / error.cc
index e2e8d6e57c39c13afa9f22b754c5317c62d1009f..c06ea8364992f3ebf8a4c52d7b0b2119d49b43f8 100644 (file)
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
+#include <config.h>
+
 #include <apt-pkg/error.h>
 
+#include <stdarg.h>
+#include <stddef.h>
+#include <list>
 #include <iostream>
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
-
 #include <string>
 #include <cstring>
+#include <algorithm>
 
-#include "config.h"
-                                                                       /*}}}*/
+                                                                       /*}}}*/
 
 // Global Error Object                                                 /*{{{*/
 /* If the implementation supports posix threads then the accessor function
 // GlobalError::GlobalError - Constructor                              /*{{{*/
 GlobalError::GlobalError() : PendingFlag(false) {}
                                                                        /*}}}*/
-// GlobalError::FatalE - Get part of the error string from errno       /*{{{*/
-bool GlobalError::FatalE(const char *Function,const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return InsertErrno(FATAL, Function, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::Errno - Get part of the error string from errno                /*{{{*/
-bool GlobalError::Errno(const char *Function,const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return InsertErrno(ERROR, Function, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::WarningE - Get part of the warning string from errno   /*{{{*/
-bool GlobalError::WarningE(const char *Function,const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return InsertErrno(WARNING, Function, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::NoticeE - Get part of the notice string from errno     /*{{{*/
-bool GlobalError::NoticeE(const char *Function,const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return InsertErrno(NOTICE, Function, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::DebugE - Get part of the debug string from errno       /*{{{*/
-bool GlobalError::DebugE(const char *Function,const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return InsertErrno(DEBUG, Function, Description, args);
+// GlobalError::FatalE, Errno, WarningE, NoticeE and DebugE - Add to the list/*{{{*/
+#define GEMessage(NAME, TYPE) \
+bool GlobalError::NAME (const char *Function, const char *Description,...) { \
+       va_list args; \
+       size_t msgSize = 400; \
+       int const errsv = errno; \
+       bool retry; \
+       do { \
+               va_start(args,Description); \
+               retry = InsertErrno(TYPE, Function, Description, args, errsv, msgSize); \
+               va_end(args); \
+       } while (retry); \
+       return false; \
 }
+GEMessage(FatalE, FATAL)
+GEMessage(Errno, ERROR)
+GEMessage(WarningE, WARNING)
+GEMessage(NoticeE, NOTICE)
+GEMessage(DebugE, DEBUG)
+#undef GEMessage
                                                                        /*}}}*/
 // GlobalError::InsertErrno - Get part of the errortype string from errno/*{{{*/
 bool GlobalError::InsertErrno(MsgType const &type, const char *Function,
                                const char *Description,...) {
        va_list args;
-       va_start(args,Description);
-       return InsertErrno(type, Function, Description, args);
+       size_t msgSize = 400;
+       int const errsv = errno;
+       bool retry;
+       do {
+               va_start(args,Description);
+               retry = InsertErrno(type, Function, Description, args, errsv, msgSize);
+               va_end(args);
+       } while (retry);
+       return false;
 }
                                                                        /*}}}*/
 // GlobalError::InsertErrno - formats an error message with the errno  /*{{{*/
 bool GlobalError::InsertErrno(MsgType type, const char* Function,
-                             const char* Description, va_list &args) {
-       char S[400];
-       snprintf(S, sizeof(S), "%s - %s (%i: %s)", Description,
-                Function, errno, strerror(errno));
-       return Insert(type, S, args);
-}
-                                                                       /*}}}*/
-// GlobalError::Fatal - Add a fatal error to the list                  /*{{{*/
-bool GlobalError::Fatal(const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return Insert(FATAL, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::Error - Add an error to the list                       /*{{{*/
-bool GlobalError::Error(const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return Insert(ERROR, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::Warning - Add a warning to the list                    /*{{{*/
-bool GlobalError::Warning(const char *Description,...) {
-       va_list args;
-       va_start(args,Description);
-       return Insert(WARNING, Description, args);
+                             const char* Description, va_list &args,
+                             int const errsv, size_t &msgSize) {
+       char* S = (char*) malloc(msgSize);
+       int const n = snprintf(S, msgSize, "%s - %s (%i: %s)", Description,
+                              Function, errsv, strerror(errsv));
+       if (n > -1 && ((unsigned int) n) < msgSize);
+       else {
+               if (n > -1)
+                       msgSize = n + 1;
+               else
+                       msgSize *= 2;
+               free(S);
+               return true;
+       }
+
+       bool const geins = Insert(type, S, args, msgSize);
+       free(S);
+       return geins;
 }
                                                                        /*}}}*/
-// GlobalError::Notice - Add a notice to the list                      /*{{{*/
-bool GlobalError::Notice(const char *Description,...)
-{
-       va_list args;
-       va_start(args,Description);
-       return Insert(NOTICE, Description, args);
-}
-                                                                       /*}}}*/
-// GlobalError::Debug - Add a debug to the list                                /*{{{*/
-bool GlobalError::Debug(const char *Description,...)
-{
-       va_list args;
-       va_start(args,Description);
-       return Insert(DEBUG, Description, args);
+// GlobalError::Fatal, Error, Warning, Notice and Debug - Add to the list/*{{{*/
+#define GEMessage(NAME, TYPE) \
+bool GlobalError::NAME (const char *Description,...) { \
+       va_list args; \
+       size_t msgSize = 400; \
+       bool retry; \
+       do { \
+               va_start(args,Description); \
+               retry = Insert(TYPE, Description, args, msgSize); \
+               va_end(args); \
+       } while (retry); \
+       return false; \
 }
+GEMessage(Fatal, FATAL)
+GEMessage(Error, ERROR)
+GEMessage(Warning, WARNING)
+GEMessage(Notice, NOTICE)
+GEMessage(Debug, DEBUG)
+#undef GEMessage
                                                                        /*}}}*/
 // GlobalError::Insert - Add a errotype message to the list            /*{{{*/
 bool GlobalError::Insert(MsgType const &type, const char *Description,...)
 {
        va_list args;
-       va_start(args,Description);
-       return Insert(type, Description, args);
+       size_t msgSize = 400;
+       bool retry;
+       do {
+               va_start(args,Description);
+               retry = Insert(type, Description, args, msgSize);
+               va_end(args);
+       } while (retry);
+       return false;
 }
                                                                        /*}}}*/
 // GlobalError::Insert - Insert a new item at the end                  /*{{{*/
 bool GlobalError::Insert(MsgType type, const char* Description,
-                        va_list &args) {
-       char S[400];
-       vsnprintf(S,sizeof(S),Description,args);
+                        va_list &args, size_t &msgSize) {
+       char* S = (char*) malloc(msgSize);
+       int const n = vsnprintf(S, msgSize, Description, args);
+       if (n > -1 && ((unsigned int) n) < msgSize);
+       else {
+               if (n > -1)
+                       msgSize = n + 1;
+               else
+                       msgSize *= 2;
+               free(S);
+               return true;
+       }
 
        Item const m(S, type);
        Messages.push_back(m);
@@ -169,6 +178,7 @@ bool GlobalError::Insert(MsgType type, const char* Description,
        if (type == FATAL || type == DEBUG)
                std::clog << m << std::endl;
 
+       free(S);
        return false;
 }
                                                                        /*}}}*/
@@ -187,7 +197,7 @@ bool GlobalError::PopMessage(std::string &Text) {
 
        // check if another error message is pending
        for (std::list<Item>::const_iterator m = Messages.begin();
-            m != Messages.end(); m++)
+            m != Messages.end(); ++m)
                if (m->Type == ERROR || m->Type == FATAL)
                        return Ret;
 
@@ -201,12 +211,13 @@ void GlobalError::DumpErrors(std::ostream &out, MsgType const &threshold,
        if (mergeStack == true)
                for (std::list<MsgStack>::const_reverse_iterator s = Stacks.rbegin();
                     s != Stacks.rend(); ++s)
-                       Messages.insert(Messages.begin(), s->Messages.begin(), s->Messages.end());
+                       std::copy(s->Messages.begin(), s->Messages.end(), std::front_inserter(Messages));
+
+       std::for_each(Messages.begin(), Messages.end(), [&threshold, &out](Item const &m) {
+               if (m.Type >= threshold)
+                       out << m << std::endl;
+       });
 
-       for (std::list<Item>::const_iterator m = Messages.begin();
-            m != Messages.end(); m++)
-               if (m->Type >= threshold)
-                       out << (*m) << std::endl;
        Discard();
 }
                                                                        /*}}}*/
@@ -214,28 +225,24 @@ void GlobalError::DumpErrors(std::ostream &out, MsgType const &threshold,
 void GlobalError::Discard() {
        Messages.clear();
        PendingFlag = false;
-};
+}
                                                                        /*}}}*/
 // GlobalError::empty - does our error list include anything?          /*{{{*/
-bool GlobalError::empty(MsgType const &trashhold) const {
+bool GlobalError::empty(MsgType const &threshold) const {
        if (PendingFlag == true)
                return false;
 
        if (Messages.empty() == true)
                return true;
 
-       for (std::list<Item>::const_iterator m = Messages.begin();
-            m != Messages.end(); m++)
-               if (m->Type >= trashhold)
-                       return false;
-
-       return true;
+       return std::find_if(Messages.begin(), Messages.end(), [&threshold](Item const &m) {
+               return m.Type >= threshold;
+       }) == Messages.end();
 }
                                                                        /*}}}*/
 // GlobalError::PushToStack                                            /*{{{*/
 void GlobalError::PushToStack() {
-       MsgStack pack(Messages, PendingFlag);
-       Stacks.push_back(pack);
+       Stacks.emplace_back(Messages, PendingFlag);
        Discard();
 }
                                                                        /*}}}*/
@@ -251,7 +258,7 @@ void GlobalError::RevertToStack() {
 // GlobalError::MergeWithStack                                         /*{{{*/
 void GlobalError::MergeWithStack() {
        MsgStack pack = Stacks.back();
-       Messages.insert(Messages.begin(), pack.Messages.begin(), pack.Messages.end());
+       Messages.splice(Messages.begin(), pack.Messages);
        PendingFlag = PendingFlag || pack.PendingFlag;
        Stacks.pop_back();
 }