and implement a custom glob() function on Windows systems.
AC_SUBST(DLZ_DRIVER_MYSQL_LIBS)
AC_SUBST_FILE(DLZ_DRIVER_RULES)
+AC_CHECK_HEADERS([glob.h])
+
if test "yes" = "$cross_compiling"; then
if test -z "$BUILD_CC"; then
AC_MSG_ERROR([BUILD_CC not set])
backtrace.@O@ base32.@O@ base64.@O@ \
bind9.@O@ buffer.@O@ bufferlist.@O@ \
commandline.@O@ counter.@O@ crc64.@O@ error.@O@ entropy.@O@ \
- event.@O@ hash.@O@ ht.@O@ heap.@O@ hex.@O@ hmac.@O@ \
+ event.@O@ glob.@O@ hash.@O@ ht.@O@ heap.@O@ hex.@O@ hmac.@O@ \
httpd.@O@ iterated_hash.@O@ \
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
md.@O@ mem.@O@ mutexblock.@O@ \
aes.c app.c assertions.c \
backtrace.c base32.c base64.c bind9.c \
buffer.c bufferlist.c commandline.c counter.c crc64.c \
- entropy.c error.c event.c hash.c ht.c heap.c hex.c hmac.c \
- httpd.c iterated_hash.c \
+ entropy.c error.c event.c glob.c hash.c ht.c heap.c hex.c \
+ hmac.c httpd.c iterated_hash.c \
lex.c lfsr.c lib.c log.c \
md.c mem.c mutexblock.c \
netaddr.c netscope.c nonce.c openssl_shim.c pool.c \
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <isc/errno.h>
+#include <isc/glob.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#if HAVE_GLOB_H
+#include <glob.h>
+#elif defined(_WIN32) || defined(_WIN64)
+#include <stdlib.h>
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#include <isc/list.h>
+#define GLOB_WIN_IMPL 1
+#define GLOB_ERR 0x0004 /* Return on error. */
+#define GLOB_NOSPACE (-1)
+#define GLOB_NOMATCH (-3)
+
+/* custom glob implementation for windows */
+static int
+glob(const char *pattern, int flags, void *unused, glob_t *pglob);
+
+static void
+globfree(glob_t *pglob);
+
+#else
+#error "Required header missing: glob.h"
+#endif
+
+isc_result_t
+isc_glob(const char *pattern, glob_t *pglob) {
+ REQUIRE(pattern != NULL);
+ REQUIRE(*pattern != '\0');
+ REQUIRE(pglob != NULL);
+
+ int rc = glob(pattern, GLOB_ERR, NULL, pglob);
+
+ switch (rc) {
+ case 0:
+ return (ISC_R_SUCCESS);
+ case GLOB_NOMATCH:
+ /* if a magic char (*?[]) was in pattern
+ * and no path matched we report error early,
+ * otherwise proceed as normal */
+ return (strpbrk(pattern, "[]*?")) ?
+ (ISC_R_FILENOTFOUND) : (ISC_R_SUCCESS);
+
+ case GLOB_NOSPACE:
+ return (ISC_R_NOMEMORY);
+ default:
+ return (errno != 0 ? isc_errno_toresult(errno) : ISC_R_IOERROR);
+ }
+
+}
+
+void
+isc_globfree(glob_t *pglob) {
+ REQUIRE(pglob != NULL);
+ globfree(pglob);
+}
+
+#ifdef GLOB_WIN_IMPL
+
+typedef struct file_path file_path_t;
+
+struct file_path {
+ char *path;
+ ISC_LINK(file_path_t) link;
+};
+
+typedef ISC_LIST(file_path_t) file_list_t;
+
+/* map a winapi error to a convenient errno code */
+static int
+map_error(DWORD win_err_code) {
+ switch (win_err_code) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ return (GLOB_NOMATCH);
+ case ERROR_ACCESS_DENIED:
+ return (EACCES);
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return (GLOB_NOSPACE);
+ default:
+ return (EIO);
+ }
+}
+
+/* add file in directory dir, that matches glob expression
+ * provided in function glob(), to the linked list fl */
+static int
+append_file(isc_mem_t *mctx,
+ file_list_t *fl,
+ const char *dir,
+ const char *file,
+ size_t full_path_len)
+{
+ file_path_t *fp = isc_mem_get(mctx, sizeof(file_path_t));
+ fp->path = isc_mem_get(mctx, full_path_len + 1);
+ _snprintf(fp->path, full_path_len + 1, "%s%s", dir, file);
+
+ ISC_LINK_INIT(fp, link);
+ ISC_LIST_PREPEND(*fl, fp, link);
+}
+
+/* sort files alphabetically case insensitive on windows */
+static int
+path_cmp(const void *path1, const void *path2) {
+ return _stricmp((const char *)path1, (const char *)path2);
+}
+
+static int
+glob(const char *pattern, int flags, void *unused, glob_t *pglob) {
+ char path[MAX_PATH];
+ WIN32_FIND_DATAA find_data;;
+ HANDLE hnd;
+
+ REQUIRE(pattern != NULL);
+ REQUIRE(pglob != NULL);
+
+ UNUSED(flags);
+ UNUSED(unused);
+
+ pglob->mctx = NULL;
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+
+ hnd = FindFirstFileA(pattern, &find_data);
+ if (hnd == INVALID_HANDLE_VALUE) {
+ return (map_error(GetLastError()));
+ }
+
+ path[MAX_PATH - 1] = 0;
+ strncpy(path, pattern, MAX_PATH);
+ if (path[MAX_PATH - 1] != 0) {
+ errno = ENAMETOOLONG;
+ goto fail;
+ }
+
+ // strip filename from path.
+ size_t dir_len = strlen(path);
+ while (dir_len > 0 && path[dir_len - 1] != '/' && path[dir_len - 1] != '\\') {
+ dir_len--;
+ }
+
+ path[dir_len] = '\0';
+
+ isc_mem_create(&pglob->mctx);
+ pglob->reserved = isc_mem_get(pglob->mctx, sizeof(file_list_t));
+
+ size_t entries = 0;
+
+ do {
+ size_t file_len = strlen(find_data.cFileName);
+ size_t full_path_len = dir_len + file_len;
+
+ if (full_path_len > MAX_PATH) {
+ errno = ENAMETOOLONG;
+ goto fail;
+ }
+
+ append_file(pglob->mctx,
+ (file_list_t *)pglob->reserved,
+ path,
+ find_data.cFileName,
+ full_path_len);
+
+ entries++;
+ } while (FindNextFileA(hnd, &find_data));
+
+ FindClose(hnd);
+
+ pglob->gl_pathv = isc_mem_get(pglob->mctx, (entries + 1) * sizeof(char*));
+ pglob->gl_pathv[entries] = NULL;
+ pglob->gl_pathc = entries;
+
+ file_list_t *fl = (file_list_t *)pglob->reserved;
+
+ size_t e = 0;
+ file_path_t *fp;
+ for (fp = ISC_LIST_HEAD(*fl); fp != NULL; fp = ISC_LIST_NEXT(fp, link)) {
+ pglob->gl_pathv[e++] = fp->path;
+ }
+
+ qsort(pglob->gl_pathv, pglob->gl_pathc, sizeof(char*), path_cmp);
+
+ return (0);
+
+fail:
+ int ec = errno;
+
+ FindClose(hnd);
+
+ if (pglob->mctx) {
+ globfree(pglob);
+ }
+
+ return ec;
+}
+
+void
+globfree(glob_t* pglob) {
+{
+ REQUIRE(pglob != NULL);
+ REQUIRE(pglob->mctx != NULL);
+
+ /* first free memory used by char ** gl_pathv */
+ if (pglob->gl_pathv) {
+ isc_mem_put(pglob->mctx,
+ pglob->gl_pathv,
+ (pglob->gl_pathc + 1) * sizeof(char *));
+ pglob->gl_pathv = NULL;
+ }
+
+ file_list_t *fl = (file_list_t *)pglob->reserved;
+ file_path_t *p, *next;
+
+ /* next free each individual file path string + nodes in list */
+ for (p = ISC_LIST_HEAD(*fl); p != NULL; p = next) {
+ next = ISC_LIST_NEXT(p, link);
+ isc_mem_put(pglob->mctx, p->path, strlen(p->path) + 1);
+ isc_mem_put(pglob->mctx, p, sizeof(file_path_t));
+ }
+
+ /* free linked list of files */
+ isc_mem_put(pglob->mctx, pglob->reserved, sizeof(file_list_t));
+ pglob->reserved = NULL;
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+
+ isc_mem_destroy(&pglob->mctx);
+ pglob->mctx = NULL;
+}
+
+#endif /* GLOB_WIN_IMPL */
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_GLOB_H
+#define ISC_GLOB_H
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+#if HAVE_GLOB_H
+#include <glob.h>
+#else
+#include <stddef.h>
+#include <isc/mem.h>
+
+typedef struct {
+ size_t gl_pathc;
+ char **gl_pathv;
+ isc_mem_t *mctx;
+ void *reserved;
+} glob_t;
+
+#endif
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_glob(const char *pattern, glob_t *pglob);
+
+void
+isc_globfree(glob_t *pglob);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_GLOB_H */
isc_fsaccess_changeowner
isc_fsaccess_remove
isc_fsaccess_set
+isc_glob
+isc_globfree
isc_hash_function
isc_hash_get_initializer
isc_hash_set_initializer
<ClInclude Include="..\include\isc\file.h" />
<ClInclude Include="..\include\isc\formatcheck.h" />
<ClInclude Include="..\include\isc\fsaccess.h" />
+ <ClInclude Include="..\include\isc\glob.h" />
<ClInclude Include="..\include\isc\hash.h" />
<ClInclude Include="..\include\isc\heap.h" />
<ClInclude Include="..\include\isc\hex.h" />
<ClCompile Include="..\entropy.c" />
<ClCompile Include="..\error.c" />
<ClCompile Include="..\event.c" />
+ <ClCompile Include="..\glob.c" />
<ClCompile Include="..\hash.c" />
<ClCompile Include="..\heap.c" />
<ClCompile Include="..\hex.c" />
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <glob.h>
#include <isc/buffer.h>
#include <isc/dir.h>
#include <isc/errno.h>
#include <isc/formatcheck.h>
+#include <isc/glob.h>
#include <isc/lex.h>
#include <isc/log.h>
#include <isc/mem.h>
parser_complain(cfg_parser_t *pctx, bool is_warning,
unsigned int flags, const char *format, va_list args);
-static isc_result_t
-glob_include(const char * restrict pattern, glob_t * restrict pglob);
-
#if defined(HAVE_GEOIP2)
static isc_result_t
parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
/* Allow include to specify a pattern that follows
* the same rules as the shell e.g "/path/zone*.conf" */
glob_t glob_obj;
- CHECK(glob_include(includename->value.string.base, &glob_obj));
+ CHECK(isc_glob(includename->value.string.base, &glob_obj));
cfg_obj_destroy(pctx, &includename);
for (size_t i = 0; i < glob_obj.gl_pathc; ++i) {
CHECK(parser_openfile(pctx, glob_obj.gl_pathv[i]));
}
+ isc_globfree(&glob_obj);
+
goto redo;
}
return (result);
}
-
-
-static isc_result_t
-glob_include(const char * restrict pattern, glob_t * restrict pglob)
-{
- int rc = glob(pattern, GLOB_ERR, NULL, pglob);
-
- switch (rc) {
- case 0:
- return (ISC_R_SUCCESS);
- case GLOB_NOMATCH:
- /* if a magic char (*?[]) was in pattern
- * and no path matched we report error early,
- * otherwise proceed as normal */
- return (strpbrk(pattern, "[]*?")) ?
- (ISC_R_FILENOTFOUND) : (ISC_R_SUCCESS);
-
- case GLOB_NOSPACE:
- return (ISC_R_NOMEMORY);
- default:
- return (errno != 0 ? isc_errno_toresult(errno) : ISC_R_IOERROR);
- }
-
-}
./lib/isc/error.c C 1998,1999,2000,2001,2004,2005,2007,2015,2016,2018,2019
./lib/isc/event.c C 1998,1999,2000,2001,2004,2005,2007,2014,2016,2017,2018,2019
./lib/isc/fsaccess.c C 2000,2001,2004,2005,2007,2016,2017,2018,2019
+./lib/isc/glob.c C 2019
./lib/isc/hash.c C 2003,2004,2005,2006,2007,2009,2013,2014,2015,2016,2017,2018,2019
./lib/isc/heap.c C 1997,1998,1999,2000,2001,2004,2005,2006,2007,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
./lib/isc/hex.c C 2000,2001,2002,2003,2004,2005,2007,2008,2013,2014,2015,2016,2018,2019
./lib/isc/include/isc/formatcheck.h C 2000,2001,2004,2005,2006,2007,2016,2018,2019
./lib/isc/include/isc/fsaccess.h C 2000,2001,2004,2005,2006,2007,2009,2016,2018,2019
./lib/isc/include/isc/fuzz.h C 2017,2018,2019
+./lib/isc/include/isc/glob.h C 2019
./lib/isc/include/isc/hash.h C 2003,2004,2005,2006,2007,2009,2013,2014,2015,2016,2017,2018,2019
./lib/isc/include/isc/heap.h C 1997,1998,1999,2000,2001,2004,2005,2006,2007,2009,2012,2016,2018,2019
./lib/isc/include/isc/hex.h C 2000,2001,2004,2005,2006,2007,2008,2016,2018,2019