Commit b4bdc42b4fd627529e1c4a4636d1631254a2f26e
1 parent
164cbdde
New exception class QPDFSystemError (fixes #221)
Showing
7 changed files
with
129 additions
and
19 deletions
ChangeLog
| 1 | +2018-08-13 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Add new class QPDFSystemError, derived from std::runtime_error, | ||
| 4 | + which is now thrown by QUtil::throw_system_error. This enables the | ||
| 5 | + triggering errno value to be retrieved. Fixes #221. | ||
| 6 | + | ||
| 1 | 2018-08-12 Jay Berkenbilt <ejb@ql.org> | 7 | 2018-08-12 Jay Berkenbilt <ejb@ql.org> |
| 2 | 8 | ||
| 3 | * qpdf command line: add --no-warn option to suppress issuing | 9 | * qpdf command line: add --no-warn option to suppress issuing |
include/qpdf/QPDFSystemError.hh
0 → 100644
| 1 | +// Copyright (c) 2005-2018 Jay Berkenbilt | ||
| 2 | +// | ||
| 3 | +// This file is part of qpdf. | ||
| 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 | +// Versions of qpdf prior to version 7 were released under the terms | ||
| 18 | +// of version 2.0 of the Artistic License. At your option, you may | ||
| 19 | +// continue to consider qpdf to be licensed under those terms. Please | ||
| 20 | +// see the manual for additional information. | ||
| 21 | + | ||
| 22 | +#ifndef QPDFSYSTEMERROR_HH | ||
| 23 | +#define QPDFSYSTEMERROR_HH | ||
| 24 | + | ||
| 25 | +#include <qpdf/DLL.h> | ||
| 26 | +#include <qpdf/Types.h> | ||
| 27 | + | ||
| 28 | +#include <qpdf/Constants.h> | ||
| 29 | +#include <string> | ||
| 30 | +#include <stdexcept> | ||
| 31 | + | ||
| 32 | +class QPDFSystemError: public std::runtime_error | ||
| 33 | +{ | ||
| 34 | + public: | ||
| 35 | + QPDF_DLL | ||
| 36 | + QPDFSystemError(std::string const& description, | ||
| 37 | + int system_errno); | ||
| 38 | + QPDF_DLL | ||
| 39 | + virtual ~QPDFSystemError() throw (); | ||
| 40 | + | ||
| 41 | + // To get a complete error string, call what(), provided by | ||
| 42 | + // std::exception. The accessors below return the original values | ||
| 43 | + // used to create the exception. | ||
| 44 | + | ||
| 45 | + QPDF_DLL | ||
| 46 | + std::string const& getDescription() const; | ||
| 47 | + QPDF_DLL | ||
| 48 | + int getErrno() const; | ||
| 49 | + | ||
| 50 | + private: | ||
| 51 | + static std::string createWhat(std::string const& description, | ||
| 52 | + int system_errno); | ||
| 53 | + | ||
| 54 | + std::string description; | ||
| 55 | + int system_errno; | ||
| 56 | +}; | ||
| 57 | + | ||
| 58 | +#endif // QPDFSYSTEMERROR_HH |
include/qpdf/QUtil.hh
| @@ -61,9 +61,14 @@ namespace QUtil | @@ -61,9 +61,14 @@ namespace QUtil | ||
| 61 | QPDF_DLL | 61 | QPDF_DLL |
| 62 | unsigned char* unsigned_char_pointer(char const* str); | 62 | unsigned char* unsigned_char_pointer(char const* str); |
| 63 | 63 | ||
| 64 | - // Throw std::runtime_error with a string formed by appending to | 64 | + // Throw QPDFSystemError, which is derived from |
| 65 | + // std::runtime_error, with a string formed by appending to | ||
| 65 | // "description: " the standard string corresponding to the | 66 | // "description: " the standard string corresponding to the |
| 66 | - // current value of errno. | 67 | + // current value of errno. You can retrieve the value of errno by |
| 68 | + // calling getErrno() on the QPDFSystemError. Prior to qpdf 8.2.0, | ||
| 69 | + // this method threw system::runtime_error directly, but since | ||
| 70 | + // QPDFSystemError is derived from system::runtime_error, old code | ||
| 71 | + // that specifically catches std::runtime_error will still work. | ||
| 67 | QPDF_DLL | 72 | QPDF_DLL |
| 68 | void throw_system_error(std::string const& description); | 73 | void throw_system_error(std::string const& description); |
| 69 | 74 |
libqpdf/QPDFSystemError.cc
0 → 100644
| 1 | +#include <qpdf/QPDFSystemError.hh> | ||
| 2 | +#include <qpdf/QUtil.hh> | ||
| 3 | +#include <string.h> | ||
| 4 | + | ||
| 5 | +QPDFSystemError::QPDFSystemError(std::string const& description, | ||
| 6 | + int system_errno) : | ||
| 7 | + std::runtime_error(createWhat(description, system_errno)), | ||
| 8 | + description(description), | ||
| 9 | + system_errno(system_errno) | ||
| 10 | +{ | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +QPDFSystemError::~QPDFSystemError() throw () | ||
| 14 | +{ | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +std::string | ||
| 18 | +QPDFSystemError::createWhat(std::string const& description, | ||
| 19 | + int system_errno) | ||
| 20 | +{ | ||
| 21 | + std::string message; | ||
| 22 | +#ifdef _MSC_VER | ||
| 23 | + // "94" is mentioned in the MSVC docs, but it's still safe if the | ||
| 24 | + // message is longer. strerror_s is a templated function that | ||
| 25 | + // knows the size of buf and truncates. | ||
| 26 | + char buf[94]; | ||
| 27 | + if (strerror_s(buf, errno) != 0) | ||
| 28 | + { | ||
| 29 | + message = description + ": failed with an unknown error"; | ||
| 30 | + } | ||
| 31 | + else | ||
| 32 | + { | ||
| 33 | + message = description + ": " + buf; | ||
| 34 | + } | ||
| 35 | +#else | ||
| 36 | + message = description + ": " + strerror(errno); | ||
| 37 | +#endif | ||
| 38 | + return message; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +std::string const& | ||
| 42 | +QPDFSystemError::getDescription() const | ||
| 43 | +{ | ||
| 44 | + return this->description; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +int | ||
| 48 | +QPDFSystemError::getErrno() const | ||
| 49 | +{ | ||
| 50 | + return this->system_errno; | ||
| 51 | +} |
libqpdf/QUtil.cc
| @@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
| 7 | # include <qpdf/InsecureRandomDataProvider.hh> | 7 | # include <qpdf/InsecureRandomDataProvider.hh> |
| 8 | #endif | 8 | #endif |
| 9 | #include <qpdf/SecureRandomDataProvider.hh> | 9 | #include <qpdf/SecureRandomDataProvider.hh> |
| 10 | +#include <qpdf/QPDFSystemError.hh> | ||
| 10 | 11 | ||
| 11 | #include <cmath> | 12 | #include <cmath> |
| 12 | #include <iomanip> | 13 | #include <iomanip> |
| @@ -132,22 +133,7 @@ QUtil::unsigned_char_pointer(char const* str) | @@ -132,22 +133,7 @@ QUtil::unsigned_char_pointer(char const* str) | ||
| 132 | void | 133 | void |
| 133 | QUtil::throw_system_error(std::string const& description) | 134 | QUtil::throw_system_error(std::string const& description) |
| 134 | { | 135 | { |
| 135 | -#ifdef _MSC_VER | ||
| 136 | - // "94" is mentioned in the MSVC docs, but it's still safe if the | ||
| 137 | - // message is longer. strerror_s is a templated function that | ||
| 138 | - // knows the size of buf and truncates. | ||
| 139 | - char buf[94]; | ||
| 140 | - if (strerror_s(buf, errno) != 0) | ||
| 141 | - { | ||
| 142 | - throw std::runtime_error(description + ": failed with an unknown error"); | ||
| 143 | - } | ||
| 144 | - else | ||
| 145 | - { | ||
| 146 | - throw std::runtime_error(description + ": " + buf); | ||
| 147 | - } | ||
| 148 | -#else | ||
| 149 | - throw std::runtime_error(description + ": " + strerror(errno)); | ||
| 150 | -#endif | 136 | + throw QPDFSystemError(description, errno); |
| 151 | } | 137 | } |
| 152 | 138 | ||
| 153 | int | 139 | int |
libqpdf/build.mk
| @@ -45,6 +45,7 @@ SRCS_libqpdf = \ | @@ -45,6 +45,7 @@ SRCS_libqpdf = \ | ||
| 45 | libqpdf/QPDFObjectHandle.cc \ | 45 | libqpdf/QPDFObjectHandle.cc \ |
| 46 | libqpdf/QPDFPageDocumentHelper.cc \ | 46 | libqpdf/QPDFPageDocumentHelper.cc \ |
| 47 | libqpdf/QPDFPageObjectHelper.cc \ | 47 | libqpdf/QPDFPageObjectHelper.cc \ |
| 48 | + libqpdf/QPDFSystemError.cc \ | ||
| 48 | libqpdf/QPDFTokenizer.cc \ | 49 | libqpdf/QPDFTokenizer.cc \ |
| 49 | libqpdf/QPDFWriter.cc \ | 50 | libqpdf/QPDFWriter.cc \ |
| 50 | libqpdf/QPDFXRefEntry.cc \ | 51 | libqpdf/QPDFXRefEntry.cc \ |
libtests/qutil.cc
| @@ -5,8 +5,10 @@ | @@ -5,8 +5,10 @@ | ||
| 5 | #include <fcntl.h> | 5 | #include <fcntl.h> |
| 6 | #include <qpdf/QUtil.hh> | 6 | #include <qpdf/QUtil.hh> |
| 7 | #include <qpdf/PointerHolder.hh> | 7 | #include <qpdf/PointerHolder.hh> |
| 8 | +#include <qpdf/QPDFSystemError.hh> | ||
| 8 | #include <string.h> | 9 | #include <string.h> |
| 9 | #include <limits.h> | 10 | #include <limits.h> |
| 11 | +#include <assert.h> | ||
| 10 | 12 | ||
| 11 | #ifdef _WIN32 | 13 | #ifdef _WIN32 |
| 12 | # include <io.h> | 14 | # include <io.h> |
| @@ -137,9 +139,10 @@ void fopen_wrapper_test() | @@ -137,9 +139,10 @@ void fopen_wrapper_test() | ||
| 137 | std::cout << "after fopen" << std::endl; | 139 | std::cout << "after fopen" << std::endl; |
| 138 | (void) fclose(f); | 140 | (void) fclose(f); |
| 139 | } | 141 | } |
| 140 | - catch (std::runtime_error& s) | 142 | + catch (QPDFSystemError& s) |
| 141 | { | 143 | { |
| 142 | std::cout << "exception: " << s.what() << std::endl; | 144 | std::cout << "exception: " << s.what() << std::endl; |
| 145 | + assert(s.getErrno() != 0); | ||
| 143 | } | 146 | } |
| 144 | } | 147 | } |
| 145 | 148 |