1 /* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ 2 /* Changes: Removed mktemp */ 3 4 /* 5 * Copyright (c) 1987, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include "includes.h" 38 39 #ifndef HAVE_MKDTEMP 40 41 #if defined(LIBC_SCCS) && !defined(lint) 42 static char rcsid[] = "$OpenBSD: mktemp.c,v 1.16 2002/05/27 18:20:45 millert Exp $"; 43 #endif /* LIBC_SCCS and not lint */ 44 45 #ifdef HAVE_CYGWIN 46 #define open binary_open 47 extern int binary_open(); 48 #endif 49 50 static int _gettemp(char *, int *, int, int); 51 52 int 53 mkstemps(path, slen) 54 char *path; 55 int slen; 56 { 57 int fd; 58 59 return (_gettemp(path, &fd, 0, slen) ? fd : -1); 60 } 61 62 int 63 mkstemp(path) 64 char *path; 65 { 66 int fd; 67 68 return (_gettemp(path, &fd, 0, 0) ? fd : -1); 69 } 70 71 char * 72 mkdtemp(path) 73 char *path; 74 { 75 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); 76 } 77 78 static int 79 _gettemp(path, doopen, domkdir, slen) 80 char *path; 81 register int *doopen; 82 int domkdir; 83 int slen; 84 { 85 register char *start, *trv, *suffp; 86 struct stat sbuf; 87 int rval; 88 pid_t pid; 89 90 if (doopen && domkdir) { 91 errno = EINVAL; 92 return(0); 93 } 94 95 for (trv = path; *trv; ++trv) 96 ; 97 trv -= slen; 98 suffp = trv; 99 --trv; 100 if (trv < path) { 101 errno = EINVAL; 102 return (0); 103 } 104 pid = getpid(); 105 while (trv >= path && *trv == 'X' && pid != 0) { 106 *trv-- = (pid % 10) + '0'; 107 pid /= 10; 108 } 109 while (trv >= path && *trv == 'X') { 110 char c; 111 112 pid = (arc4random() & 0xffff) % (26+26); 113 if (pid < 26) 114 c = pid + 'A'; 115 else 116 c = (pid - 26) + 'a'; 117 *trv-- = c; 118 } 119 start = trv + 1; 120 121 /* 122 * check the target directory; if you have six X's and it 123 * doesn't exist this runs for a *very* long time. 124 */ 125 if (doopen || domkdir) { 126 for (;; --trv) { 127 if (trv <= path) 128 break; 129 if (*trv == '/') { 130 *trv = '\0'; 131 rval = stat(path, &sbuf); 132 *trv = '/'; 133 if (rval != 0) 134 return(0); 135 if (!S_ISDIR(sbuf.st_mode)) { 136 errno = ENOTDIR; 137 return(0); 138 } 139 break; 140 } 141 } 142 } 143 144 for (;;) { 145 if (doopen) { 146 if ((*doopen = 147 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 148 return(1); 149 if (errno != EEXIST) 150 return(0); 151 } else if (domkdir) { 152 if (mkdir(path, 0700) == 0) 153 return(1); 154 if (errno != EEXIST) 155 return(0); 156 } else if (lstat(path, &sbuf)) 157 return(errno == ENOENT ? 1 : 0); 158 159 /* tricky little algorithm for backward compatibility */ 160 for (trv = start;;) { 161 if (!*trv) 162 return (0); 163 if (*trv == 'Z') { 164 if (trv == suffp) 165 return (0); 166 *trv++ = 'a'; 167 } else { 168 if (isdigit(*trv)) 169 *trv = 'a'; 170 else if (*trv == 'z') /* inc from z to A */ 171 *trv = 'A'; 172 else { 173 if (trv == suffp) 174 return (0); 175 ++*trv; 176 } 177 break; 178 } 179 } 180 } 181 /*NOTREACHED*/ 182 } 183 184 #endif /* !HAVE_MKDTEMP */ 185 186 #pragma ident "%Z%%M% %I% %E% SMI"