File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / compat / mktemp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 10:46:11 2013 UTC (10 years, 11 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_8p0, v1_8_8, v1_8_7p0, v1_8_7, HEAD
1.8.7

    1: /*
    2:  * Copyright (c) 2001, 2003, 2004, 2008-2011, 2013
    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: #if !defined(HAVE_MKSTEMPS) || !defined(HAVE_MKDTEMP)
   21: 
   22: #include <sys/types.h>
   23: #include <sys/time.h>
   24: #include <sys/stat.h>
   25: 
   26: #include <errno.h>
   27: #include <fcntl.h>
   28: #include <limits.h>
   29: #include <stdio.h>
   30: #ifdef HAVE_STDLIB_H
   31: # include <stdlib.h>
   32: #endif /* HAVE_STDLIB_H */
   33: #include <ctype.h>
   34: #ifdef HAVE_UNISTD_H
   35: # include <unistd.h>
   36: #endif /* HAVE_UNISTD_H */
   37: #if TIME_WITH_SYS_TIME
   38: # include <time.h>
   39: #endif
   40: 
   41: #include "missing.h"
   42: 
   43: #define MKTEMP_FILE	1
   44: #define MKTEMP_DIR	2
   45: 
   46: #define TEMPCHARS	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
   47: #define NUM_CHARS	(sizeof(TEMPCHARS) - 1)
   48: 
   49: #ifndef INT_MAX
   50: #define INT_MAX	0x7fffffff
   51: #endif
   52: 
   53: #ifdef HAVE_RANDOM
   54: # define RAND		random
   55: # define SRAND		srandom
   56: # define SEED_T		unsigned int
   57: #else
   58: # ifdef HAVE_LRAND48
   59: #  define RAND		lrand48
   60: #  define SRAND		srand48
   61: #  define SEED_T	long
   62: # else
   63: #  define RAND		rand
   64: #  define SRAND		srand
   65: #  define SEED_T	unsigned int
   66: # endif
   67: #endif
   68: 
   69: static void
   70: seed_random(void)
   71: {
   72: 	SEED_T seed;
   73: 	struct timeval tv;
   74: 
   75: 	/*
   76: 	 * Seed from time of day and process id multiplied by small primes.
   77: 	 */
   78: 	(void) gettimeofday(&tv, NULL);
   79: 	seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 +
   80: 	    (getpid() % 1000) * 983;
   81: 	SRAND(seed);
   82: }
   83: 
   84: static unsigned int
   85: get_random(void)
   86: {
   87: 	static int initialized;
   88: 
   89: 	if (!initialized) {
   90: 		seed_random();
   91: 		initialized = 1;
   92: 	}
   93: 
   94: 	return RAND() & 0xffffffff;
   95: }
   96: 
   97: static int
   98: mktemp_internal(char *path, int slen, int mode)
   99: {
  100: 	char *start, *cp, *ep;
  101: 	const char *tempchars = TEMPCHARS;
  102: 	unsigned int r, tries;
  103: 	int fd;
  104: 
  105: 	for (ep = path; *ep; ep++)
  106: 		;
  107: 	if (path + slen >= ep) {
  108: 		errno = EINVAL;
  109: 		return -1;
  110: 	}
  111: 	ep -= slen;
  112: 
  113: 	tries = 1;
  114: 	for (start = ep; start > path && start[-1] == 'X'; start--) {
  115: 		if (tries < INT_MAX / NUM_CHARS)
  116: 			tries *= NUM_CHARS;
  117: 	}
  118: 	tries *= 2;
  119: 
  120: 	do {
  121: 		for (cp = start; *cp; cp++) {
  122: 			r = get_random() % NUM_CHARS;
  123: 			*cp = tempchars[r];
  124: 		}
  125: 
  126: 		switch (mode) {
  127: 		case MKTEMP_FILE:
  128: 			fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
  129: 			if (fd != -1 || errno != EEXIST)
  130: 				return fd;
  131: 			break;
  132: 		case MKTEMP_DIR:
  133: 			if (mkdir(path, S_IRWXU) == 0)
  134: 				return 0;
  135: 			if (errno != EEXIST)
  136: 				return -1;
  137: 			break;
  138: 		}
  139: 	} while (--tries);
  140: 
  141: 	errno = EEXIST;
  142: 	return -1;
  143: }
  144: 
  145: #ifndef HAVE_MKSTEMPS
  146: int
  147: mkstemps(char *path, int slen)
  148: {
  149: 	return mktemp_internal(path, slen, MKTEMP_FILE);
  150: }
  151: #endif /* HAVE_MKSTEMPS */
  152: 
  153: #ifndef HAVE_MKDTEMP
  154: char *
  155: mkdtemp(char *path)
  156: {
  157: 	if (mktemp_internal(path, 0, MKTEMP_DIR) == -1)
  158: 		return NULL;
  159: 	return path;
  160: }
  161: #endif /* HAVE_MKDTEMP */
  162: #endif /* !HAVE_MKSTEMPS || !HAVE_MKDTEMP */

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