diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in index b29a107a16..07c8394a03 100644 --- a/lib/isc/unix/Makefile.in +++ b/lib/isc/unix/Makefile.in @@ -25,13 +25,15 @@ CINCLUDES = -I${srcdir}/.. \ CDEFINES = CWARNINGS = +# Alphabetically OBJS = @ISC_IPV6_O@ \ - app.@O@ time.@O@ stdtime.@O@ socket.@O@ \ - interfaceiter.@O@ net.@O@ + app.@O@ dir.@O@ interfaceiter.@O@ net.@O@ socket.@O@ \ + stdtime.@O@ time.@O@ +# Alphabetically SRCS = @ISC_IPV6_C@ \ - app.c time.c stdtime.c socket.c \ - interfaceiter.c net.c + app.c dir.c interfaceiter.c net.c socket.c \ + stdtime.c time.c SUBDIRS = include TARGETS = ${OBJS} diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c new file mode 100644 index 0000000000..3c894e6545 --- /dev/null +++ b/lib/isc/unix/dir.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: dir.c,v 1.1 1999/09/23 17:31:58 tale Exp $ */ + +/* Principal Authors: DCL */ + +#include + +#include +#include + +#define ISC_DIR_MAGIC 0x4449522aU /* DIR*. */ +#define VALID_DIR(dir) ((dir) != NULL && \ + (dir)->magic == ISC_DIR_MAGIC) + +void +isc_dir_init(isc_dir_t *dir) { + REQUIRE(dir != NULL); + + dir->entry.name[0] = '\0'; + dir->entry.length = 0; + + dir->handle = NULL; + + dir->magic = ISC_DIR_MAGIC; +} + +/* + * Allocate workspace and open directory stream. If either one fails, + * NULL will be returned. + */ +isc_result_t +isc_dir_open(const char *dirname, isc_dir_t *dir) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(dirname != NULL); + REQUIRE(VALID_DIR(dir)); + + /* + * Open stream. + */ + dir->handle = opendir(dirname); + + if (dir->handle == NULL) { + if (errno == ENOMEM) + result = ISC_R_NOMEMORY; + else if (errno == EPERM) + result = ISC_R_NOPERM; + else if (errno == ENOENT) + result = ISC_R_NOTFOUND; + + } + + return (result); +} + +/* + * Return previously retrieved file or get next one. Unix's dirent has + * separate open and read functions, but the Win32 and DOS interfaces open + * the dir stream and reads the first file in one operation. + */ +isc_result_t +isc_dir_read(isc_dir_t *dir) { + struct dirent *entry; + + REQUIRE(VALID_DIR(dir) && dir->handle != NULL); + + /* + * Fetch next file in directory. + */ + entry = readdir(dir->handle); + + if (entry == NULL) + return (ISC_R_NOMORE); + + /* + * Make sure that the space for the name is long enough. + */ + INSIST(sizeof(dir->entry.name) > strlen(entry->d_name)); + + strcpy(dir->entry.name, entry->d_name); + dir->entry.length = entry->d_namlen; + + return (ISC_R_SUCCESS); +} + +/* + * Close directory stream. + */ +void +isc_dir_close(isc_dir_t *dir) { + REQUIRE(VALID_DIR(dir) && dir->handle != NULL); + + closedir(dir->handle); + dir->handle = NULL; +} + +/* + * Reposition directory stream at start. + */ +isc_result_t +isc_dir_reset(isc_dir_t *dir) { + REQUIRE(VALID_DIR(dir) && dir->handle != NULL); + + rewinddir(dir->handle); + + return (ISC_R_SUCCESS); +} diff --git a/lib/isc/unix/include/isc/dir.h b/lib/isc/unix/include/isc/dir.h new file mode 100644 index 0000000000..4017337c0a --- /dev/null +++ b/lib/isc/unix/include/isc/dir.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: dir.h,v 1.1 1999/09/23 17:31:59 tale Exp $ */ + +/* Principal Authors: DCL */ + +#ifndef DIRENT_H +#define DIRENT_H 1 + +#include +#include +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +typedef struct { + char name[NAME_MAX]; + unsigned int length; +} isc_direntry_t; + +typedef struct { + int magic; + char dirname[PATH_MAX]; + isc_direntry_t entry; + DIR * handle; +} isc_dir_t; + +void +isc_dir_init(isc_dir_t *dir); + +isc_result_t +isc_dir_open(const char *dirname, isc_dir_t *dir); + +isc_result_t +isc_dir_read(isc_dir_t *dir); + +isc_result_t +isc_dir_reset(isc_dir_t *dir); + +void +isc_dir_close(isc_dir_t *dir); + +ISC_LANG_BEGINDECLS + +#endif /* DIRENT_H */ diff --git a/lib/isc/win32/dir.c b/lib/isc/win32/dir.c new file mode 100644 index 0000000000..b720f093c9 --- /dev/null +++ b/lib/isc/win32/dir.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: dir.c,v 1.1 1999/09/23 17:31:59 tale Exp $ */ + +/* Principal Authors: DCL */ + +#include + +#include +#include + +#define ISC_DIR_MAGIC 0x4449522aU /* DIR*. */ +#define VALID_DIR(dir) ((dir) != NULL && \ + (dir)->magic == ISC_DIR_MAGIC) + +static isc_result_t +start_directory(isc_dir_t *p); + +void +isc_dir_init(isc_dir_t *dir) { + REQUIRE(dir != NULL); + + dir->dirname[0] = '\0'; + + dir->entry.name[0] = '\0'; + dir->entry.length = 0; + memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data)); + + dir->entry_filled = ISC_FALSE; + dir->search_handle = INVALID_HANDLE_VALUE; + + dir->magic = ISC_DIR_MAGIC; +} + +/* + * Allocate workspace and open directory stream. If either one fails, + * NULL will be returned. + */ +isc_result_t +isc_dir_open(const char *dirname, isc_dir_t *dir) { + char *p; + isc_result_t result; + + REQUIRE(dirname != NULL); + REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE); + + /* + * Copy directory name. Need to have enough space for the name, + * a possible path separator, the wildcard, and the final NUL. + */ + if (strlen(dirname) + 3 > sizeof(dir->dirname)) + /* XXXDCL ? */ + return (ISC_R_NOSPACE); + strcpy(dir->dirname, dirname); + + /* + * Append path separator, if needed, and "*". + */ + p = strchr(dir->dirname, '\0'); + if (dir->dirname < p && + *(p - 1) != '\\' && + *(p - 1) != '/' && + *(p - 1) != ':') + strcpy(p++, "\\"); + strcpy(p, "*"); + + /* + * Open stream. + */ + result = start_directory(dir); + + return (result); +} + +/* + * Return previously retrieved file or get next one. Unix's dirent has + * separate open and read functions, but the Win32 and DOS interfaces open + * the dir stream and reads the first file in one operation. + */ +isc_result_t +isc_dir_read(isc_dir_t *dir) { + REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE); + + if (dir->entry_filled) + /* + * start_directory() already filled in the first entry. + */ + dir->entry_filled = ISC_FALSE; + + else { + /* + * Fetch next file in directory. + */ + if (FindNextFile(dir->search_handle, + &dir->entry.find_data) == FALSE) + /* + * Either the last file has been processed or + * an error has occured. The former is not + * really an error, but the latter is. + */ + if (GetLastError() == ERROR_NO_MORE_FILES) + return (ISC_R_NOMORE); + else + return (ISC_R_UNEXPECTED); + } + + /* + * Make sure that the space for the name is long enough. + */ + strcpy(dir->entry.name, dir->entry.find_data.cFileName); + dir->entry.length = strlen(dir->entry.name); + + return (ISC_R_SUCCESS); +} + +/* + * Close directory stream. + */ +void +isc_dir_close(isc_dir_t *dir) { + REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE); + + FindClose(dir->search_handle); + dir->search_handle = INVALID_HANDLE_VALUE; +} + +/* + * Reposition directory stream at start. + */ +isc_result_t +isc_dir_reset(isc_dir_t *dir) { + isc_result_t result; + + REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE); + REQUIRE(dir->dirname != NULL); + + /* + * NT cannot reposition the seek pointer to the beginning of the + * the directory stream, but rather the directory needs to be + * closed and reopened. The latter might fail. + */ + + isc_dir_close(dir); + + result = start_directory(dir); + + return (result); +} + +/* + * Initialize isc_dir_t structure with new directory. The function + * returns 0 on failure and nonzero on success. + * + * Note: + * - Be sure to close previous stream before opening new one + */ +static isc_result_t +start_directory(isc_dir_t *dir) +{ + REQUIRE(VALID_DIR(dir)); + REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE); + + dir->entry_filled = ISC_FALSE; + + /* + * Open stream and retrieve first file. + */ + dir->search_handle = FindFirstFile(dir->dirname, + &dir->entry.find_data); + + if (dir->search_handle == INVALID_HANDLE_VALUE) { + /* + * Something went wrong but we don't know what. GetLastError() + * could give us more information about the error, but the + * MSDN documentation is frustratingly thin about what + * possible errors could have resulted. (Score one for + * the Unix manual pages.) So there is just this lame error + * instead of being able to differentiate ISC_R_NOTFOUND + * from ISC_R_UNEXPECTED. + */ + return (ISC_R_FAILURE); + } + + /* + * Make sure that the space for the name is long enough. + */ + INSIST(sizeof(dir->entry.name) > + strlen(dir->entry.find_data.cFileName)); + + /* + * Fill in the data for the first entry of the directory. + */ + strcpy(dir->entry.name, dir->entry.find_data.cFileName); + dir->entry.length = strlen(dir->entry.name); + + dir->entry_filled = ISC_TRUE; + + return (ISC_R_SUCCESS); +} diff --git a/lib/isc/win32/include/isc/dir.h b/lib/isc/win32/include/isc/dir.h new file mode 100644 index 0000000000..e99194c3e9 --- /dev/null +++ b/lib/isc/win32/include/isc/dir.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: dir.h,v 1.1 1999/09/23 17:31:59 tale Exp $ */ + +/* Principal Authors: DCL */ + +#ifndef DIRENT_H +#define DIRENT_H 1 + +#include + +#include +#include +#include + +ISC_LANG_BEGINDECLS + +typedef struct { + char name[MAX_PATH]; + unsigned int length; + WIN32_FIND_DATA find_data; +} isc_direntry_t; + +typedef struct { + int magic; + char dirname[MAX_PATH]; + isc_direntry_t entry; + isc_boolean_t entry_filled; + HANDLE search_handle; +} isc_dir_t; + +void +isc_dir_init(isc_dir_t *dir); + +isc_result_t +isc_dir_open(const char *dirname, isc_dir_t *dir); + +isc_result_t +isc_dir_read(isc_dir_t *dir); + +isc_result_t +isc_dir_reset(isc_dir_t *dir); + +void +isc_dir_close(isc_dir_t *dir); + +ISC_LANG_BEGINDECLS + +#endif /* DIRENT_H */ diff --git a/util/copyrights b/util/copyrights index e567fdfaed..4c633ecec1 100644 --- a/util/copyrights +++ b/util/copyrights @@ -527,6 +527,7 @@ ./lib/isc/unix/.cvsignore X 1999 ./lib/isc/unix/Makefile.in MAKE 1998,1999 ./lib/isc/unix/app.c C 1999 +./lib/isc/unix/dir.c C 1999 ./lib/isc/unix/ifiter_ioctl.c C 1999 ./lib/isc/unix/ifiter_sysctl.c C 1999 ./lib/isc/unix/include/.cvsignore X 1999 @@ -534,6 +535,7 @@ ./lib/isc/unix/include/isc/.cvsignore X 1999 ./lib/isc/unix/include/isc/Makefile.in MAKE 1998,1999 ./lib/isc/unix/include/isc/app.h C 1999 +./lib/isc/unix/include/isc/dir.h C 1999 ./lib/isc/unix/include/isc/ipv6.h C 1999 ./lib/isc/unix/include/isc/net.h.in C 1999 ./lib/isc/unix/include/isc/netdb.h C 1999 @@ -548,7 +550,9 @@ ./lib/isc/util.h C 1998,1999 ./lib/isc/version.c C 1998,1999 ./lib/isc/win32/condition.c C 1998,1999 +./lib/isc/win32/dir.c C 1999 ./lib/isc/win32/include/isc/condition.h C 1998,1999 +./lib/isc/win32/include/isc/dir.h C 1999 ./lib/isc/win32/include/isc/int.h C 1999 ./lib/isc/win32/include/isc/mutex.h C 1998,1999 ./lib/isc/win32/include/isc/thread.h C 1998,1999