You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2016/10/19 12:01:41 UTC

[3/4] lucy git commit: Stop using strerror

Stop using strerror

Especially with non-English locales, 'strerror' can return strings in
arbitrary encodings. Now that CB_VCatF has more thorough UTF-8 checks,
this can result in unwanted exceptions.

'strerror' also isn't thread-safe.

Add some utility functions to set the global error object, optionally
followed by a textual representation of the error in 'errno' or
returned by 'GetLastError' on Windows. Convert 'errno' values using
custom messages for all 'errno' macros from current Linux and Darwin
kernels.

Also make some error messages more informative by adding the reason
for the error, e.g. in FSDH_do_open which may fail when opening an
index.

Fixes LUCY-311.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/87ea1b4d
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/87ea1b4d
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/87ea1b4d

Branch: refs/heads/master
Commit: 87ea1b4d195196611333f1148e1f4dce2166c2e4
Parents: e30057d
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Oct 8 16:16:48 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed Oct 19 13:48:56 2016 +0200

----------------------------------------------------------------------
 core/Lucy/Store/ErrorMessage.c   | 873 ++++++++++++++++++++++++++++++++++
 core/Lucy/Store/ErrorMessage.cfh |  50 ++
 core/Lucy/Store/FSDirHandle.c    |  12 +-
 core/Lucy/Store/FSFileHandle.c   | 129 ++---
 core/Lucy/Store/FSFolder.c       |  19 +-
 core/Lucy/Store/Lock.c           |   1 -
 core/Lucy/Store/LockFactory.c    |   1 -
 7 files changed, 986 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/ErrorMessage.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/ErrorMessage.c b/core/Lucy/Store/ErrorMessage.c
