Annotation of embedaddon/ntp/lib/isc/unix/dir.c, revision 1.1.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>