Annotation of embedaddon/sudo/compat/mktemp.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2001, 2003, 2004, 2008-2011
        !             3:  *     Todd C. Miller <Todd.Miller@courtesan.com>
        !             4:  *
        !             5:  * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: #include <config.h>
        !            19: 
        !            20: #include <sys/types.h>
        !            21: #include <sys/time.h>
        !            22: #include <sys/stat.h>
        !            23: 
        !            24: #include <errno.h>
        !            25: #include <fcntl.h>
        !            26: #include <limits.h>
        !            27: #include <stdio.h>
        !            28: #ifdef HAVE_STDLIB_H
        !            29: # include <stdlib.h>
        !            30: #endif /* HAVE_STDLIB_H */
        !            31: #include <ctype.h>
        !            32: #ifdef HAVE_UNISTD_H
        !            33: # include <unistd.h>
        !            34: #endif /* HAVE_UNISTD_H */
        !            35: #if TIME_WITH_SYS_TIME
        !            36: # include <time.h>
        !            37: #endif
        !            38: 
        !            39: #include "missing.h"
        !            40: 
        !            41: #define MKTEMP_FILE    1
        !            42: #define MKTEMP_DIR     2
        !            43: 
        !            44: #define TEMPCHARS      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
        !            45: #define NUM_CHARS      (sizeof(TEMPCHARS) - 1)
        !            46: 
        !            47: #ifndef INT_MAX
        !            48: #define INT_MAX        0x7fffffff
        !            49: #endif
        !            50: 
        !            51: #ifdef HAVE_RANDOM
        !            52: # define RAND          random
        !            53: # define SRAND         srandom
        !            54: # define SEED_T                unsigned int
        !            55: #else
        !            56: # ifdef HAVE_LRAND48
        !            57: #  define RAND         lrand48
        !            58: #  define SRAND                srand48
        !            59: #  define SEED_T       long
        !            60: # else
        !            61: #  define RAND         rand
        !            62: #  define SRAND                srand
        !            63: #  define SEED_T       unsigned int
        !            64: # endif
        !            65: #endif
        !            66: 
        !            67: static void
        !            68: seed_random(void)
        !            69: {
        !            70:        SEED_T seed;
        !            71:        struct timeval tv;
        !            72: 
        !            73:        /*
        !            74:         * Seed from time of day and process id multiplied by small primes.
        !            75:         */
        !            76:        (void) gettimeofday(&tv, NULL);
        !            77:        seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 +
        !            78:            (getpid() % 1000) * 983;
        !            79:        SRAND(seed);
        !            80: }
        !            81: 
        !            82: static unsigned int
        !            83: get_random(void)
        !            84: {
        !            85:        static int initialized;
        !            86: 
        !            87:        if (!initialized) {
        !            88:                seed_random();
        !            89:                initialized = 1;
        !            90:        }
        !            91: 
        !            92:        return RAND() & 0xffffffff;
        !            93: }
        !            94: 
        !            95: static int
        !            96: mktemp_internal(char *path, int slen, int mode)
        !            97: {
        !            98:        char *start, *cp, *ep;
        !            99:        const char *tempchars = TEMPCHARS;
        !           100:        unsigned int r, tries;
        !           101:        int fd;
        !           102: 
        !           103:        for (ep = path; *ep; ep++)
        !           104:                ;
        !           105:        if (path + slen >= ep) {
        !           106:                errno = EINVAL;
        !           107:                return -1;
        !           108:        }
        !           109:        ep -= slen;
        !           110: 
        !           111:        tries = 1;
        !           112:        for (start = ep; start > path && start[-1] == 'X'; start--) {
        !           113:                if (tries < INT_MAX / NUM_CHARS)
        !           114:                        tries *= NUM_CHARS;
        !           115:        }
        !           116:        tries *= 2;
        !           117: 
        !           118:        do {
        !           119:                for (cp = start; *cp; cp++) {
        !           120:                        r = get_random() % NUM_CHARS;
        !           121:                        *cp = tempchars[r];
        !           122:                }
        !           123: 
        !           124:                switch (mode) {
        !           125:                case MKTEMP_FILE:
        !           126:                        fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
        !           127:                        if (fd != -1 || errno != EEXIST)
        !           128:                                return fd;
        !           129:                        break;
        !           130:                case MKTEMP_DIR:
        !           131:                        if (mkdir(path, S_IRWXU) == 0)
        !           132:                                return 0;
        !           133:                        if (errno != EEXIST)
        !           134:                                return -1;
        !           135:                        break;
        !           136:                }
        !           137:        } while (--tries);
        !           138: 
        !           139:        errno = EEXIST;
        !           140:        return -1;
        !           141: }
        !           142: 
        !           143: #ifndef HAVE_MKSTEMPS
        !           144: int
        !           145: mkstemps(char *path, int slen)
        !           146: {
        !           147:        return mktemp_internal(path, slen, MKTEMP_FILE);
        !           148: }
        !           149: #endif /* HAVE_MKSTEMPS */
        !           150: 
        !           151: #ifndef HAVE_MKDTEMP
        !           152: char *
        !           153: mkdtemp(char *path)
        !           154: {
        !           155:        if (mktemp_internal(path, 0, MKTEMP_DIR) == -1)
        !           156:                return NULL;
        !           157:        return path;
        !           158: }
        !           159: #endif /* HAVE_MKDTEMP */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>