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>