/* * Copyright (C) 1999, 2000 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.10 2000/05/11 15:09:27 tale Exp $ */ /* Principal Authors: DCL */ #include #include #include #include #include #include #include #include "errno2result.h" #define ISC_DIR_MAGIC 0x4449522aU /* DIR*. */ #define VALID_DIR(dir) ISC_MAGIC_VALID(dir, 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(isc_dir_t *dir, const char *dirname) { isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_DIR(dir)); REQUIRE(dirname != NULL); /* * Open stream. */ dir->handle = opendir(dirname); if (dir->handle == NULL) return isc__errno2result(errno); 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. */ if (sizeof(dir->entry.name) <= strlen(entry->d_name)) return (ISC_R_UNEXPECTED); strcpy(dir->entry.name, entry->d_name); /* * Some dirents have d_namlen, but it is not portable. */ dir->entry.length = strlen(entry->d_name); return (ISC_R_SUCCESS); } /* * Close directory stream. */ void isc_dir_close(isc_dir_t *dir) { REQUIRE(VALID_DIR(dir) && dir->handle != NULL); (void)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); } /* * XXX Is there a better place for this? */ isc_result_t isc_dir_chdir(const char *dirname) { /* * Change the current directory to 'dirname'. */ REQUIRE(dirname != NULL); if (chdir(dirname) < 0) return (isc__errno2result(errno)); return (ISC_R_SUCCESS); }