new file mode 100644
index 0000000..e5d95f6
--- /dev/null
+++ b/core/Lucy/Store/ErrorMessage.c
@@ -0,0 +1,873 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+
+#include "Lucy/Store/ErrorMessage.h"
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Util/Memory.h"
+
+#include <errno.h>
+#include <string.h>
+
+void
+ErrMsg_set(const char *fmt, ...) {
+    CharBuf *buf = CB_new(0);
+
+    va_list args;
+    va_start(args, fmt);
+    CB_VCatF(buf, fmt, args);
+    va_end(args);
+
+    Err_set_error(Err_new(CB_Yield_String(buf)));
+    DECREF(buf);
+}
+
+void
+ErrMsg_set_with_errno(const char *fmt, ...) {
+    int cur_errno = errno;
+
+    CharBuf *buf = CB_new(0);
+
+    va_list args;
+    va_start(args, fmt);
+    CB_VCatF(buf, fmt, args);
+    va_end(args);
+
+    CB_Cat_Trusted_Utf8(buf, ": ", 2);
+
+    const char *msg = ErrMsg_strerror(cur_errno);
+
+    if (msg != NULL) {
+        CB_Cat_Trusted_Utf8(buf, msg, strlen(msg));
+    }
+    else {
+        CB_catf(buf, "Unknown error: %i32", (int32_t)cur_errno);
+    }
+
+    Err_set_error(Err_new(CB_Yield_String(buf)));
+    DECREF(buf);
+}
+
+void
+ErrMsg_set_with_win_error(const char *fmt, ...) {
+    char *win_error = Err_win_error();
+
+    CharBuf *buf = CB_new(0);
+
+    va_list args;
+    va_start(args, fmt);
+    CB_VCatF(buf, fmt, args);
+    va_end(args);
+
+    CB_Cat_Trusted_Utf8(buf, ": ", 2);
+    CB_Cat_Utf8(buf, win_error, strlen(win_error));
+
+    Err_set_error(Err_new(CB_Yield_String(buf)));
+    DECREF(buf);
+    FREEMEM(win_error);
+}
+
+const char*
+ErrMsg_strerror(int my_errno) {
+    const char *msg = NULL;
+
+    switch (my_errno) {
+        case 0:
+            msg = "No error";
+            break;
+
+        // Error macros from Linux.
+#ifdef E2BIG
+        case E2BIG:
+            msg = "Argument list too long";
+            break;
+#endif
+#ifdef EACCES
+        case EACCES:
+            msg = "Permission denied";
+            break;
+#endif
+#ifdef EADDRINUSE
+        case EADDRINUSE:
+            msg = "Address already in use";
+            break;
+#endif
+#ifdef EADDRNOTAVAIL
+        case EADDRNOTAVAIL:
+            msg = "Cannot assign requested address";
+            break;
+#endif
+#ifdef EADV
+        case EADV:
+            msg = "Advertise error";
+            break;
+#endif
+#ifdef EAFNOSUPPORT
+        case EAFNOSUPPORT:
+            msg = "Address family not supported by protocol";
+            break;
+#endif
+#ifdef EAGAIN
+        case EAGAIN:
+            msg = "Try again";
+            break;
+#endif
+#ifdef EALREADY
+        case EALREADY:
+            msg = "Operation already in progress";
+            break;
+#endif
+#ifdef EBADE
+        case EBADE:
+            msg = "Invalid exchange";
+            break;
+#endif
+#ifdef EBADF
+        case EBADF:
+            msg = "Bad file number";
+            break;
+#endif
+#ifdef EBADFD
+        case EBADFD:
+            msg = "File descriptor in bad state";
+            break;
+#endif
+#ifdef EBADMSG
+        case EBADMSG:
+            msg = "Not a data message";
+            break;
+#endif
+#ifdef EBADR
+        case EBADR:
+            msg = "Invalid request descriptor";
+            break;
+#endif
+#ifdef EBADRQC
+        case EBADRQC:
+            msg = "Invalid request code";
+            break;
+#endif
+#ifdef EBADSLT
+        case EBADSLT:
+            msg = "Invalid slot";
+            break;
+#endif
+#ifdef EBFONT
+        case EBFONT:
+            msg = "Bad font file format";
+            break;
+#endif
+#ifdef EBUSY
+        case EBUSY:
+            msg = "Device or resource busy";
+            break;
+#endif
+#ifdef ECANCELED
+        case ECANCELED:
+            msg = "Operation Canceled";
+            break;
+#endif
+#ifdef ECHILD
+        case ECHILD:
+            msg = "No child processes";
+            break;
+#endif
+#ifdef ECHRNG
+        case ECHRNG:
+            msg = "Channel number out of range";
+            break;
+#endif
+#ifdef ECOMM
+        case ECOMM:
+            msg = "Communication error on send";
+            break;
+#endif
+#ifdef ECONNABORTED
+        case ECONNABORTED:
+            msg = "Software caused connection abort";
+            break;
+#endif
+#ifdef ECONNREFUSED
+        case ECONNREFUSED:
+            msg = "Connection refused";
+            break;
+#endif
+#ifdef ECONNRESET
+        case ECONNRESET:
+            msg = "Connection reset by peer";
+            break;
+#endif
+#ifdef EDEADLK
+        case EDEADLK:
+            msg = "Resource deadlock would occur";
+            break;
+#endif
+#ifdef EDESTADDRREQ
+        case EDESTADDRREQ:
+            msg = "Destination address required";
+            break;
+#endif
+#ifdef EDOM
+        case EDOM:
+            msg = "Math argument out of domain of func";
+            break;
+#endif
+#ifdef EDOTDOT
+        case EDOTDOT:
+            msg = "RFS specific error";
+            break;
+#endif
+#ifdef EDQUOT
+        case EDQUOT:
+            msg = "Quota exceeded";
+            break;
+#endif
+#ifdef EEXIST
+        case EEXIST:
+            msg = "File exists";
+            break;
+#endif
+#ifdef EFAULT
+        case EFAULT:
+            msg = "Bad address";
+            break;
+#endif
+#ifdef EFBIG
+        case EFBIG:
+            msg = "File too large";
+            break;
+#endif
+#ifdef EHOSTDOWN
+        case EHOSTDOWN:
+            msg = "Host is down";
+            break;
+#endif
+#ifdef EHOSTUNREACH
+        case EHOSTUNREACH:
+            msg = "No route to host";
+            break;
+#endif
+#ifdef EHWPOISON
+        case EHWPOISON:
+            msg = "Memory page has hardware error";
+            break;
+#endif
+#ifdef EIDRM
+        case EIDRM:
+            msg = "Identifier removed";
+            break;
+#endif
+#ifdef EILSEQ
+        case EILSEQ:
+            msg = "Illegal byte sequence";
+            break;
+#endif
+#ifdef EINPROGRESS
+        case EINPROGRESS:
+            msg = "Operation now in progress";
+            break;
+#endif
+#ifdef EINTR
+        case EINTR:
+            msg = "Interrupted system call";
+            break;
+#endif
+#ifdef EINVAL
+        case EINVAL:
+            msg = "Invalid argument";
+            break;
+#endif
+#ifdef EIO
+        case EIO:
+            msg = "I/O error";
+            break;
+#endif
+#ifdef EISCONN
+        case EISCONN:
+            msg = "Transport endpoint is already connected";
+            break;
+#endif
+#ifdef EISDIR
+        case EISDIR:
+            msg = "Is a directory";
+            break;
+#endif
+#ifdef EISNAM
+        case EISNAM:
+            msg = "Is a named type file";
+            break;
+#endif
+#ifdef EKEYEXPIRED
+        case EKEYEXPIRED:
+            msg = "Key has expired";
+            break;
+#endif
+#ifdef EKEYREJECTED
+        case EKEYREJECTED:
+            msg = "Key was rejected by service";
+            break;
+#endif
+#ifdef EKEYREVOKED
+        case EKEYREVOKED:
+            msg = "Key has been revoked";
+            break;
+#endif
+#ifdef EL2HLT
+        case EL2HLT:
+            msg = "Level 2 halted";
+            break;
+#endif
+#ifdef EL2NSYNC
+        case EL2NSYNC:
+            msg = "Level 2 not synchronized";
+            break;
+#endif
+#ifdef EL3HLT
+        case EL3HLT:
+            msg = "Level 3 halted";
+            break;
+#endif
+#ifdef EL3RST
+        case EL3RST:
+            msg = "Level 3 reset";
+            break;
+#endif
+#ifdef ELIBACC
+        case ELIBACC:
+            msg = "Can not access a needed shared library";
+            break;
+#endif
+#ifdef ELIBBAD
+        case ELIBBAD:
+            msg = "Accessing a corrupted shared library";
+            break;
+#endif
+#ifdef ELIBEXEC
+        case ELIBEXEC:
+            msg = "Cannot exec a shared library directly";
+            break;
+#endif
+#ifdef ELIBMAX
+        case ELIBMAX:
+            msg = "Attempting to link in too many shared libraries";
+            break;
+#endif
+#ifdef ELIBSCN
+        case ELIBSCN:
+            msg = ".lib section in a.out corrupted";
+            break;
+#endif
+#ifdef ELNRNG
+        case ELNRNG:
+            msg = "Link number out of range";
+            break;
+#endif
+#ifdef ELOOP
+        case ELOOP:
+            msg = "Too many symbolic links encountered";
+            break;
+#endif
+#ifdef EMEDIUMTYPE
+        case EMEDIUMTYPE:
+            msg = "Wrong medium type";
+            break;
+#endif
+#ifdef EMFILE
+        case EMFILE:
+            msg = "Too many open files";
+            break;
+#endif
+#ifdef EMLINK
+        case EMLINK:
+            msg = "Too many links";
+            break;
+#endif
+#ifdef EMSGSIZE
+        case EMSGSIZE:
+            msg = "Message too long";
+            break;
+#endif
+#ifdef EMULTIHOP
+        case EMULTIHOP:
+            msg = "Multihop attempted";
+            break;
+#endif
+#ifdef ENAMETOOLONG
+        case ENAMETOOLONG:
+            msg = "File name too long";
+            break;
+#endif
+#ifdef ENAVAIL
+        case ENAVAIL:
+            msg = "No XENIX semaphores available";
+            break;
+#endif
+#ifdef ENETDOWN
+        case ENETDOWN:
+            msg = "Network is down";
+            break;
+#endif
+#ifdef ENETRESET
+        case ENETRESET:
+            msg = "Network dropped connection because of reset";
+            break;
+#endif
+#ifdef ENETUNREACH
+        case ENETUNREACH:
+            msg = "Network is unreachable";
+            break;
+#endif
+#ifdef ENFILE
+        case ENFILE:
+            msg = "File table overflow";
+            break;
+#endif
+#ifdef ENOANO
+        case ENOANO:
+            msg = "No anode";
+            break;
+#endif
+#ifdef ENOBUFS
+        case ENOBUFS:
+            msg = "No buffer space available";
+            break;
+#endif
+#ifdef ENOCSI
+        case ENOCSI:
+            msg = "No CSI structure available";
+            break;
+#endif
+#ifdef ENODATA
+        case ENODATA:
+            msg = "No data available";
+            break;
+#endif
+#ifdef ENODEV
+        case ENODEV:
+            msg = "No such device";
+            break;
+#endif
+#ifdef ENOENT
+        case ENOENT:
+            msg = "No such file or directory";
+            break;
+#endif
+#ifdef ENOEXEC
+        case ENOEXEC:
+            msg = "Exec format error";
+            break;
+#endif
+#ifdef ENOKEY
+        case ENOKEY:
+            msg = "Required key not available";
+            break;
+#endif
+#ifdef ENOLCK
+        case ENOLCK:
+            msg = "No record locks available";
+            break;
+#endif
+#ifdef ENOLINK
+        case ENOLINK:
+            msg = "Link has been severed";
+            break;
+#endif
+#ifdef ENOMEDIUM
+        case ENOMEDIUM:
+            msg = "No medium found";
+            break;
+#endif
+#ifdef ENOMEM
+        case ENOMEM:
+            msg = "Out of memory";
+            break;
+#endif
+#ifdef ENOMSG
+        case ENOMSG:
+            msg = "No message of desired type";
+            break;
+#endif
+#ifdef ENONET
+        case ENONET:
+            msg = "Machine is not on the network";
+            break;
+#endif
+#ifdef ENOPKG
+        case ENOPKG:
+            msg = "Package not installed";
+            break;
+#endif
+#ifdef ENOPROTOOPT
+        case ENOPROTOOPT:
+            msg = "Protocol not available";
+            break;
+#endif
+#ifdef ENOSPC
+        case ENOSPC:
+            msg = "No space left on device";
+            break;
+#endif
+#ifdef ENOSR
+        case ENOSR:
+            msg = "Out of streams resources";
+            break;
+#endif
+#ifdef ENOSTR
+        case ENOSTR:
+            msg = "Device not a stream";
+            break;
+#endif
+#ifdef ENOSYS
+        case ENOSYS:
+            msg = "Invalid system call number";
+            break;
+#endif
+#ifdef ENOTBLK
+        case ENOTBLK:
+            msg = "Block device required";
+            break;
+#endif
+#ifdef ENOTCONN
+        case ENOTCONN:
+            msg = "Transport endpoint is not connected";
+            break;
+#endif
+#ifdef ENOTDIR
+        case ENOTDIR:
+            msg = "Not a directory";
+            break;
+#endif
+#ifdef ENOTEMPTY
+        case ENOTEMPTY:
+            msg = "Directory not empty";
+            break;
+#endif
+#ifdef ENOTNAM
+        case ENOTNAM:
+            msg = "Not a XENIX named type file";
+            break;
+#endif
+#ifdef ENOTRECOVERABLE
+        case ENOTRECOVERABLE:
+            msg = "State not recoverable";
+            break;
+#endif
+#ifdef ENOTSOCK
+        case ENOTSOCK:
+            msg = "Socket operation on non-socket";
+            break;
+#endif
+#ifdef ENOTTY
+        case ENOTTY:
+            msg = "Not a typewriter";
+            break;
+#endif
+#ifdef ENOTUNIQ
+        case ENOTUNIQ:
+            msg = "Name not unique on network";
+            break;
+#endif
+#ifdef ENXIO
+        case ENXIO:
+            msg = "No such device or address";
+            break;
+#endif
+#ifdef EOPNOTSUPP
+        case EOPNOTSUPP:
+            msg = "Operation not supported on transport endpoint";
+            break;
+#endif
+#ifdef EOVERFLOW
+        case EOVERFLOW:
+            msg = "Value too large for defined data type";
+            break;
+#endif
+#ifdef EOWNERDEAD
+        case EOWNERDEAD:
+            msg = "Owner died";
+            break;
+#endif
+#ifdef EPERM
+        case EPERM:
+            msg = "Operation not permitted";
+            break;
+#endif
+#ifdef EPFNOSUPPORT
+        case EPFNOSUPPORT:
+            msg = "Protocol family not supported";
+            break;
+#endif
+#ifdef EPIPE
+        case EPIPE:
+            msg = "Broken pipe";
+            break;
+#endif
+#ifdef EPROTO
+        case EPROTO:
+            msg = "Protocol error";
+            break;
+#endif
+#ifdef EPROTONOSUPPORT
+        case EPROTONOSUPPORT:
+            msg = "Protocol not supported";
+            break;
+#endif
+#ifdef EPROTOTYPE
+        case EPROTOTYPE:
+            msg = "Protocol wrong type for socket";
+            break;
+#endif
+#ifdef ERANGE
+        case ERANGE:
+            msg = "Math result not representable";
+            break;
+#endif
+#ifdef EREMCHG
+        case EREMCHG:
+            msg = "Remote address changed";
+            break;
+#endif
+#ifdef EREMOTE
+        case EREMOTE:
+            msg = "Object is remote";
+            break;
+#endif
+#ifdef EREMOTEIO
+        case EREMOTEIO:
+            msg = "Remote I/O error";
+            break;
+#endif
+#ifdef ERESTART
+        case ERESTART:
+            msg = "Interrupted system call should be restarted";
+            break;
+#endif
+#ifdef ERFKILL
+        case ERFKILL:
+            msg = "Operation not possible due to RF-kill";
+            break;
+#endif
+#ifdef EROFS
+        case EROFS:
+            msg = "Read-only file system";
+            break;
+#endif
+#ifdef ESHUTDOWN
+        case ESHUTDOWN:
+            msg = "Cannot send after transport endpoint shutdown";
+            break;
+#endif
+#ifdef ESOCKTNOSUPPORT
+        case ESOCKTNOSUPPORT:
+            msg = "Socket type not supported";
+            break;
+#endif
+#ifdef ESPIPE
+        case ESPIPE:
+            msg = "Illegal seek";
+            break;
+#endif
+#ifdef ESRCH
+        case ESRCH:
+            msg = "No such process";
+            break;
+#endif
+#ifdef ESRMNT
+        case ESRMNT:
+            msg = "Srmount error";
+            break;
+#endif
+#ifdef ESTALE
+        case ESTALE:
+            msg = "Stale file handle";
+            break;
+#endif
+#ifdef ESTRPIPE
+        case ESTRPIPE:
+            msg = "Streams pipe error";
+            break;
+#endif
+#ifdef ETIME
+        case ETIME:
+            msg = "Timer expired";
+            break;
+#endif
+#ifdef ETIMEDOUT
+        case ETIMEDOUT:
+            msg = "Connection timed out";
+            break;
+#endif
+#ifdef ETOOMANYREFS
+        case ETOOMANYREFS:
+            msg = "Too many references: cannot splice";
+            break;
+#endif
+#ifdef ETXTBSY
+        case ETXTBSY:
+            msg = "Text file busy";
+            break;
+#endif
+#ifdef EUCLEAN
+        case EUCLEAN:
+            msg = "Structure needs cleaning";
+            break;
+#endif
+#ifdef EUNATCH
+        case EUNATCH:
+            msg = "Protocol driver not attached";
+            break;
+#endif
+#ifdef EUSERS
+        case EUSERS:
+            msg = "Too many users";
+            break;
+#endif
+#ifdef EXDEV
+        case EXDEV:
+            msg = "Cross-device link";
+            break;
+#endif
+#ifdef EXFULL
+        case EXFULL:
+            msg = "Exchange full";
+            break;
+#endif
+
+        // Additional error macros from Darwin.
+#ifdef EAUTH
+        case EAUTH:
+            msg = "Authentication error";
+            break;
+#endif
+#ifdef EBADARCH
+        case EBADARCH:
+            msg = "Bad CPU type in executable";
+            break;
+#endif
+#ifdef EBADEXEC
+        case EBADEXEC:
+            msg = "Bad executable";
+            break;
+#endif
+#ifdef EBADMACHO
+        case EBADMACHO:
+            msg = "Malformed Macho file";
+            break;
+#endif
+#ifdef EBADRPC
+        case EBADRPC:
+            msg = "RPC struct is bad";
+            break;
+#endif
+#ifdef EDEVERR
+        case EDEVERR:
+            msg = "Device error, e.g. paper out";
+            break;
+#endif
+#ifdef EFTYPE
+        case EFTYPE:
+            msg = "Inappropriate file type or format";
+            break;
+#endif
+#ifdef ELAST
+        case ELAST:
+            msg = "Must be equal largest errno";
+            break;
+#endif
+#ifdef ENEEDAUTH
+        case ENEEDAUTH:
+            msg = "Need authenticator";
+            break;
+#endif
+#ifdef ENOATTR
+        case ENOATTR:
+            msg = "Attribute not found";
+            break;
+#endif
+#ifdef ENOPOLICY
+        case ENOPOLICY:
+            msg = "No such policy registered";
+            break;
+#endif
+#ifdef EPROCLIM
+        case EPROCLIM:
+            msg = "Too many processes";
+            break;
+#endif
+#ifdef EPROCUNAVAIL
+        case EPROCUNAVAIL:
+            msg = "Bad procedure for program";
+            break;
+#endif
+#ifdef EPROGMISMATCH
+        case EPROGMISMATCH:
+            msg = "Program version wrong";
+            break;
+#endif
+#ifdef EPROGUNAVAIL
+        case EPROGUNAVAIL:
+            msg = "RPC prog. not avail";
+            break;
+#endif
+#ifdef EPWROFF
+        case EPWROFF:
+            msg = "Device power is off";
+            break;
+#endif
+#ifdef EQFULL
+        case EQFULL:
+            msg = "Interface output queue is full";
+            break;
+#endif
+#ifdef ERPCMISMATCH
+        case ERPCMISMATCH:
+            msg = "RPC version wrong";
+            break;
+#endif
+#ifdef ESHLIBVERS
+        case ESHLIBVERS:
+            msg = "Shared library version mismatch";
+            break;
+#endif
+
+        // These macros might share an error code
+#if defined(EDEADLOCK) && (!defined(EDEADLK) || EDEADLOCK != EDEADLK)
+        case EDEADLOCK:
+            msg = "Resource deadlock would occur";
+            break;
+#endif
+#if defined(ENOTSUP) && (!defined(EOPNOTSUPP) || ENOTSUP != EOPNOTSUPP)
+        case ENOTSUP:
+            msg = "Operation not supported";
+            break;
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || EWOULDBLOCK != EAGAIN)
+        case EWOULDBLOCK:
+            msg = "Operation would block";
+            break;
+#endif
+
+        default:
+            msg = NULL;
+            break;
+    }
+
+    return msg;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/ErrorMessage.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/ErrorMessage.cfh b/core/Lucy/Store/ErrorMessage.cfh
new file mode 100644
index 0000000..8b462e3
--- /dev/null
+++ b/core/Lucy/Store/ErrorMessage.cfh
@@ -0,0 +1,50 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Lucy;
+
+/** Utility functions for error messages. Should probably be moved to
+ * Clownfish.
+ */
+inert class Lucy::Store::ErrorMessage nickname ErrMsg {
+
+    /** Set the global Err object with a message given by the format string
+     * and varargs.
+     */
+    inert void
+    set(const char *fmt, ...);
+
+    /** Return an error message for an `errno` value, or NULL if the value
+     * is unknown.
+     */
+    inert const char*
+    strerror(int my_errno);
+
+    /** Set the global Err object with a message given by the format string
+     * and varargs, followed by a textual representation of the error in
+     * `errno`.
+     */
+    inert void
+    set_with_errno(const char *fmt, ...);
+
+    /** Set the global Err object with a message given by the format string
+     * and varargs, followed by a textual representation of the error
+     * returned from `GetLastError`.
+     */
+    inert void
+    set_with_win_error(const char *fmt, ...);
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/FSDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/FSDirHandle.c b/core/Lucy/Store/FSDirHandle.c
index 4840677..11ed557 100644
--- a/core/Lucy/Store/FSDirHandle.c
+++ b/core/Lucy/Store/FSDirHandle.c
@@ -18,7 +18,6 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <errno.h>
 #include <sys/stat.h>
 
 #include "charmony.h"
@@ -26,6 +25,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Vector.h"
+#include "Lucy/Store/ErrorMessage.h"
 #include "Lucy/Store/FSDirHandle.h"
 
 #ifdef CHY_HAS_SYS_TYPES_H
@@ -80,8 +80,7 @@ FSDH_do_open(FSDirHandle *self, String *dir) {
 
     if (dir_path_size >= MAX_PATH - 2) {
         // Deal with Windows ceiling on file path lengths.
-        Err_set_error(Err_new(Str_newf("Directory path is too long: %o",
-                                       dir)));
+        ErrMsg_set("Directory path is too long: %o", dir);
         CFISH_DECREF(self);
         return NULL;
     }
@@ -95,7 +94,7 @@ FSDH_do_open(FSDirHandle *self, String *dir) {
         = FindFirstFile(search_string, (WIN32_FIND_DATA*)ivars->sys_dir_entry);
     if (INVALID_HANDLE_VALUE == ivars->sys_dirhandle) {
         // Directory inaccessible or doesn't exist.
-        Err_set_error(Err_new(Str_newf("Failed to open dir '%o'", dir)));
+        ErrMsg_set_with_win_error("Failed to open dir '%o'", dir);
         CFISH_DECREF(self);
         return NULL;
     }
@@ -218,7 +217,7 @@ FSDH_do_open(FSDirHandle *self, String *dir) {
     ivars->sys_dirhandle = opendir(dir_path_ptr);
     FREEMEM(dir_path_ptr);
     if (!ivars->sys_dirhandle) {
-        Err_set_error(Err_new(Str_newf("Failed to opendir '%o'", dir)));
+        ErrMsg_set_with_errno("Failed to opendir '%o'", dir);
         DECREF(self);
         return NULL;
     }
@@ -315,8 +314,7 @@ FSDH_Close_IMP(FSDirHandle *self) {
         DIR *sys_dirhandle = (DIR*)ivars->sys_dirhandle;
         ivars->sys_dirhandle = NULL;
         if (closedir(sys_dirhandle) == -1) {
-            Err_set_error(Err_new(Str_newf("Error closing dirhandle: %s",
-                                           strerror(errno))));
+            ErrMsg_set_with_errno("Error closing dirhandle");
             return false;
         }
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/FSFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/FSFileHandle.c b/core/Lucy/Store/FSFileHandle.c
index 235d8f1..494d661 100644
--- a/core/Lucy/Store/FSFileHandle.c
+++ b/core/Lucy/Store/FSFileHandle.c
@@ -19,7 +19,6 @@
 
 #include "charmony.h"
 
-#include <errno.h>
 #include <stdio.h>
 #include <fcntl.h> // open, POSIX flags
 
@@ -36,6 +35,7 @@
   #error "No support for memory mapped files"
 #endif
 
+#include "Lucy/Store/ErrorMessage.h"
 #include "Lucy/Store/FSFileHandle.h"
 #include "Lucy/Store/FileWindow.h"
 
@@ -95,7 +95,7 @@ FSFH_do_open(FSFileHandle *self, String *path, uint32_t flags) {
     FH_do_open((FileHandle*)self, path, flags);
     FSFileHandleIVARS *const ivars = FSFH_IVARS(self);
     if (!path || !Str_Get_Size(path)) {
-        Err_set_error(Err_new(Str_newf("Missing required param 'path'")));
+        ErrMsg_set("Missing required param 'path'");
         CFISH_DECREF(self);
         return NULL;
     }
@@ -107,8 +107,7 @@ FSFH_do_open(FSFileHandle *self, String *path, uint32_t flags) {
         FREEMEM(path_ptr);
         if (ivars->fd == -1) {
             ivars->fd = 0;
-            Err_set_error(Err_new(Str_newf("Attempt to open '%o' failed: %s",
-                                           path, strerror(errno))));
+            ErrMsg_set_with_errno("Attempt to open '%o' failed", path);
             CFISH_DECREF(self);
             return NULL;
         }
@@ -119,8 +118,7 @@ FSFH_do_open(FSFileHandle *self, String *path, uint32_t flags) {
             // Derive length.
             ivars->len = chy_lseek64(ivars->fd, INT64_C(0), SEEK_END);
             if (ivars->len == -1) {
-                Err_set_error(Err_new(Str_newf("lseek64 on %o failed: %s",
-                                               ivars->path, strerror(errno))));
+                ErrMsg_set_with_errno("lseek64 on %o failed", path);
                 CFISH_DECREF(self);
                 return NULL;
             }
@@ -128,8 +126,7 @@ FSFH_do_open(FSFileHandle *self, String *path, uint32_t flags) {
                 int64_t check_val
                     = chy_lseek64(ivars->fd, INT64_C(0), SEEK_SET);
                 if (check_val == -1) {
-                    Err_set_error(Err_new(Str_newf("lseek64 on %o failed: %s",
-                                                   ivars->path, strerror(errno))));
+                    ErrMsg_set_with_errno("lseek64 on %o failed", path);
                     CFISH_DECREF(self);
                     return NULL;
                 }
@@ -155,8 +152,8 @@ FSFH_do_open(FSFileHandle *self, String *path, uint32_t flags) {
         }
     }
     else {
-        Err_set_error(Err_new(Str_newf("Must specify FH_READ_ONLY or FH_WRITE_ONLY to open '%o'",
-                                       path)));
+        ErrMsg_set("Must specify FH_READ_ONLY or FH_WRITE_ONLY to open '%o'",
+                   path);
         CFISH_DECREF(self);
         return NULL;
     }
@@ -177,8 +174,7 @@ FSFH_Close_IMP(FSFileHandle *self) {
     // Close system-specific handles.
     if (ivars->fd) {
         if (close(ivars->fd)) {
-            Err_set_error(Err_new(Str_newf("Failed to close file: %s",
-                                           strerror(errno))));
+            ErrMsg_set_with_errno("Failed to close file");
             return false;
         }
         ivars->fd  = 0;
@@ -202,12 +198,12 @@ FSFH_Write_IMP(FSFileHandle *self, const void *data, size_t len) {
         ivars->len += check_val;
         if ((size_t)check_val != len) {
             if (check_val == -1) {
-                Err_set_error(Err_new(Str_newf("Error when writing %u64 bytes: %s",
-                                               (uint64_t)len, strerror(errno))));
+                ErrMsg_set_with_errno("Error when writing %u64 bytes",
+                                      (uint64_t)len);
             }
             else {
-                Err_set_error(Err_new(Str_newf("Attempted to write %u64 bytes, but wrote %i64",
-                                               (uint64_t)len, check_val)));
+                ErrMsg_set("Attempted to write %u64 bytes, but wrote %i64",
+                           (uint64_t)len, check_val);
             }
             return false;
         }
@@ -227,17 +223,17 @@ FSFH_Window_IMP(FSFileHandle *self, FileWindow *window, int64_t offset,
     FSFileHandleIVARS *const ivars = FSFH_IVARS(self);
     const int64_t end = offset + len;
     if (!(ivars->flags & FH_READ_ONLY)) {
-        Err_set_error(Err_new(Str_newf("Can't read from write-only handle")));
+        ErrMsg_set("Can't read from write-only handle");
         return false;
     }
     else if (offset < 0) {
-        Err_set_error(Err_new(Str_newf("Can't read from negative offset %i64",
-                                       offset)));
+        ErrMsg_set("Can't read from negative offset %i64", offset);
         return false;
     }
     else if (end > ivars->len) {
-        Err_set_error(Err_new(Str_newf("Tried to read past EOF: offset %i64 + request %i64 > len %i64",
-                                       offset, len, ivars->len)));
+        ErrMsg_set("Tried to read past EOF: "
+                   "offset %i64 + request %i64 > len %i64",
+                   offset, len, ivars->len);
         return false;
     }
     else {
@@ -278,17 +274,18 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) {
     const int64_t end = offset + (int64_t)len;
 
     if (ivars->flags & FH_WRITE_ONLY) {
-        Err_set_error(Err_new(Str_newf("Can't read from write-only filehandle")));
+        ErrMsg_set("Can't read from write-only filehandle");
         return false;
     }
     if (offset < 0 || end < offset) {
-        Err_set_error(Err_new(Str_newf("Invalid offset and len (%i64, %u64)",
-                                       offset, (uint64_t)len)));
+        ErrMsg_set("Invalid offset and len (%i64, %u64)",
+                   offset, (uint64_t)len);
         return false;
     }
     else if (end > ivars->len) {
-        Err_set_error(Err_new(Str_newf("Tried to read past EOF: offset %i64 + request %u64 > len %i64",
-                                       offset, (uint64_t)len, ivars->len)));
+        ErrMsg_set("Tried to read past EOF: "
+                   "offset %i64 + request %u64 > len %i64",
+                   offset, (uint64_t)len, ivars->len);
         return false;
     }
     memcpy(dest, ivars->buf + offset, len);
@@ -348,23 +345,20 @@ SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) {
     FREEMEM(path_ptr);
     if (ivars->fd == -1) {
         ivars->fd = 0;
-        Err_set_error(Err_new(Str_newf("Can't open '%o': %s", ivars->path,
-                                       strerror(errno))));
+        ErrMsg_set_with_errno("Can't open '%o'", ivars->path);
         return false;
     }
 
     // Derive len.
     ivars->len = chy_lseek64(ivars->fd, INT64_C(0), SEEK_END);
     if (ivars->len == -1) {
-        Err_set_error(Err_new(Str_newf("lseek64 on %o failed: %s", ivars->path,
-                                       strerror(errno))));
+        ErrMsg_set_with_errno("lseek64 on %o failed", ivars->path);
         return false;
     }
     else {
         int64_t check_val = chy_lseek64(ivars->fd, INT64_C(0), SEEK_SET);
         if (check_val == -1) {
-            Err_set_error(Err_new(Str_newf("lseek64 on %o failed: %s",
-                                           ivars->path, strerror(errno))));
+            ErrMsg_set_with_errno("lseek64 on %o failed", ivars->path);
             return false;
         }
     }
@@ -391,10 +385,9 @@ SI_map(FSFileHandle *self, FSFileHandleIVARS *ivars, int64_t offset,
         // Read-only memory mapping.
         buf = mmap(NULL, (size_t)len, PROT_READ, MAP_SHARED, ivars->fd, offset);
         if (buf == (void*)(-1)) {
-            Err_set_error(Err_new(Str_newf("mmap of offset %i64 and length %i64 (page size %i64) "
-                                           "against '%o' failed: %s",
-                                           offset, len, ivars->page_size,
-                                           ivars->path, strerror(errno))));
+            ErrMsg_set_with_errno("mmap of offset %i64 and length %i64 "
+                                  "(page size %i64) against '%o' failed",
+                                  offset, len, ivars->page_size, ivars->path);
             return NULL;
         }
     }
@@ -406,9 +399,8 @@ static CFISH_INLINE bool
 SI_unmap(FSFileHandle *self, char *buf, int64_t len) {
     if (buf != NULL) {
         if (munmap(buf, (size_t)len)) {
-            Err_set_error(Err_new(Str_newf("Failed to munmap '%o': %s",
-                                           FSFH_IVARS(self)->path,
-                                           strerror(errno))));
+            ErrMsg_set_with_errno("Failed to munmap '%o'",
+                                  FSFH_IVARS(self)->path);
             return false;
         }
     }
@@ -423,8 +415,7 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) {
 
     // Sanity check.
     if (offset < 0) {
-        Err_set_error(Err_new(Str_newf("Can't read from an offset less than 0 (%i64)",
-                                       offset)));
+        ErrMsg_set("Can't read from an offset less than 0 (%i64)", offset);
         return false;
     }
 
@@ -432,12 +423,12 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) {
     check_val = chy_pread64(ivars->fd, dest, len, offset);
     if (check_val != (int64_t)len) {
         if (check_val == -1) {
-            Err_set_error(Err_new(Str_newf("Tried to read %u64 bytes, got %i64: %s",
-                                           (uint64_t)len, check_val, strerror(errno))));
+            ErrMsg_set_with_errno("Tried to read %u64 bytes, got %i64",
+                                  (uint64_t)len, check_val);
         }
         else {
-            Err_set_error(Err_new(Str_newf("Tried to read %u64 bytes, got %i64",
-                                           (uint64_t)len, check_val)));
+            ErrMsg_set("Tried to read %u64 bytes, got %i64",
+                       (uint64_t)len, check_val);
         }
         return false;
     }
@@ -472,10 +463,7 @@ SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) {
                         );
     FREEMEM(filepath);
     if (ivars->win_fhandle == INVALID_HANDLE_VALUE) {
-        char *win_error = Err_win_error();
-        Err_set_error(Err_new(Str_newf("CreateFile for %o failed: %s",
-                                       ivars->path, win_error)));
-        FREEMEM(win_error);
+        ErrMsg_set_with_win_error("CreateFile for %o failed", ivars->path);
         return false;
     }
 
@@ -483,8 +471,7 @@ SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) {
     DWORD file_size_hi;
     DWORD file_size_lo = GetFileSize(ivars->win_fhandle, &file_size_hi);
     if (file_size_lo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
-        Err_set_error(Err_new(Str_newf("GetFileSize for %o failed",
-                                       ivars->path)));
+        ErrMsg_set_with_win_error("GetFileSize for %o failed", ivars->path);
         return false;
     }
     ivars->len = ((uint64_t)file_size_hi << 32) | file_size_lo;
@@ -495,10 +482,8 @@ SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) {
         ivars->win_maphandle = CreateFileMapping(ivars->win_fhandle, NULL,
                                                  PAGE_READONLY, 0, 0, NULL);
         if (ivars->win_maphandle == NULL) {
-            char *win_error = Err_win_error();
-            Err_set_error(Err_new(Str_newf("CreateFileMapping for %o failed: %s",
-                                           ivars->path, win_error)));
-            FREEMEM(win_error);
+            ErrMsg_set_with_win_error("CreateFileMapping for %o failed",
+                                      ivars->path);
             return false;
         }
     }
@@ -521,10 +506,8 @@ SI_map(FSFileHandle *self, FSFileHandleIVARS *ivars, int64_t offset,
         buf = MapViewOfFile(ivars->win_maphandle, FILE_MAP_READ,
                             file_offset_hi, file_offset_lo, amount);
         if (buf == NULL) {
-            char *win_error = Err_win_error();
-            Err_set_error(Err_new(Str_newf("MapViewOfFile for %o failed: %s",
-                                           ivars->path, win_error)));
-            FREEMEM(win_error);
+            ErrMsg_set_with_win_error("MapViewOfFile for %o failed",
+                                      ivars->path);
         }
     }
 
@@ -536,11 +519,8 @@ SI_unmap(FSFileHandle *self, char *buf, int64_t len) {
     UNUSED_VAR(self);
     if (buf != NULL) {
         if (!UnmapViewOfFile(buf)) {
-            char *win_error = Err_win_error();
-            Err_set_error(Err_new(Str_newf("Failed to unmap '%o': %s",
-                                           FSFH_IVARS(self)->path,
-                                           win_error)));
-            FREEMEM(win_error);
+            ErrMsg_set_with_win_error("Failed to unmap '%o'",
+                                      FSFH_IVARS(self)->path);
             return false;
         }
     }
@@ -553,20 +533,14 @@ SI_close_win_handles(FSFileHandle *self) {
     // Close both standard handle and mapping handle.
     if (ivars->win_maphandle) {
         if (!CloseHandle(ivars->win_maphandle)) {
-            char *win_error = Err_win_error();
-            Err_set_error(Err_new(Str_newf("Failed to close file mapping handle: %s",
-                                           win_error)));
-            FREEMEM(win_error);
+            ErrMsg_set_with_win_error("Failed to close file mapping handle");
             return false;
         }
         ivars->win_maphandle = NULL;
     }
     if (ivars->win_fhandle) {
         if (!CloseHandle(ivars->win_fhandle)) {
-            char *win_error = Err_win_error();
-            Err_set_error(Err_new(Str_newf("Failed to close file handle: %s",
-                                           win_error)));
-            FREEMEM(win_error);
+            ErrMsg_set_with_win_error("Failed to close file handle");
             return false;
         }
         ivars->win_fhandle = NULL;
@@ -590,16 +564,14 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) {
 
     // Sanity check.
     if (offset < 0) {
-        Err_set_error(Err_new(Str_newf("Can't read from an offset less than 0 (%i64)",
-                                       offset)));
+        ErrMsg_set("Can't read from an offset less than 0 (%i64)", offset);
         return false;
     }
 
     // ReadFile() takes a DWORD (unsigned 32-bit integer) as a length
     // argument, so throw a sensible error rather than wrap around.
     if (len > UINT32_MAX) {
-        Err_set_error(Err_new(Str_newf("Can't read more than 4 GB (%u64)",
-                                       (uint64_t)len)));
+        ErrMsg_set("Can't read more than 4 GB (%u64)", (uint64_t)len);
         return false;
     }
 
@@ -615,10 +587,7 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) {
 
     // Verify that the read has succeeded by now.
     if (!check_val) {
-        char *win_error = Err_win_error();
-        Err_set_error(Err_new(Str_newf("Failed to read %u64 bytes: %s",
-                                       (uint64_t)len, win_error)));
-        FREEMEM(win_error);
+        ErrMsg_set_with_win_error("Failed to read %u64 bytes", (uint64_t)len);
         return false;
     }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/FSFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/FSFolder.c b/core/Lucy/Store/FSFolder.c
index cedea94..d4d7f41 100644
--- a/core/Lucy/Store/FSFolder.c
+++ b/core/Lucy/Store/FSFolder.c
@@ -40,6 +40,7 @@
 #endif
 
 #include "Clownfish/CharBuf.h"
+#include "Lucy/Store/ErrorMessage.h"
 #include "Lucy/Store/FSFolder.h"
 #include "Lucy/Store/CompoundFileReader.h"
 #include "Lucy/Store/CompoundFileWriter.h"
@@ -182,8 +183,8 @@ FSFolder_Rename_IMP(FSFolder *self, String* from, String *to) {
     char *to_path   = S_fullpath_ptr(self, to);
     bool  retval    = !rename(from_path, to_path);
     if (!retval) {
-        Err_set_error(Err_new(Str_newf("rename from '%s' to '%s' failed: %s",
-                                       from_path, to_path, strerror(errno))));
+        ErrMsg_set_with_errno("rename from '%s' to '%s' failed",
+                              from_path, to_path);
     }
     FREEMEM(from_path);
     FREEMEM(to_path);
@@ -339,8 +340,7 @@ S_create_dir(String *path) {
     bool retval = true;
     char *path_ptr = Str_To_Utf8(path);
     if (-1 == chy_makedir(path_ptr, 0777)) {
-        Err_set_error(Err_new(Str_newf("Couldn't create directory '%o': %s",
-                                       path, strerror(errno))));
+        ErrMsg_set_with_errno("Couldn't create directory '%o'", path);
         retval = false;
     }
     FREEMEM(path_ptr);
@@ -398,10 +398,9 @@ S_hard_link(char *from8, char *to8) {
         return true;
     }
     else {
-        char *win_error = Err_win_error();
-        Err_set_error(Err_new(Str_newf("CreateHardLink for new file '%s' from '%s' failed: %s",
-                                       to8, from8, win_error)));
-        FREEMEM(win_error);
+        ErrMsg_set_with_win_error("CreateHardLink for new file '%s' "
+                                  "from '%s' failed",
+                                  to8, from8);
         return false;
     }
 }
@@ -435,8 +434,8 @@ S_absolutify(String *path) {
 static bool
 S_hard_link(char *from8, char *to8) {
     if (-1 == link(from8, to8)) {
-        Err_set_error(Err_new(Str_newf("hard link for new file '%s' from '%s' failed: %s",
-                                       to8, from8, strerror(errno))));
+        ErrMsg_set_with_errno("hard link for new file '%s' from '%s' failed",
+                              to8, from8);
         return false;
     }
     else {

http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/Lock.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/Lock.c b/core/Lucy/Store/Lock.c
index 9d86ae9..97592b0 100644
--- a/core/Lucy/Store/Lock.c
+++ b/core/Lucy/Store/Lock.c
@@ -18,7 +18,6 @@
 #define C_LUCY_LOCKFILELOCK
 #include "Lucy/Util/ToolSet.h"
 
-#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/87ea1b4d/core/Lucy/Store/LockFactory.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Store/LockFactory.c b/core/Lucy/Store/LockFactory.c
index eb50cea..d2042cd 100644
--- a/core/Lucy/Store/LockFactory.c
+++ b/core/Lucy/Store/LockFactory.c
@@ -17,7 +17,6 @@
 #define C_LUCY_LOCKFACTORY
 #include "Lucy/Util/ToolSet.h"
 
-#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>