Annotation of embedaddon/ntp/lib/isc/unix/dir.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004, 2005, 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.25.332.3 2009/02/16 23:47:15 tbox Exp $ */
! 19:
! 20: /*! \file
! 21: * \author Principal Authors: DCL */
! 22:
! 23: #include <config.h>
! 24:
! 25: #include <sys/types.h>
! 26: #include <sys/stat.h>
! 27:
! 28: #include <ctype.h>
! 29: #include <errno.h>
! 30: #include <unistd.h>
! 31:
! 32: #include <isc/dir.h>
! 33: #include <isc/magic.h>
! 34: #include <isc/string.h>
! 35: #include <isc/util.h>
! 36:
! 37: #include "errno2result.h"
! 38:
! 39: #define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
! 40: #define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
! 41:
! 42: void
! 43: isc_dir_init(isc_dir_t *dir) {
! 44: REQUIRE(dir != NULL);
! 45:
! 46: dir->entry.name[0] = '\0';
! 47: dir->entry.length = 0;
! 48:
! 49: dir->handle = NULL;
! 50:
! 51: dir->magic = ISC_DIR_MAGIC;
! 52: }
! 53:
! 54: /*!
! 55: * \brief Allocate workspace and open directory stream. If either one fails,
! 56: * NULL will be returned.
! 57: */
! 58: isc_result_t
! 59: isc_dir_open(isc_dir_t *dir, const char *dirname) {
! 60: char *p;
! 61: isc_result_t result = ISC_R_SUCCESS;
! 62:
! 63: REQUIRE(VALID_DIR(dir));
! 64: REQUIRE(dirname != NULL);
! 65:
! 66: /*
! 67: * Copy directory name. Need to have enough space for the name,
! 68: * a possible path separator, the wildcard, and the final NUL.
! 69: */
! 70: if (strlen(dirname) + 3 > sizeof(dir->dirname))
! 71: /* XXXDCL ? */
! 72: return (ISC_R_NOSPACE);
! 73: strcpy(dir->dirname, dirname);
! 74:
! 75: /*
! 76: * Append path separator, if needed, and "*".
! 77: */
! 78: p = dir->dirname + strlen(dir->dirname);
! 79: if (dir->dirname < p && *(p - 1) != '/')
! 80: *p++ = '/';
! 81: *p++ = '*';
! 82: *p++ = '\0';
! 83:
! 84: /*
! 85: * Open stream.
! 86: */
! 87: dir->handle = opendir(dirname);
! 88:
! 89: if (dir->handle == NULL)
! 90: return isc__errno2result(errno);
! 91:
! 92: return (result);
! 93: }
! 94:
! 95: /*!
! 96: * \brief Return previously retrieved file or get next one.
! 97:
! 98: * Unix's dirent has
! 99: * separate open and read functions, but the Win32 and DOS interfaces open
! 100: * the dir stream and reads the first file in one operation.
! 101: */
! 102: isc_result_t
! 103: isc_dir_read(isc_dir_t *dir) {
! 104: struct dirent *entry;
! 105:
! 106: REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
! 107:
! 108: /*
! 109: * Fetch next file in directory.
! 110: */
! 111: entry = readdir(dir->handle);
! 112:
! 113: if (entry == NULL)
! 114: return (ISC_R_NOMORE);
! 115:
! 116: /*
! 117: * Make sure that the space for the name is long enough.
! 118: */
! 119: if (sizeof(dir->entry.name) <= strlen(entry->d_name))
! 120: return (ISC_R_UNEXPECTED);
! 121:
! 122: strcpy(dir->entry.name, entry->d_name);
! 123:
! 124: /*
! 125: * Some dirents have d_namlen, but it is not portable.
! 126: */
! 127: dir->entry.length = strlen(entry->d_name);
! 128:
! 129: return (ISC_R_SUCCESS);
! 130: }
! 131:
! 132: /*!
! 133: * \brief Close directory stream.
! 134: */
! 135: void
! 136: isc_dir_close(isc_dir_t *dir) {
! 137: REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
! 138:
! 139: (void)closedir(dir->handle);
! 140: dir->handle = NULL;
! 141: }
! 142:
! 143: /*!
! 144: * \brief Reposition directory stream at start.
! 145: */
! 146: isc_result_t
! 147: isc_dir_reset(isc_dir_t *dir) {
! 148: REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
! 149:
! 150: rewinddir(dir->handle);
! 151:
! 152: return (ISC_R_SUCCESS);
! 153: }
! 154:
! 155: isc_result_t
! 156: isc_dir_chdir(const char *dirname) {
! 157: /*!
! 158: * \brief Change the current directory to 'dirname'.
! 159: */
! 160:
! 161: REQUIRE(dirname != NULL);
! 162:
! 163: if (chdir(dirname) < 0)
! 164: return (isc__errno2result(errno));
! 165:
! 166: return (ISC_R_SUCCESS);
! 167: }
! 168:
! 169: isc_result_t
! 170: isc_dir_chroot(const char *dirname) {
! 171:
! 172: REQUIRE(dirname != NULL);
! 173:
! 174: #ifdef HAVE_CHROOT
! 175: if (chroot(dirname) < 0 || chdir("/") < 0)
! 176: return (isc__errno2result(errno));
! 177:
! 178: return (ISC_R_SUCCESS);
! 179: #else
! 180: return (ISC_R_NOTIMPLEMENTED);
! 181: #endif
! 182: }
! 183:
! 184: isc_result_t
! 185: isc_dir_createunique(char *templet) {
! 186: isc_result_t result;
! 187: char *x;
! 188: char *p;
! 189: int i;
! 190: int pid;
! 191:
! 192: REQUIRE(templet != NULL);
! 193:
! 194: /*!
! 195: * \brief mkdtemp is not portable, so this emulates it.
! 196: */
! 197:
! 198: pid = getpid();
! 199:
! 200: /*
! 201: * Replace trailing Xs with the process-id, zero-filled.
! 202: */
! 203: for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
! 204: x--, pid /= 10)
! 205: *x = pid % 10 + '0';
! 206:
! 207: x++; /* Set x to start of ex-Xs. */
! 208:
! 209: do {
! 210: i = mkdir(templet, 0700);
! 211: if (i == 0 || errno != EEXIST)
! 212: break;
! 213:
! 214: /*
! 215: * The BSD algorithm.
! 216: */
! 217: p = x;
! 218: while (*p != '\0') {
! 219: if (isdigit(*p & 0xff))
! 220: *p = 'a';
! 221: else if (*p != 'z')
! 222: ++*p;
! 223: else {
! 224: /*
! 225: * Reset character and move to next.
! 226: */
! 227: *p++ = 'a';
! 228: continue;
! 229: }
! 230:
! 231: break;
! 232: }
! 233:
! 234: if (*p == '\0') {
! 235: /*
! 236: * Tried all combinations. errno should already
! 237: * be EEXIST, but ensure it is anyway for
! 238: * isc__errno2result().
! 239: */
! 240: errno = EEXIST;
! 241: break;
! 242: }
! 243: } while (1);
! 244:
! 245: if (i == -1)
! 246: result = isc__errno2result(errno);
! 247: else
! 248: result = ISC_R_SUCCESS;
! 249:
! 250: return (result);
! 251: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>