Commit b4bdc42b4fd627529e1c4a4636d1631254a2f26e

Authored by Jay Berkenbilt
1 parent 164cbdde

New exception class QPDFSystemError (fixes #221)

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 7 2018-08-12 Jay Berkenbilt <ejb@ql.org>
2 8  
3 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 61 QPDF_DLL
62 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 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 72 QPDF_DLL
68 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 7 # include <qpdf/InsecureRandomDataProvider.hh>
8 8 #endif
9 9 #include <qpdf/SecureRandomDataProvider.hh>
  10 +#include <qpdf/QPDFSystemError.hh>
10 11  
11 12 #include <cmath>
12 13 #include <iomanip>
... ... @@ -132,22 +133,7 @@ QUtil::unsigned_char_pointer(char const* str)
132 133 void
133 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 139 int
... ...
libqpdf/build.mk
... ... @@ -45,6 +45,7 @@ SRCS_libqpdf = \
45 45 libqpdf/QPDFObjectHandle.cc \
46 46 libqpdf/QPDFPageDocumentHelper.cc \
47 47 libqpdf/QPDFPageObjectHelper.cc \
  48 + libqpdf/QPDFSystemError.cc \
48 49 libqpdf/QPDFTokenizer.cc \
49 50 libqpdf/QPDFWriter.cc \
50 51 libqpdf/QPDFXRefEntry.cc \
... ...
libtests/qutil.cc
... ... @@ -5,8 +5,10 @@
5 5 #include <fcntl.h>
6 6 #include <qpdf/QUtil.hh>
7 7 #include <qpdf/PointerHolder.hh>
  8 +#include <qpdf/QPDFSystemError.hh>
8 9 #include <string.h>
9 10 #include <limits.h>
  11 +#include <assert.h>
10 12  
11 13 #ifdef _WIN32
12 14 # include <io.h>
... ... @@ -137,9 +139,10 @@ void fopen_wrapper_test()
137 139 std::cout << "after fopen" << std::endl;
138 140 (void) fclose(f);
139 141 }
140   - catch (std::runtime_error& s)
  142 + catch (QPDFSystemError& s)
141 143 {
142 144 std::cout << "exception: " << s.what() << std::endl;
  145 + assert(s.getErrno() != 0);
143 146 }
144 147 }
145 148  
... ...