Commit 8b64e7b4 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

src: Add XSI-compliant version strerror_r

parent a5d66e71
......@@ -112,6 +112,7 @@ if(ENABLE_APP)
shrpx_api_downstream_connection.cc
shrpx_health_monitor_downstream_connection.cc
shrpx_exec.cc
xsi_strerror.c
)
if(HAVE_SPDYLAY)
list(APPEND NGHTTPX_SRCS
......
......@@ -139,7 +139,8 @@ NGHTTPX_SRCS = \
shrpx_health_monitor_downstream_connection.cc \
shrpx_health_monitor_downstream_connection.h \
shrpx_exec.cc shrpx_exec.h \
buffer.h memchunk.h template.h allocator.h
buffer.h memchunk.h template.h allocator.h \
xsi_strerror.c xsi_strerror.h
if HAVE_SPDYLAY
NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h
......
This diff is collapsed.
......@@ -58,6 +58,7 @@
#include "util.h"
#include "base64.h"
#include "ssl_compat.h"
#include "xsi_strerror.h"
namespace shrpx {
......@@ -225,6 +226,8 @@ read_tls_ticket_key_file(const std::vector<StringRef> &files,
}
FILE *open_file_for_write(const char *filename) {
std::array<char, STRERROR_BUFSIZE> errbuf;
#if defined O_CLOEXEC
auto fd = open(filename, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR);
......@@ -237,14 +240,16 @@ FILE *open_file_for_write(const char *filename) {
}
#endif
if (fd == -1) {
LOG(ERROR) << "Failed to open " << filename
<< " for writing. Cause: " << strerror(errno);
auto error = errno;
LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return nullptr;
}
auto f = fdopen(fd, "wb");
if (f == nullptr) {
LOG(ERROR) << "Failed to open " << filename
<< " for writing. Cause: " << strerror(errno);
auto error = errno;
LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return nullptr;
}
......@@ -963,6 +968,8 @@ int parse_forwarded_node_type(const StringRef &optarg) {
namespace {
int parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt,
const StringRef &optarg) {
std::array<char, STRERROR_BUFSIZE> errbuf;
auto eq = std::find(std::begin(optarg), std::end(optarg), '=');
if (eq == std::end(optarg) || eq + 1 == std::end(optarg)) {
LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
......@@ -991,7 +998,8 @@ int parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt,
auto fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
auto error = errno;
LOG(ERROR) << opt << ": " << optarg << ": " << strerror(error);
LOG(ERROR) << opt << ": " << optarg << ": "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return -1;
}
......@@ -1002,7 +1010,8 @@ int parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt,
auto n = read(fd, buf.data(), buf.size());
if (n == -1) {
auto error = errno;
LOG(ERROR) << opt << ": " << optarg << ": " << strerror(error);
LOG(ERROR) << opt << ": " << optarg << ": "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return -1;
}
if (n == 0) {
......@@ -1068,10 +1077,13 @@ namespace {
// must be NULL-terminated string.
int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt,
const StringRef &dir_path) {
std::array<char, STRERROR_BUFSIZE> errbuf;
auto dir = opendir(dir_path.c_str());
if (dir == nullptr) {
auto error = errno;
LOG(ERROR) << opt << ": " << dir_path << ": " << strerror(error);
LOG(ERROR) << opt << ": " << dir_path << ": "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return -1;
}
......@@ -1088,7 +1100,7 @@ int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt,
if (errno != 0) {
auto error = errno;
LOG(ERROR) << opt << ": failed to read directory " << dir_path << ": "
<< strerror(error);
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return -1;
}
break;
......@@ -1113,7 +1125,7 @@ int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt,
if (fd == -1) {
auto error = errno;
LOG(ERROR) << opt << ": failed to read SCT from " << path << ": "
<< strerror(error);
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return -1;
}
......@@ -1131,7 +1143,7 @@ int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt,
if (nread == -1) {
auto error = errno;
LOG(ERROR) << opt << ": failed to read SCT data from " << path << ": "
<< strerror(error);
<< xsi_strerror(error, errbuf.data(), errbuf.size());
return -1;
}
......@@ -2000,6 +2012,7 @@ int parse_config(Config *config, const StringRef &opt, const StringRef &optarg,
int parse_config(Config *config, int optid, const StringRef &opt,
const StringRef &optarg, std::set<StringRef> &included_set) {
std::array<char, STRERROR_BUFSIZE> errbuf;
char host[NI_MAXHOST];
uint16_t port;
......@@ -2304,7 +2317,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
auto pwd = getpwnam(optarg.c_str());
if (!pwd) {
LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": "
<< strerror(errno);
<< xsi_strerror(errno, errbuf.data(), errbuf.size());
return -1;
}
config->user = make_string_ref(config->balloc, StringRef{pwd->pw_name});
......
......@@ -52,6 +52,7 @@
#include "util.h"
#include "app_helper.h"
#include "template.h"
#include "xsi_strerror.h"
using namespace nghttp2;
......@@ -63,23 +64,26 @@ void drop_privileges(
neverbleed_t *nb
#endif // HAVE_NEVERBLEED
) {
std::array<char, STRERROR_BUFSIZE> errbuf;
auto config = get_config();
if (getuid() == 0 && config->uid != 0) {
if (initgroups(config->user.c_str(), config->gid) != 0) {
auto error = errno;
LOG(FATAL) << "Could not change supplementary groups: "
<< strerror(error);
<< xsi_strerror(error, errbuf.data(), errbuf.size());
exit(EXIT_FAILURE);
}
if (setgid(config->gid) != 0) {
auto error = errno;
LOG(FATAL) << "Could not change gid: " << strerror(error);
LOG(FATAL) << "Could not change gid: "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
exit(EXIT_FAILURE);
}
if (setuid(config->uid) != 0) {
auto error = errno;
LOG(FATAL) << "Could not change uid: " << strerror(error);
LOG(FATAL) << "Could not change uid: "
<< xsi_strerror(error, errbuf.data(), errbuf.size());
exit(EXIT_FAILURE);
}
if (setuid(0) != -1) {
......@@ -387,6 +391,8 @@ std::random_device rd;
} // namespace
int worker_process_event_loop(WorkerProcessConfig *wpconf) {
std::array<char, STRERROR_BUFSIZE> errbuf;
if (reopen_log_files() != 0) {
LOG(FATAL) << "Failed to open log file";
return -1;
......@@ -501,7 +507,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
rv = pthread_sigmask(SIG_BLOCK, &set, nullptr);
if (rv != 0) {
LOG(ERROR) << "Blocking SIGCHLD failed: " << strerror(rv);
LOG(ERROR) << "Blocking SIGCHLD failed: "
<< xsi_strerror(rv, errbuf.data(), errbuf.size());
return -1;
}
#endif // !NOTHREADS
......@@ -514,7 +521,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
#ifndef NOTHREADS
rv = pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
if (rv != 0) {
LOG(ERROR) << "Unblocking SIGCHLD failed: " << strerror(rv);
LOG(ERROR) << "Unblocking SIGCHLD failed: "
<< xsi_strerror(rv, errbuf.data(), errbuf.size());
return -1;
}
#endif // !NOTHREADS
......
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2016 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "xsi_strerror.h"
/* Make sure that we get XSI-compliant version of strerror_r */
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif /* _POSIX_C_SOURCE */
#ifdef _GNU_SOURCE
#undef _GNU_SOURCE
#endif /* _GNU_SOURCE */
#include <string.h>
char *xsi_strerror(int errnum, char *buf, size_t buflen) {
int rv;
rv = strerror_r(errnum, buf, buflen);
if (rv != 0) {
if (buflen > 0) {
buf[0] = '\0';
}
}
return buf;
}
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2016 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef XSI_STRERROR_H
#define XSI_STRERROR_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Looks like error message is quite small, but we really don't know
how much longer they become. */
#define STRERROR_BUFSIZE 256
/*
* Returns description of error denoted by |errnum|. The description
* is written in |buf| of length |buflen| including terminal NULL. If
* there is an error, including the case that buffer space is not
* sufficient to include error message, and |buflen| > 0, empty string
* is written to |buf|. This function returns |buf|.
*/
char *xsi_strerror(int errnum, char *buf, unsigned long buflen);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XSI_STRERROR_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment