File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / compat / mktemp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:23:02 2012 UTC (12 years, 4 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_5p1, v1_8_3p2, HEAD
sudo

    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>