1/* $NetBSD: mktemp.c,v 1.1.1.1 2009/04/12 15:33:26 christos Exp $ */ 2 3#if defined(LIBC_SCCS) && !defined(lint) 4static const char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; 5static const char rcsid[] = "Id: mktemp.c,v 1.2 2005/04/27 04:56:11 sra Exp"; 6#endif /* LIBC_SCCS and not lint */ 7 8/* 9 * Copyright (c) 1987, 1993 10 * The Regents of the University of California. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41/* 42 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 43 * 44 * Permission to use, copy, modify, and distribute this software for any 45 * purpose with or without fee is hereby granted, provided that the above 46 * copyright notice and this permission notice appear in all copies, and that 47 * the name of Digital Equipment Corporation not be used in advertising or 48 * publicity pertaining to distribution of the document or software without 49 * specific, written prior permission. 50 * 51 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 52 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 53 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 54 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 55 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 56 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 57 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 58 * SOFTWARE. 59 */ 60 61#include "port_before.h" 62 63#include <sys/types.h> 64#include <sys/stat.h> 65 66#include <ctype.h> 67#include <errno.h> 68#include <fcntl.h> 69#include <stdio.h> 70 71#include "port_after.h" 72 73#if (!defined(NEED_MKTEMP)) && (!defined(NEED_MKSTEMP)) 74int __mktemp_unneeded__; 75#else 76 77static int gettemp(char *path, int *doopen); 78 79#ifdef NEED_MKSTEMP 80mkstemp(char *path) { 81 int fd; 82 83 return (gettemp(path, &fd) ? fd : -1); 84} 85#endif 86 87#ifdef NEED_MKTEMP 88char * 89mktemp(char *path) { 90 return(gettemp(path, (int *)NULL) ? path : (char *)NULL); 91} 92#endif 93 94static int 95gettemp(char *path, int *doopen) { 96 char *start, *trv; 97 struct stat sbuf; 98 u_int pid; 99 100 pid = getpid(); 101 for (trv = path; *trv; ++trv); /*%< extra X's get set to 0's */ 102 while (*--trv == 'X') { 103 *trv = (pid % 10) + '0'; 104 pid /= 10; 105 } 106 107 /* 108 * check the target directory; if you have six X's and it 109 * doesn't exist this runs for a *very* long time. 110 */ 111 for (start = trv + 1;; --trv) { 112 if (trv <= path) 113 break; 114 if (*trv == '/') { 115 *trv = '\0'; 116 if (stat(path, &sbuf)) 117 return(0); 118 if (!S_ISDIR(sbuf.st_mode)) { 119 errno = ENOTDIR; 120 return(0); 121 } 122 *trv = '/'; 123 break; 124 } 125 } 126 127 for (;;) { 128 if (doopen) { 129 if ((*doopen = 130 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 131 return(1); 132 if (errno != EEXIST) 133 return(0); 134 } 135 else if (stat(path, &sbuf)) 136 return(errno == ENOENT ? 1 : 0); 137 138 /* tricky little algorithm for backward compatibility */ 139 for (trv = start;;) { 140 if (!*trv) 141 return(0); 142 if (*trv == 'z') 143 *trv++ = 'a'; 144 else { 145 if (isdigit(*trv)) 146 *trv = 'a'; 147 else 148 ++*trv; 149 break; 150 } 151 } 152 } 153 /*NOTREACHED*/ 154} 155 156#endif /*NEED_MKTEMP*/ 157 158/*! \file */ 159