Annotation of embedaddon/ntp/lib/isc/win32/dir.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 1999-2001 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /* $Id: dir.c,v 1.16.22.2 2009/01/18 23:47:41 tbox Exp $ */
! 19:
! 20: /* Principal Authors: DCL */
! 21:
! 22: #include <config.h>
! 23:
! 24: #include <string.h>
! 25: #include <direct.h>
! 26: #include <process.h>
! 27: #include <io.h>
! 28:
! 29: #include <sys/stat.h>
! 30:
! 31: #include <isc/dir.h>
! 32: #include <isc/magic.h>
! 33: #include <isc/assertions.h>
! 34: #include <isc/util.h>
! 35:
! 36: #include "errno2result.h"
! 37:
! 38: #define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
! 39: #define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
! 40:
! 41: static isc_result_t
! 42: start_directory(isc_dir_t *p);
! 43:
! 44: void
! 45: isc_dir_init(isc_dir_t *dir) {
! 46: REQUIRE(dir != NULL);
! 47:
! 48: dir->dirname[0] = '\0';
! 49:
! 50: dir->entry.name[0] = '\0';
! 51: dir->entry.length = 0;
! 52: memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data));
! 53:
! 54: dir->entry_filled = ISC_FALSE;
! 55: dir->search_handle = INVALID_HANDLE_VALUE;
! 56:
! 57: dir->magic = ISC_DIR_MAGIC;
! 58: }
! 59:
! 60: /*
! 61: * Allocate workspace and open directory stream. If either one fails,
! 62: * NULL will be returned.
! 63: */
! 64: isc_result_t
! 65: isc_dir_open(isc_dir_t *dir, const char *dirname) {
! 66: char *p;
! 67: isc_result_t result;
! 68:
! 69: REQUIRE(dirname != NULL);
! 70: REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE);
! 71:
! 72: /*
! 73: * Copy directory name. Need to have enough space for the name,
! 74: * a possible path separator, the wildcard, and the final NUL.
! 75: */
! 76: if (strlen(dirname) + 3 > sizeof(dir->dirname))
! 77: /* XXXDCL ? */
! 78: return (ISC_R_NOSPACE);
! 79: strcpy(dir->dirname, dirname);
! 80:
! 81: /*
! 82: * Append path separator, if needed, and "*".
! 83: */
! 84: p = dir->dirname + strlen(dir->dirname);
! 85: if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':')
! 86: *p++ = '\\';
! 87: *p++ = '*';
! 88: *p++ = '\0';
! 89:
! 90: /*
! 91: * Open stream.
! 92: */
! 93: result = start_directory(dir);
! 94:
! 95: return (result);
! 96: }
! 97:
! 98: /*
! 99: * Return previously retrieved file or get next one. Unix's dirent has
! 100: * separate open and read functions, but the Win32 and DOS interfaces open
! 101: * the dir stream and reads the first file in one operation.
! 102: */
! 103: isc_result_t
! 104: isc_dir_read(isc_dir_t *dir) {
! 105: REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
! 106:
! 107: if (dir->entry_filled)
! 108: /*
! 109: * start_directory() already filled in the first entry.
! 110: */
! 111: dir->entry_filled = ISC_FALSE;
! 112:
! 113: else {
! 114: /*
! 115: * Fetch next file in directory.
! 116: */
! 117: if (FindNextFile(dir->search_handle,
! 118: &dir->entry.find_data) == FALSE)
! 119: /*
! 120: * Either the last file has been processed or
! 121: * an error has occurred. The former is not
! 122: * really an error, but the latter is.
! 123: */
! 124: if (GetLastError() == ERROR_NO_MORE_FILES)
! 125: return (ISC_R_NOMORE);
! 126: else
! 127: return (ISC_R_UNEXPECTED);
! 128: }
! 129:
! 130: /*
! 131: * Make sure that the space for the name is long enough.
! 132: */
! 133: strcpy(dir->entry.name, dir->entry.find_data.cFileName);
! 134: dir->entry.length = strlen(dir->entry.name);
! 135:
! 136: return (ISC_R_SUCCESS);
! 137: }
! 138:
! 139: /*
! 140: * Close directory stream.
! 141: */
! 142: void
! 143: isc_dir_close(isc_dir_t *dir) {
! 144: REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
! 145:
! 146: FindClose(dir->search_handle);
! 147: dir->search_handle = INVALID_HANDLE_VALUE;
! 148: }
! 149:
! 150: /*
! 151: * Reposition directory stream at start.
! 152: */
! 153: isc_result_t
! 154: isc_dir_reset(isc_dir_t *dir) {
! 155: isc_result_t result;
! 156:
! 157: REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
! 158: REQUIRE(dir->dirname != NULL);
! 159:
! 160: /*
! 161: * NT cannot reposition the seek pointer to the beginning of the
! 162: * the directory stream, but rather the directory needs to be
! 163: * closed and reopened. The latter might fail.
! 164: */
! 165:
! 166: isc_dir_close(dir);
! 167:
! 168: result = start_directory(dir);
! 169:
! 170: return (result);
! 171: }
! 172:
! 173: /*
! 174: * Initialize isc_dir_t structure with new directory. The function
! 175: * returns 0 on failure and nonzero on success.
! 176: *
! 177: * Note:
! 178: * - Be sure to close previous stream before opening new one
! 179: */
! 180: static isc_result_t
! 181: start_directory(isc_dir_t *dir)
! 182: {
! 183: REQUIRE(VALID_DIR(dir));
! 184: REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE);
! 185:
! 186: dir->entry_filled = ISC_FALSE;
! 187:
! 188: /*
! 189: * Open stream and retrieve first file.
! 190: */
! 191: dir->search_handle = FindFirstFile(dir->dirname,
! 192: &dir->entry.find_data);
! 193:
! 194: if (dir->search_handle == INVALID_HANDLE_VALUE) {
! 195: /*
! 196: * Something went wrong but we don't know what. GetLastError()
! 197: * could give us more information about the error, but the
! 198: * MSDN documentation is frustratingly thin about what
! 199: * possible errors could have resulted. (Score one for
! 200: * the Unix manual pages.) So there is just this lame error
! 201: * instead of being able to differentiate ISC_R_NOTFOUND
! 202: * from ISC_R_UNEXPECTED.
! 203: */
! 204: return (ISC_R_FAILURE);
! 205: }
! 206:
! 207: /*
! 208: * Make sure that the space for the name is long enough.
! 209: */
! 210: INSIST(sizeof(dir->entry.name) >
! 211: strlen(dir->entry.find_data.cFileName));
! 212:
! 213: /*
! 214: * Fill in the data for the first entry of the directory.
! 215: */
! 216: strcpy(dir->entry.name, dir->entry.find_data.cFileName);
! 217: dir->entry.length = strlen(dir->entry.name);
! 218:
! 219: dir->entry_filled = ISC_TRUE;
! 220:
! 221: return (ISC_R_SUCCESS);
! 222: }
! 223:
! 224: isc_result_t
! 225: isc_dir_chdir(const char *dirname) {
! 226: /*
! 227: * Change the current directory to 'dirname'.
! 228: */
! 229:
! 230: REQUIRE(dirname != NULL);
! 231:
! 232: if (chdir(dirname) < 0)
! 233: return (isc__errno2result(errno));
! 234:
! 235: return (ISC_R_SUCCESS);
! 236: }
! 237:
! 238: isc_result_t
! 239: isc_dir_chroot(const char *dirname) {
! 240: return (ISC_R_NOTIMPLEMENTED);
! 241: }
! 242:
! 243: isc_result_t
! 244: isc_dir_createunique(char *templet) {
! 245: isc_result_t result;
! 246: char *x;
! 247: char *p;
! 248: int i;
! 249: int pid;
! 250:
! 251: REQUIRE(templet != NULL);
! 252:
! 253: /*
! 254: * mkdtemp is not portable, so this emulates it.
! 255: */
! 256:
! 257: pid = getpid();
! 258:
! 259: /*
! 260: * Replace trailing Xs with the process-id, zero-filled.
! 261: */
! 262: for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
! 263: x--, pid /= 10)
! 264: *x = pid % 10 + '0';
! 265:
! 266: x++; /* Set x to start of ex-Xs. */
! 267:
! 268: do {
! 269: i = mkdir(templet);
! 270: i = chmod(templet, 0700);
! 271:
! 272: if (i == 0 || errno != EEXIST)
! 273: break;
! 274:
! 275: /*
! 276: * The BSD algorithm.
! 277: */
! 278: p = x;
! 279: while (*p != '\0') {
! 280: if (isdigit(*p & 0xff))
! 281: *p = 'a';
! 282: else if (*p != 'z')
! 283: ++*p;
! 284: else {
! 285: /*
! 286: * Reset character and move to next.
! 287: */
! 288: *p++ = 'a';
! 289: continue;
! 290: }
! 291:
! 292: break;
! 293: }
! 294:
! 295: if (*p == '\0') {
! 296: /*
! 297: * Tried all combinations. errno should already
! 298: * be EEXIST, but ensure it is anyway for
! 299: * isc__errno2result().
! 300: */
! 301: errno = EEXIST;
! 302: break;
! 303: }
! 304: } while (1);
! 305:
! 306: if (i == -1)
! 307: result = isc__errno2result(errno);
! 308: else
! 309: result = ISC_R_SUCCESS;
! 310:
! 311: return (result);
! 312: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>