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