summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-11-09 14:43:47 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-11-09 14:43:47 +0000
commit228b4c50d757b80efe493728a658ae145eaf67ef (patch)
treeaefd6e605ca52f6e4125f6e25d405e56a1ef681a
parent02f725cab581063a0570402032f0b328e6f3a8a3 (diff)
2010-11-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Capture errno right after system/library call to avoid it to get overwritten. Use util::safeStrerror instead of strerror directly because strerror might return NULL. We don't check errno for std::fstream anymore. * src/AbstractDiskWriter.cc * src/CookieStorage.cc * src/DHTAutoSaveCommand.cc * src/DHTRoutingTableDeserializer.cc * src/DHTRoutingTableSerializer.cc * src/DefaultBtProgressInfoFile.cc * src/EpollEventPoll.cc * src/IteratableChunkChecksumValidator.cc * src/KqueueEventPoll.cc * src/Logger.cc * src/MessageDigestHelper.cc * src/PortEventPoll.cc * src/SelectEventPoll.cc * src/SocketCore.cc * src/message.h * src/util.cc * src/util.h
-rw-r--r--ChangeLog24
-rw-r--r--src/AbstractDiskWriter.cc49
-rw-r--r--src/CookieStorage.cc6
-rw-r--r--src/DHTAutoSaveCommand.cc5
-rw-r--r--src/DHTRoutingTableDeserializer.cc5
-rw-r--r--src/DHTRoutingTableSerializer.cc5
-rw-r--r--src/DefaultBtProgressInfoFile.cc28
-rw-r--r--src/EpollEventPoll.cc18
-rw-r--r--src/IteratableChunkChecksumValidator.cc3
-rw-r--r--src/KqueueEventPoll.cc12
-rw-r--r--src/Logger.cc3
-rw-r--r--src/MessageDigestHelper.cc11
-rw-r--r--src/PortEventPoll.cc19
-rw-r--r--src/SelectEventPoll.cc22
-rw-r--r--src/SocketCore.cc141
-rw-r--r--src/message.h5
-rw-r--r--src/util.cc28
-rw-r--r--src/util.h8
18 files changed, 256 insertions, 136 deletions
diff --git a/ChangeLog b/ChangeLog
index 5fb10463..fe8100b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2010-11-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
+
+ Capture errno right after system/library call to avoid it to get
+ overwritten. Use util::safeStrerror instead of strerror directly
+ because strerror might return NULL. We don't check errno for
+ std::fstream anymore.
+ * src/AbstractDiskWriter.cc
+ * src/CookieStorage.cc
+ * src/DHTAutoSaveCommand.cc
+ * src/DHTRoutingTableDeserializer.cc
+ * src/DHTRoutingTableSerializer.cc
+ * src/DefaultBtProgressInfoFile.cc
+ * src/EpollEventPoll.cc
+ * src/IteratableChunkChecksumValidator.cc
+ * src/KqueueEventPoll.cc
+ * src/Logger.cc
+ * src/MessageDigestHelper.cc
+ * src/PortEventPoll.cc
+ * src/SelectEventPoll.cc
+ * src/SocketCore.cc
+ * src/message.h
+ * src/util.cc
+ * src/util.h
+
2010-11-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Use const reference
diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc
index fd00d649..066c4e35 100644
--- a/src/AbstractDiskWriter.cc
+++ b/src/AbstractDiskWriter.cc
@@ -99,10 +99,12 @@ void AbstractDiskWriter::openExistingFile(uint64_t totalLength)
}
if((fd_ = open(filename_.c_str(), flags, OPEN_MODE)) < 0) {
+ int errNum = errno;
throw DL_ABORT_EX2
- (errno,
- StringFormat
- (EX_FILE_OPEN, filename_.c_str(), strerror(errno)).str());
+ (errNum,
+ StringFormat(EX_FILE_OPEN,
+ filename_.c_str(),
+ util::safeStrerror(errNum).c_str()).str());
}
}
@@ -112,9 +114,12 @@ void AbstractDiskWriter::createFile(int addFlags)
util::mkdirs(File(filename_).getDirname());
if((fd_ = open(filename_.c_str(), O_CREAT|O_RDWR|O_TRUNC|O_BINARY|addFlags,
OPEN_MODE)) < 0) {
+ int errNum = errno;
throw DL_ABORT_EX2
- (errno,
- StringFormat(EX_FILE_OPEN, filename_.c_str(), strerror(errno)).str());
+ (errNum,
+ StringFormat(EX_FILE_OPEN,
+ filename_.c_str(),
+ util::safeStrerror(errNum).c_str()).str());
}
}
@@ -142,8 +147,11 @@ ssize_t AbstractDiskWriter::readDataInternal(unsigned char* data, size_t len)
void AbstractDiskWriter::seek(off_t offset)
{
if(a2lseek(fd_, offset, SEEK_SET) == (off_t)-1) {
+ int errNum = errno;
throw DL_ABORT_EX
- (StringFormat(EX_FILE_SEEK, filename_.c_str(), strerror(errno)).str());
+ (StringFormat(EX_FILE_SEEK,
+ filename_.c_str(),
+ util::safeStrerror(errNum).c_str()).str());
}
}
@@ -151,14 +159,20 @@ void AbstractDiskWriter::writeData(const unsigned char* data, size_t len, off_t
{
seek(offset);
if(writeDataInternal(data, len) < 0) {
+ int errNum = errno;
// If errno is ENOSPC(not enough space in device), throw
// DownloadFailureException and abort download instantly.
- if(errno == ENOSPC) {
+ if(errNum == ENOSPC) {
throw DOWNLOAD_FAILURE_EXCEPTION
- (StringFormat(EX_FILE_WRITE, filename_.c_str(), strerror(errno)).str());
+ (StringFormat(EX_FILE_WRITE,
+ filename_.c_str(),
+ util::safeStrerror(errNum).c_str()).str());
+ } else {
+ throw DL_ABORT_EX
+ (StringFormat(EX_FILE_WRITE,
+ filename_.c_str(),
+ util::safeStrerror(errNum).c_str()).str());
}
- throw DL_ABORT_EX(StringFormat(EX_FILE_WRITE,
- filename_.c_str(), strerror(errno)).str());
}
}
@@ -167,8 +181,11 @@ ssize_t AbstractDiskWriter::readData(unsigned char* data, size_t len, off_t offs
ssize_t ret;
seek(offset);
if((ret = readDataInternal(data, len)) < 0) {
- throw DL_ABORT_EX(StringFormat(EX_FILE_READ,
- filename_.c_str(), strerror(errno)).str());
+ int errNum = errno;
+ throw DL_ABORT_EX
+ (StringFormat(EX_FILE_READ,
+ filename_.c_str(),
+ util::safeStrerror(errNum).c_str()).str());
}
return ret;
}
@@ -189,8 +206,9 @@ void AbstractDiskWriter::truncate(uint64_t length)
}
#else
if(ftruncate(fd_, length) == -1) {
+ int errNum = errno;
throw DL_ABORT_EX(StringFormat("ftruncate failed. cause: %s",
- strerror(errno)).str());
+ util::safeStrerror(errNum).c_str()).str());
}
#endif
}
@@ -205,15 +223,16 @@ void AbstractDiskWriter::allocate(off_t offset, uint64_t length)
// For linux, we use fallocate to detect file system supports
// fallocate or not.
int r = fallocate(fd_, 0, offset, length);
+ int errNum = errno;
if(r == -1) {
throw DL_ABORT_EX(StringFormat("fallocate failed. cause: %s",
- strerror(errno)).str());
+ util::safeStrerror(errNum).c_str()).str());
}
# elif HAVE_POSIX_FALLOCATE
int r = posix_fallocate(fd_, offset, length);
if(r != 0) {
throw DL_ABORT_EX(StringFormat("posix_fallocate failed. cause: %s",
- strerror(r)).str());
+ util::safeStrerror(r).c_str()).str());
}
# else
# error "no *_fallocate function available."
diff --git a/src/CookieStorage.cc b/src/CookieStorage.cc
index 40cf5544..c1d451bb 100644
--- a/src/CookieStorage.cc
+++ b/src/CookieStorage.cc
@@ -343,8 +343,7 @@ bool CookieStorage::saveNsFormat(const std::string& filename)
{
std::ofstream o(tempfilename.c_str(), std::ios::binary);
if(!o) {
- logger_->error("Cannot create cookie file %s, cause %s",
- filename.c_str(), strerror(errno));
+ logger_->error("Cannot create cookie file %s", filename.c_str());
return false;
}
for(std::deque<DomainEntry>::const_iterator i = domains_.begin(),
@@ -353,8 +352,7 @@ bool CookieStorage::saveNsFormat(const std::string& filename)
}
o.flush();
if(!o) {
- logger_->error("Failed to save cookies to %s, cause %s",
- filename.c_str(), strerror(errno));
+ logger_->error("Failed to save cookies to %s", filename.c_str());
return false;
}
}
diff --git a/src/DHTAutoSaveCommand.cc b/src/DHTAutoSaveCommand.cc
index 7be49920..4ceda309 100644
--- a/src/DHTAutoSaveCommand.cc
+++ b/src/DHTAutoSaveCommand.cc
@@ -34,7 +34,6 @@
/* copyright --> */
#include "DHTAutoSaveCommand.h"
-#include <cerrno>
#include <cstring>
#include <fstream>
@@ -117,8 +116,8 @@ void DHTAutoSaveCommand::save()
std::ios::out|std::ios::binary);
if(!o) {
throw DL_ABORT_EX
- (StringFormat("Failed to save DHT routing table to %s. cause:%s",
- dhtFile.c_str(), strerror(errno)).str());
+ (StringFormat("Failed to save DHT routing table to %s.",
+ dhtFile.c_str()).str());
}
serializer.serialize(o);
}
diff --git a/src/DHTRoutingTableDeserializer.cc b/src/DHTRoutingTableDeserializer.cc
index ee73736a..6ed09d08 100644
--- a/src/DHTRoutingTableDeserializer.cc
+++ b/src/DHTRoutingTableDeserializer.cc
@@ -34,7 +34,6 @@
/* copyright --> */
#include "DHTRoutingTableDeserializer.h"
-#include <cerrno>
#include <cstring>
#include <cassert>
#include <istream>
@@ -73,9 +72,7 @@ void readBytes(unsigned char* buf, size_t buflen,
"Unexpected EOF").str()); \
} \
if(!in) { \
- throw DL_ABORT_EX \
- (StringFormat("Failed to load DHT routing table. cause:%s", \
- strerror(errno)).str()); \
+ throw DL_ABORT_EX("Failed to load DHT routing table."); \
}
void DHTRoutingTableDeserializer::deserialize(std::istream& in)
diff --git a/src/DHTRoutingTableSerializer.cc b/src/DHTRoutingTableSerializer.cc
index 2228e422..aa995fc7 100644
--- a/src/DHTRoutingTableSerializer.cc
+++ b/src/DHTRoutingTableSerializer.cc
@@ -34,7 +34,6 @@
/* copyright --> */
#include "DHTRoutingTableSerializer.h"
-#include <cerrno>
#include <cstring>
#include <ostream>
@@ -130,9 +129,7 @@ void DHTRoutingTableSerializer::serialize(std::ostream& o)
o.flush();
if(!o) {
- throw DL_ABORT_EX
- (StringFormat("Failed to save DHT routing table. cause:%s",
- strerror(errno)).str());
+ throw DL_ABORT_EX("Failed to save DHT routing table.");
}
}
diff --git a/src/DefaultBtProgressInfoFile.cc b/src/DefaultBtProgressInfoFile.cc
index 4fae8fbc..b35837d3 100644
--- a/src/DefaultBtProgressInfoFile.cc
+++ b/src/DefaultBtProgressInfoFile.cc
@@ -34,7 +34,6 @@
/* copyright --> */
#include "DefaultBtProgressInfoFile.h"
-#include <cerrno>
#include <cstring>
#include <fstream>
@@ -111,8 +110,8 @@ void DefaultBtProgressInfoFile::save()
{
std::ofstream o(filenameTemp.c_str(), std::ios::out|std::ios::binary);
if(!o) {
- throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_WRITE,
- filename_.c_str(), strerror(errno)).str());
+ throw DL_ABORT_EX
+ (StringFormat(EX_SEGMENT_FILE_WRITE, filename_.c_str()).str());
}
#ifdef ENABLE_BITTORRENT
bool torrentDownload = isTorrentDownload();
@@ -199,25 +198,26 @@ void DefaultBtProgressInfoFile::save()
}
o.flush();
if(!o) {
- throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_WRITE,
- filename_.c_str(), strerror(errno)).str());
+ throw DL_ABORT_EX
+ (StringFormat(EX_SEGMENT_FILE_WRITE, filename_.c_str()).str());
}
logger_->info(MSG_SAVED_SEGMENT_FILE);
}
if(!File(filenameTemp).renameTo(filename_)) {
- throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_WRITE,
- filename_.c_str(), strerror(errno)).str());
+ throw DL_ABORT_EX
+ (StringFormat(EX_SEGMENT_FILE_WRITE, filename_.c_str()).str());
}
}
#define CHECK_STREAM(in, length) \
if(in.gcount() != length) { \
- throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_READ, \
- filename_.c_str(),"Unexpected EOF").str()); \
+ throw DL_ABORT_EX(StringFormat("Failed to read segment file %s." \
+ " Unexpected EOF.", \
+ filename_.c_str()).str()); \
} \
if(!in) { \
- throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_READ, \
- filename_.c_str(), strerror(errno)).str()); \
+ throw DL_ABORT_EX \
+ (StringFormat(EX_SEGMENT_FILE_READ, filename_.c_str()).str()); \
}
// It is assumed that integers are saved as:
@@ -227,9 +227,9 @@ void DefaultBtProgressInfoFile::load()
{
logger_->info(MSG_LOADING_SEGMENT_FILE, filename_.c_str());
std::ifstream in(filename_.c_str(), std::ios::in|std::ios::binary);
- if(!in) { \
- throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_READ, \
- filename_.c_str(), strerror(errno)).str());
+ if(!in) {
+ throw DL_ABORT_EX
+ (StringFormat(EX_SEGMENT_FILE_READ, filename_.c_str()).str());
}
unsigned char versionBuf[2];
in.read(reinterpret_cast<char*>(versionBuf), sizeof(versionBuf));
diff --git a/src/EpollEventPoll.cc b/src/EpollEventPoll.cc
index abd2960e..75db479d 100644
--- a/src/EpollEventPoll.cc
+++ b/src/EpollEventPoll.cc
@@ -34,6 +34,7 @@
/* copyright --> */
#include "EpollEventPoll.h"
+#include <cerrno>
#include <cstring>
#include <algorithm>
#include <numeric>
@@ -41,6 +42,7 @@
#include "Command.h"
#include "LogFactory.h"
#include "Logger.h"
+#include "util.h"
namespace aria2 {
@@ -90,10 +92,11 @@ EpollEventPoll::~EpollEventPoll()
if(epfd_ != -1) {
int r;
while((r = close(epfd_)) == -1 && errno == EINTR);
+ int errNum = errno;
if(r == -1) {
logger_->error("Error occurred while closing epoll file descriptor"
" %d: %s",
- epfd_, strerror(errno));
+ epfd_, util::safeStrerror(errNum).c_str());
}
}
delete [] epEvents_;
@@ -165,6 +168,7 @@ bool EpollEventPoll::addEvents(sock_t socket,
std::deque<SharedHandle<KSocketEntry> >::iterator i =
std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry);
int r = 0;
+ int errNum = 0;
if(i != socketEntries_.end() && (*i) == socketEntry) {
event.addSelf(*i);
@@ -178,6 +182,7 @@ bool EpollEventPoll::addEvents(sock_t socket,
r = epoll_ctl(epfd_, EPOLL_CTL_ADD, (*i)->getSocket(),
&epEvent);
+ errNum = errno;
}
} else {
socketEntries_.insert(i, socketEntry);
@@ -191,11 +196,12 @@ bool EpollEventPoll::addEvents(sock_t socket,
struct epoll_event epEvent = socketEntry->getEvents();
r = epoll_ctl(epfd_, EPOLL_CTL_ADD, socketEntry->getSocket(), &epEvent);
+ errNum = errno;
}
if(r == -1) {
if(logger_->debug()) {
logger_->debug("Failed to add socket event %d:%s",
- socket, strerror(errno));
+ socket, util::safeStrerror(errNum).c_str());
}
return false;
} else {
@@ -229,27 +235,31 @@ bool EpollEventPoll::deleteEvents(sock_t socket,
event.removeSelf(*i);
int r = 0;
+ int errNum = 0;
if((*i)->eventEmpty()) {
// In kernel before 2.6.9, epoll_ctl with EPOLL_CTL_DEL requires non-null
// pointer of epoll_event.
struct epoll_event ev = {0,{0}};
r = epoll_ctl(epfd_, EPOLL_CTL_DEL, (*i)->getSocket(), &ev);
+ errNum = r;
socketEntries_.erase(i);
} else {
// If socket is closed, then it seems it is automatically removed from
// epoll, so following EPOLL_CTL_MOD may fail.
struct epoll_event epEvent = (*i)->getEvents();
r = epoll_ctl(epfd_, EPOLL_CTL_MOD, (*i)->getSocket(), &epEvent);
+ errNum = r;
if(r == -1) {
if(logger_->debug()) {
logger_->debug("Failed to delete socket event, but may be ignored:%s",
- strerror(errno));
+ util::safeStrerror(errNum).c_str());
}
}
}
if(r == -1) {
if(logger_->debug()) {
- logger_->debug("Failed to delete socket event:%s", strerror(errno));
+ logger_->debug("Failed to delete socket event:%s",
+ util::safeStrerror(errNum).c_str());
}
return false;
} else {
diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc
index 3a0dd34b..d1d7f1a3 100644
--- a/src/IteratableChunkChecksumValidator.cc
+++ b/src/IteratableChunkChecksumValidator.cc
@@ -34,7 +34,6 @@
/* copyright --> */
#include "IteratableChunkChecksumValidator.h"
-#include <cerrno>
#include <cstring>
#include <cstdlib>
@@ -161,7 +160,7 @@ std::string IteratableChunkChecksumValidator::digest(off_t offset, size_t length
if(r == 0 || r < static_cast<size_t>(woffset)) {
throw DL_ABORT_EX
(StringFormat(EX_FILE_READ, dctx_->getBasePath().c_str(),
- strerror(errno)).str());
+ "data is too short").str());
}
size_t wlength;
if(max < static_cast<off_t>(curoffset+r)) {
diff --git a/src/KqueueEventPoll.cc b/src/KqueueEventPoll.cc
index 6b211b5a..be4b7a5a 100644
--- a/src/KqueueEventPoll.cc
+++ b/src/KqueueEventPoll.cc
@@ -34,6 +34,7 @@
/* copyright --> */
#include "KqueueEventPoll.h"
+#include <cerrno>
#include <cstring>
#include <algorithm>
#include <numeric>
@@ -41,6 +42,7 @@
#include "Command.h"
#include "LogFactory.h"
#include "Logger.h"
+#include "util.h"
#ifdef KEVENT_UDATA_INTPTR_T
# define PTR_TO_UDATA(X) (reinterpret_cast<intptr_t>(X))
@@ -96,10 +98,11 @@ KqueueEventPoll::~KqueueEventPoll()
if(kqfd_ != -1) {
int r;
while((r = close(kqfd_)) == -1 && errno == EINTR);
+ int errNum = errno;
if(r == -1) {
logger_->error("Error occurred while closing kqueue file descriptor"
" %d: %s",
- kqfd_, strerror(errno));
+ kqfd_, util::safeStrerror(errNum).c_str());
}
}
delete [] kqEvents_;
@@ -186,10 +189,11 @@ bool KqueueEventPoll::addEvents
n = socketEntry->getEvents(changelist);
}
r = kevent(kqfd_, changelist, n, changelist, 0, &zeroTimeout);
+ int errNum = errno;
if(r == -1) {
if(logger_->debug()) {
logger_->debug("Failed to add socket event %d:%s",
- socket, strerror(errno));
+ socket, util::safeStrerror(errNum).c_str());
}
return false;
} else {
@@ -225,12 +229,14 @@ bool KqueueEventPoll::deleteEvents(sock_t socket,
struct kevent changelist[2];
size_t n = (*i)->getEvents(changelist);
r = kevent(kqfd_, changelist, n, changelist, 0, &zeroTimeout);
+ int errNum = errno;
if((*i)->eventEmpty()) {
socketEntries_.erase(i);
}
if(r == -1) {
if(logger_->debug()) {
- logger_->debug("Failed to delete socket event:%s", strerror(errno));
+ logger_->debug("Failed to delete socket event:%s",
+ util::safeStrerror(errNum).c_str());
}
return false;
} else {
diff --git a/src/Logger.cc b/src/Logger.cc
index 6048f450..120d65d9 100644
--- a/src/Logger.cc
+++ b/src/Logger.cc
@@ -34,7 +34,6 @@
/* copyright --> */
#include "Logger.h"
-#include <cerrno>
#include <cstring>
#include "DlAbortEx.h"
@@ -68,7 +67,7 @@ void Logger::openFile(const std::string& filename)
file_.open(filename.c_str(), std::ios::app|std::ios::binary);
if(!file_) {
throw DL_ABORT_EX
- (StringFormat(EX_FILE_OPEN, filename.c_str(), strerror(errno)).str());
+ (StringFormat(EX_FILE_OPEN, filename.c_str(), "n/a").str());
}
}
diff --git a/src/MessageDigestHelper.cc b/src/MessageDigestHelper.cc
index 5ffd40b1..22b3bf31 100644
--- a/src/MessageDigestHelper.cc
+++ b/src/MessageDigestHelper.cc
@@ -33,15 +33,16 @@
*/
/* copyright --> */
#include "MessageDigestHelper.h"
+
+#include <cstring>
+#include <cstdlib>
+
#include "messageDigest.h"
#include "DlAbortEx.h"
#include "message.h"
#include "DefaultDiskWriter.h"
#include "util.h"
#include "StringFormat.h"
-#include <cerrno>
-#include <cstring>
-#include <cstdlib>
namespace aria2 {
@@ -92,7 +93,7 @@ std::string MessageDigestHelper::digest(MessageDigestContext* ctx,
ssize_t readLength = bs->readData(BUF, BUFSIZE, offset);
if((size_t)readLength != BUFSIZE) {
throw DL_ABORT_EX
- (StringFormat(EX_FILE_READ, "n/a", strerror(errno)).str());
+ (StringFormat(EX_FILE_READ, "n/a", "data is too short").str());
}
ctx->digestUpdate(BUF, readLength);
offset += readLength;
@@ -101,7 +102,7 @@ std::string MessageDigestHelper::digest(MessageDigestContext* ctx,
ssize_t readLength = bs->readData(BUF, tail, offset);
if((size_t)readLength != tail) {
throw DL_ABORT_EX
- (StringFormat(EX_FILE_READ, "n/a", strerror(errno)).str());
+ (StringFormat(EX_FILE_READ, "n/a", "data is too short").str());
}
ctx->digestUpdate(BUF, readLength);
}
diff --git a/src/PortEventPoll.cc b/src/PortEventPoll.cc
index 91335b15..cb3757cd 100644
--- a/src/PortEventPoll.cc
+++ b/src/PortEventPoll.cc
@@ -34,6 +34,7 @@
/* copyright --> */
#include "PortEventPoll.h"
+#include <cerrno>
#include <cstring>
#include <algorithm>
#include <numeric>
@@ -41,6 +42,7 @@
#include "Command.h"
#include "LogFactory.h"
#include "Logger.h"
+#include "util.h"
namespace aria2 {
@@ -85,9 +87,10 @@ PortEventPoll::~PortEventPoll()
if(port_ != -1) {
int r;
while((r = close(port_)) == -1 && errno == EINTR);
+ int errNum = errno;
if(r == -1) {
logger_->error("Error occurred while closing port %d: %s",
- port_, strerror(errno));
+ port_, util::safeStrerror(errNum).c_str());
}
}
delete [] portEvents_;
@@ -120,9 +123,10 @@ void PortEventPoll::poll(const struct timeval& tv)
p->processEvents(pev.portev_events);
int r = port_associate(port_, PORT_SOURCE_FD, pev.portev_object,
p->getEvents().events, p);
+ int errNum = errno;
if(r == -1) {
logger_->error("port_associate failed for file descriptor %d: cause %s",
- pev.portev_object, strerror(errno));
+ pev.portev_object, util::safeStrerror(errNum).c_str());
}
}
}
@@ -171,11 +175,13 @@ bool PortEventPoll::addEvents(sock_t socket,
std::deque<SharedHandle<KSocketEntry> >::iterator i =
std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry);
int r = 0;
+ int errNum = 0;
if(i != socketEntries_.end() && (*i) == socketEntry) {
event.addSelf(*i);
A2PortEvent pv = (*i)->getEvents();
r = port_associate(port_, PORT_SOURCE_FD, (*i)->getSocket(),
pv.events, pv.socketEntry);
+ errNum = r;
} else {
socketEntries_.insert(i, socketEntry);
if(socketEntries_.size() > portEventsSize_) {
@@ -187,11 +193,12 @@ bool PortEventPoll::addEvents(sock_t socket,
A2PortEvent pv = socketEntry->getEvents();
r = port_associate(port_, PORT_SOURCE_FD, socketEntry->getSocket(),
pv.events, pv.socketEntry);
+ errNum = r;
}
if(r == -1) {
if(logger_->debug()) {
logger_->debug("Failed to add socket event %d:%s",
- socket, strerror(errno));
+ socket, util::safeStrerror(errNum).c_str());
}
return false;
} else {
@@ -223,17 +230,21 @@ bool PortEventPoll::deleteEvents(sock_t socket,
if(i != socketEntries_.end() && (*i) == socketEntry) {
event.removeSelf(*i);
int r = 0;
+ int errNum = 0;
if((*i)->eventEmpty()) {
r = port_dissociate(port_, PORT_SOURCE_FD, (*i)->getSocket());
+ errNum = errno;
socketEntries_.erase(i);
} else {
A2PortEvent pv = (*i)->getEvents();
r = port_associate(port_, PORT_SOURCE_FD, (*i)->getSocket(),
pv.events, pv.socketEntry);
+ errNum = errno;
}
if(r == -1) {
if(logger_->debug()) {
- logger_->debug("Failed to delete socket event:%s", strerror(errno));
+ logger_->debug("Failed to delete socket event:%s",
+ util::safeStrerror(errNum).c_str());
}
return false;
} else {
diff --git a/src/SelectEventPoll.cc b/src/SelectEventPoll.cc
index 9b3950fd..473091e3 100644
--- a/src/SelectEventPoll.cc
+++ b/src/SelectEventPoll.cc
@@ -40,7 +40,6 @@
#include <cstring>
#include <algorithm>
#include <numeric>
-#include <iostream>
#include "Command.h"
#include "LogFactory.h"
@@ -280,7 +279,6 @@ bool SelectEventPoll::addEvents(sock_t socket, Command* command,
SharedHandle<SocketEntry> socketEntry(new SocketEntry(socket));
std::deque<SharedHandle<SocketEntry> >::iterator i =
std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry);
- int r = 0;
if(i != socketEntries_.end() && (*i) == socketEntry) {
(*i)->addCommandEvent(command, events);
} else {
@@ -288,15 +286,7 @@ bool SelectEventPoll::addEvents(sock_t socket, Command* command,
socketEntry->addCommandEvent(command, events);
}
updateFdSet();
- if(r == -1) {
- if(logger_->debug()) {
- logger_->debug("Failed to add socket event %d:%s",
- socket, strerror(errno));
- }
- return false;
- } else {
- return true;
- }
+ return true;
}
bool SelectEventPoll::deleteEvents(sock_t socket, Command* command,
@@ -307,19 +297,11 @@ bool SelectEventPoll::deleteEvents(sock_t socket, Command* command,
std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry);
if(i != socketEntries_.end() && (*i) == socketEntry) {
(*i)->removeCommandEvent(command, events);
- int r = 0;
if((*i)->eventEmpty()) {
socketEntries_.erase(i);
}
updateFdSet();
- if(r == -1) {
- if(logger_->debug()) {
- logger_->debug("Failed to delete socket event:%s", strerror(errno));
- }
- return false;
- } else {
- return true;
- }
+ return true;
} else {
if(logger_->debug()) {
logger_->debug("Socket %d is not found in SocketEntries.", socket);
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index a7d196e9..f735ec01 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -92,32 +92,29 @@ namespace aria2 {
# define CLOSE(X) while(close(X) == -1 && errno == EINTR)
#endif // __MINGW32__
-static const char *errorMsg(const int err)
+namespace {
+std::string errorMsg(int errNum)
{
#ifndef __MINGW32__
- return strerror(err);
+ return util::safeStrerror(errNum);
#else
static char buf[256];
if (FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
- err,
+ errNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &buf,
sizeof(buf),
NULL
) == 0) {
- snprintf(buf, sizeof(buf), EX_SOCKET_UNKNOWN_ERROR, err, err);
+ snprintf(buf, sizeof(buf), EX_SOCKET_UNKNOWN_ERROR, errNum, errNum);
}
return buf;
#endif // __MINGW32__
}
-
-static const char *errorMsg()
-{
- return errorMsg(SOCKET_ERRNO);
-}
+} // namespace
int SocketCore::protocolFamily_ = AF_UNSPEC;
@@ -170,18 +167,23 @@ SocketCore::~SocketCore() {
void SocketCore::create(int family, int protocol)
{
+ int errNum;
closeConnection();
sock_t fd = socket(family, sockType_, protocol);
+ errNum = SOCKET_ERRNO;
if(fd == (sock_t) -1) {
throw DL_ABORT_EX
- (StringFormat("Failed to create socket. Cause:%s", errorMsg()).str());
+ (StringFormat
+ ("Failed to create socket. Cause:%s", errorMsg(errNum).c_str()).str());
}
int sockopt = 1;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(a2_sockopt_t) &sockopt, sizeof(sockopt)) < 0) {
+ errNum = SOCKET_ERRNO;
CLOSE(fd);
throw DL_ABORT_EX
- (StringFormat("Failed to create socket. Cause:%s", errorMsg()).str());
+ (StringFormat
+ ("Failed to create socket. Cause:%s", errorMsg(errNum).c_str()).str());
}
sockfd_ = fd;
}
@@ -190,13 +192,18 @@ static sock_t bindInternal(int family, int socktype, int protocol,
const struct sockaddr* addr, socklen_t addrlen,
std::string& error)
{
+ int errNum;
sock_t fd = socket(family, socktype, protocol);
+ errNum = SOCKET_ERRNO;
if(fd == (sock_t) -1) {
+ error = errorMsg(errNum);
return -1;
}
int sockopt = 1;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt,
sizeof(sockopt)) < 0) {
+ errNum = SOCKET_ERRNO;
+ error = errorMsg(errNum);
CLOSE(fd);
return -1;
}
@@ -205,13 +212,16 @@ static sock_t bindInternal(int family, int socktype, int protocol,
int sockopt = 1;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (a2_sockopt_t) &sockopt,
sizeof(sockopt)) < 0) {
+ errNum = SOCKET_ERRNO;
+ error = errorMsg(errNum);
CLOSE(fd);
return -1;
}
}
#endif // IPV6_V6ONLY
if(::bind(fd, addr, addrlen) == -1) {
- error = errorMsg();
+ errNum = SOCKET_ERRNO;
+ error = errorMsg(errNum);
CLOSE(fd);
return -1;
}
@@ -319,7 +329,9 @@ void SocketCore::bind(const struct sockaddr* addr, socklen_t addrlen)
void SocketCore::beginListen()
{
if(listen(sockfd_, 1) == -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_LISTEN, errorMsg()).str());
+ int errNum = SOCKET_ERRNO;
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_LISTEN, errorMsg(errNum).c_str()).str());
}
}
@@ -328,9 +340,13 @@ SocketCore* SocketCore::acceptConnection() const
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
sock_t fd;
- while((fd = accept(sockfd_, reinterpret_cast<struct sockaddr*>(&sockaddr), &len)) == (sock_t) -1 && SOCKET_ERRNO == A2_EINTR);
+ while((fd = accept(sockfd_, reinterpret_cast<struct sockaddr*>(&sockaddr),
+ &len)) == (sock_t) -1 &&
+ SOCKET_ERRNO == A2_EINTR);
+ int errNum = SOCKET_ERRNO;
if(fd == (sock_t) -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_ACCEPT, errorMsg()).str());
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_ACCEPT, errorMsg(errNum).c_str()).str());
}
return new SocketCore(fd, sockType_);
}
@@ -349,7 +365,9 @@ void SocketCore::getAddrInfo
{
struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr);
if(getsockname(sockfd_, addrp, &len) == -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str());
+ int errNum = SOCKET_ERRNO;
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_GET_NAME, errorMsg(errNum).c_str()).str());
}
}
@@ -367,7 +385,9 @@ void SocketCore::getPeerInfo(std::pair<std::string, uint16_t>& peerinfo) const
socklen_t len = sizeof(sockaddr);
struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr);
if(getpeername(sockfd_, addrp, &len) == -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str());
+ int errNum = SOCKET_ERRNO;
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_GET_NAME, errorMsg(errNum).c_str()).str());
}
peerinfo = util::getNumericNameInfo(addrp, len);
}
@@ -386,15 +406,19 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port)
}
WSAAPI_AUTO_DELETE<struct addrinfo*> resDeleter(res, freeaddrinfo);
struct addrinfo* rp;
+ int errNum;
for(rp = res; rp; rp = rp->ai_next) {
sock_t fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ errNum = SOCKET_ERRNO;
if(fd == (sock_t) -1) {
- error = errorMsg();
+ error = errorMsg(errNum);
continue;
}
int sockopt = 1;
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt, sizeof(sockopt)) < 0) {
- error = errorMsg();
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt,
+ sizeof(sockopt)) < 0) {
+ errNum = SOCKET_ERRNO;
+ error = errorMsg(errNum);
CLOSE(fd);
continue;
}
@@ -405,7 +429,8 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port)
i != eoi; ++i) {
if(::bind(fd,reinterpret_cast<const struct sockaddr*>(&(*i).first),
(*i).second) == -1) {
- error = errorMsg();
+ errNum = SOCKET_ERRNO;
+ error = errorMsg(errNum);
if(LogFactory::getInstance()->debug()) {
LogFactory::getInstance()->debug(EX_SOCKET_BIND, error.c_str());
}
@@ -425,7 +450,8 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port)
setNonBlockingMode();
if(connect(fd, rp->ai_addr, rp->ai_addrlen) == -1 &&
SOCKET_ERRNO != A2_EINPROGRESS) {
- error = errorMsg();
+ errNum = SOCKET_ERRNO;
+ error = errorMsg(errNum);
CLOSE(sockfd_);
sockfd_ = (sock_t) -1;
continue;
@@ -444,7 +470,9 @@ void SocketCore::setSockOpt
(int level, int optname, void* optval, socklen_t optlen)
{
if(setsockopt(sockfd_, level, optname, (a2_sockopt_t)optval, optlen) < 0) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_SET_OPT, errorMsg()).str());
+ int errNum = SOCKET_ERRNO;
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_SET_OPT, errorMsg(errNum).c_str()).str());
}
}
@@ -502,7 +530,9 @@ void SocketCore::setNonBlockingMode()
#ifdef __MINGW32__
static u_long flag = 1;
if (::ioctlsocket(sockfd_, FIONBIO, &flag) == -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_NONBLOCKING, errorMsg()).str());
+ int errNum = SOCKET_ERRNO;
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_NONBLOCKING, errorMsg(errNum).c_str()).str());
}
#else
int flags;
@@ -518,7 +548,9 @@ void SocketCore::setBlockingMode()
#ifdef __MINGW32__
static u_long flag = 0;
if (::ioctlsocket(sockfd_, FIONBIO, &flag) == -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_BLOCKING, errorMsg()).str());
+ int errNum = SOCKET_ERRNO;
+ throw DL_ABORT_EX(StringFormat
+ (EX_SOCKET_BLOCKING, errorMsg(errNum).c_str()).str());
}
#else
int flags;
@@ -576,13 +608,14 @@ bool SocketCore::isWritable(time_t timeout)
p.events = POLLOUT;
int r;
while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR);
+ int errNum = SOCKET_ERRNO;
if(r > 0) {
return p.revents&(POLLOUT|POLLHUP|POLLERR);
} else if(r == 0) {
return false;
} else {
throw DL_RETRY_EX
- (StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
+ (StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str()).str());
}
#else // !HAVE_POLL
# ifndef __MINGW32__
@@ -597,17 +630,19 @@ bool SocketCore::isWritable(time_t timeout)
tv.tv_usec = 0;
int r = select(sockfd_+1, NULL, &fds, NULL, &tv);
+ int errNum = SOCKET_ERRNO;
if(r == 1) {
return true;
} else if(r == 0) {
// time out
return false;
} else {
- if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) {
+ if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) {
return false;
} else {
throw DL_RETRY_EX
- (StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str());
+ (StringFormat(EX_SOCKET_CHECK_WRITABLE,
+ errorMsg(errNum).c_str()).str());
}
}
#endif // !HAVE_POLL
@@ -626,13 +661,14 @@ bool SocketCore::isReadable(time_t timeout)
p.events = POLLIN;
int r;
while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR);
+ int errNum = SOCKET_ERRNO;
if(r > 0) {
return p.revents&(POLLIN|POLLHUP|POLLERR);
} else if(r == 0) {
return false;
} else {
throw DL_RETRY_EX
- (StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
+ (StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str()).str());
}
#else // !HAVE_POLL
# ifndef __MINGW32__
@@ -647,17 +683,19 @@ bool SocketCore::isReadable(time_t timeout)
tv.tv_usec = 0;
int r = select(sockfd_+1, &fds, NULL, NULL, &tv);
+ int errNum = SOCKET_ERRNO;
if(r == 1) {
return true;
} else if(r == 0) {
// time out
return false;
} else {
- if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) {
+ if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) {
return false;
} else {
throw DL_RETRY_EX
- (StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str());
+ (StringFormat(EX_SOCKET_CHECK_READABLE,
+ errorMsg(errNum).c_str()).str());
}
}
#endif // !HAVE_POLL
@@ -699,12 +737,14 @@ ssize_t SocketCore::writeData(const char* data, size_t len)
if(!secure_) {
while((ret = send(sockfd_, data, len, 0)) == -1 && SOCKET_ERRNO == A2_EINTR);
+ int errNum = SOCKET_ERRNO;
if(ret == -1) {
- if(A2_WOULDBLOCK(SOCKET_ERRNO)) {
+ if(A2_WOULDBLOCK(errNum)) {
wantWrite_ = true;
ret = 0;
} else {
- throw DL_RETRY_EX(StringFormat(EX_SOCKET_SEND, errorMsg()).str());
+ throw DL_RETRY_EX(StringFormat(EX_SOCKET_SEND,
+ errorMsg(errNum).c_str()).str());
}
}
} else {
@@ -743,12 +783,14 @@ void SocketCore::readData(char* data, size_t& len)
if(!secure_) {
while((ret = recv(sockfd_, data, len, 0)) == -1 && SOCKET_ERRNO == A2_EINTR);
+ int errNum = SOCKET_ERRNO;
if(ret == -1) {
- if(A2_WOULDBLOCK(SOCKET_ERRNO)) {
+ if(A2_WOULDBLOCK(errNum)) {
wantRead_ = true;
ret = 0;
} else {
- throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV, errorMsg()).str());
+ throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV,
+ errorMsg(errNum).c_str()).str());
}
}
} else {
@@ -789,12 +831,14 @@ void SocketCore::peekData(char* data, size_t& len)
if(!secure_) {
while((ret = recv(sockfd_, data, len, MSG_PEEK)) == -1 &&
SOCKET_ERRNO == A2_EINTR);
+ int errNum = SOCKET_ERRNO;
if(ret == -1) {
- if(A2_WOULDBLOCK(SOCKET_ERRNO)) {
+ if(A2_WOULDBLOCK(errNum)) {
wantRead_ = true;
ret = 0;
} else {
- throw DL_RETRY_EX(StringFormat(EX_SOCKET_PEEK, errorMsg()).str());
+ throw DL_RETRY_EX(StringFormat(EX_SOCKET_PEEK,
+ errorMsg(errNum).c_str()).str());
}
}
} else {
@@ -1133,20 +1177,23 @@ ssize_t SocketCore::writeData(const char* data, size_t len,
WSAAPI_AUTO_DELETE<struct addrinfo*> resDeleter(res, freeaddrinfo);
struct addrinfo* rp;
ssize_t r = -1;
+ int errNum = 0;
for(rp = res; rp; rp = rp->ai_next) {
while((r = sendto(sockfd_, data, len, 0, rp->ai_addr, rp->ai_addrlen)) == -1
&& A2_EINTR == SOCKET_ERRNO);
+ errNum = SOCKET_ERRNO;
if(r == static_cast<ssize_t>(len)) {
break;
}
- if(r == -1 && A2_WOULDBLOCK(SOCKET_ERRNO)) {
+ if(r == -1 && A2_WOULDBLOCK(errNum)) {
wantWrite_ = true;
r = 0;
break;
}
}
if(r == -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, errorMsg()).str());
+ throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND,
+ errorMsg(errNum).c_str()).str());
}
return r;
}
@@ -1163,12 +1210,14 @@ ssize_t SocketCore::readDataFrom(char* data, size_t len,
ssize_t r;
while((r = recvfrom(sockfd_, data, len, 0, addrp, &sockaddrlen)) == -1 &&
A2_EINTR == SOCKET_ERRNO);
+ int errNum = SOCKET_ERRNO;
if(r == -1) {
- if(A2_WOULDBLOCK(SOCKET_ERRNO)) {
+ if(A2_WOULDBLOCK(errNum)) {
wantRead_ = true;
r = 0;
} else {
- throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV, errorMsg()).str());
+ throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV,
+ errorMsg(errNum).c_str()).str());
}
} else {
sender = util::getNumericNameInfo(addrp, sockaddrlen);
@@ -1182,9 +1231,11 @@ std::string SocketCore::getSocketError() const
int error;
socklen_t optlen = sizeof(error);
- if(getsockopt(sockfd_, SOL_SOCKET, SO_ERROR, (a2_sockopt_t) &error, &optlen) == -1) {
+ if(getsockopt(sockfd_, SOL_SOCKET, SO_ERROR,
+ (a2_sockopt_t) &error, &optlen) == -1) {
+ int errNum = SOCKET_ERRNO;
throw DL_ABORT_EX(StringFormat("Failed to get socket error: %s",
- errorMsg()).str());
+ errorMsg(errNum).c_str()).str());
}
if(error != 0) {
return errorMsg(error);
@@ -1243,7 +1294,9 @@ void getInterfaceAddress
// First find interface in interface addresses
struct ifaddrs* ifaddr = 0;
if(getifaddrs(&ifaddr) == -1) {
- logger->info(MSG_INTERFACE_NOT_FOUND, iface.c_str(), errorMsg());
+ int errNum = SOCKET_ERRNO;
+ logger->info(MSG_INTERFACE_NOT_FOUND,
+ iface.c_str(), errorMsg(errNum).c_str());
} else {
auto_delete<struct ifaddrs*> ifaddrDeleter(ifaddr, freeifaddrs);
for(struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
diff --git a/src/message.h b/src/message.h
index e04ab897..2022ea05 100644
--- a/src/message.h
+++ b/src/message.h
@@ -229,9 +229,8 @@
#define EX_FILE_OFFSET_OUT_OF_RANGE _("The offset is out of range, offset=%s")
#define EX_NOT_DIRECTORY _("%s is not a directory.")
#define EX_MAKE_DIR _("Failed to make the directory %s, cause: %s")
-#define EX_SEGMENT_FILE_OPEN _("Failed to open the segment file %s, cause: %s")
-#define EX_SEGMENT_FILE_WRITE _("Failed to write into the segment file %s, cause: %s")
-#define EX_SEGMENT_FILE_READ _("Failed to read from the segment file %s, cause: %s")
+#define EX_SEGMENT_FILE_WRITE "Failed to write into the segment file %s"
+#define EX_SEGMENT_FILE_READ "Failed to read from the segment file %s"
#define EX_SOCKET_OPEN _("Failed to open a socket, cause: %s")
#define EX_SOCKET_SET_OPT _("Failed to set a socket option, cause: %s")
diff --git a/src/util.cc b/src/util.cc
index e5822b2d..53b0919c 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -1128,10 +1128,13 @@ unsigned int alphaToNum(const std::string& alphabets)
void mkdirs(const std::string& dirpath)
{
File dir(dirpath);
- if(!dir.mkdirs() &&!dir.isDir()) {
- throw DL_ABORT_EX
- (StringFormat(EX_MAKE_DIR, dir.getPath().c_str(),
- strerror(errno)).str());
+ if(!dir.mkdirs()) {
+ int errNum = errno;
+ if(!dir.isDir()) {
+ throw DL_ABORT_EX
+ (StringFormat(EX_MAKE_DIR, dir.getPath().c_str(),
+ safeStrerror(errNum).c_str()).str());
+ }
}
}
@@ -1171,7 +1174,8 @@ void* allocateAlignedMemory(size_t alignment, size_t size)
int res;
if((res = posix_memalign(&buffer, alignment, size)) != 0) {
throw FATAL_EXCEPTION
- (StringFormat("Error in posix_memalign: %s", strerror(res)).str());
+ (StringFormat("Error in posix_memalign: %s",
+ util::safeStrerror(res).c_str()).str());
}
return buffer;
}
@@ -1498,6 +1502,20 @@ std::string encodeNonUtf8(const std::string& s)
return util::isUtf8(s)?s:util::percentEncode(s);
}
+std::string makeString(const char* str)
+{
+ if(str) {
+ return str;
+ } else {
+ return A2STR::NIL;
+ }
+}
+
+std::string safeStrerror(int errNum)
+{
+ return makeString(strerror(errNum));
+}
+
} // namespace util
} // namespace aria2
diff --git a/src/util.h b/src/util.h
index 8c47bf04..6982fa83 100644
--- a/src/util.h
+++ b/src/util.h
@@ -427,6 +427,14 @@ std::string createSafePath(const std::string& dir, const std::string& filename);
std::string encodeNonUtf8(const std::string& s);
+// Create string safely. If str is NULL, returns empty string.
+// Otherwise, returns std::string(str).
+std::string makeString(const char* str);
+
+// This function is basically the same with strerror(errNum) but when
+// strerror returns NULL, this function returns empty string.
+std::string safeStrerror(int errNum);
+
} // namespace util
} // namespace aria2