1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)mktemp.c 5.8 (Berkeley) 10/16/89"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/types.h> 23 #include <sys/file.h> 24 #include <sys/stat.h> 25 #include <errno.h> 26 #include <stdio.h> 27 #include <ctype.h> 28 29 mkstemp(path) 30 char *path; 31 { 32 int fd; 33 34 return (_gettemp(path, &fd) ? fd : -1); 35 } 36 37 char * 38 mktemp(path) 39 char *path; 40 { 41 return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); 42 } 43 44 static 45 _gettemp(path, doopen) 46 char *path; 47 register int *doopen; 48 { 49 extern int errno; 50 register char *start, *trv; 51 struct stat sbuf; 52 u_int pid; 53 54 pid = getpid(); 55 for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ 56 while (*--trv == 'X') { 57 *trv = (pid % 10) + '0'; 58 pid /= 10; 59 } 60 61 /* 62 * check the target directory; if you have six X's and it 63 * doesn't exist this runs for a *very* long time. 64 */ 65 for (start = trv + 1;; --trv) { 66 if (trv <= path) 67 break; 68 if (*trv == '/') { 69 *trv = '\0'; 70 if (stat(path, &sbuf)) 71 return(0); 72 if (!S_ISDIR(sbuf.st_mode)) { 73 errno = ENOTDIR; 74 return(0); 75 } 76 *trv = '/'; 77 break; 78 } 79 } 80 81 for (;;) { 82 if (doopen) { 83 if ((*doopen = 84 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 85 return(1); 86 if (errno != EEXIST) 87 return(0); 88 } 89 else if (stat(path, &sbuf)) 90 return(errno == ENOENT ? 1 : 0); 91 92 /* tricky little algorithm for backward compatibility */ 93 for (trv = start;;) { 94 if (!*trv) 95 return(0); 96 if (*trv == 'z') 97 *trv++ = 'a'; 98 else { 99 if (isdigit(*trv)) 100 *trv = 'a'; 101 else 102 ++*trv; 103 break; 104 } 105 } 106 } 107 /*NOTREACHED*/ 108 } 109