1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)mktemp.c 5.10 (Berkeley) 02/24/91"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 #include <fcntl.h> 15 #include <errno.h> 16 #include <stdio.h> 17 18 static int _gettemp(); 19 20 mkstemp(path) 21 char *path; 22 { 23 int fd; 24 25 return (_gettemp(path, &fd) ? fd : -1); 26 } 27 28 char * 29 mktemp(path) 30 char *path; 31 { 32 return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); 33 } 34 35 static 36 _gettemp(path, doopen) 37 char *path; 38 register int *doopen; 39 { 40 extern int errno; 41 register char *start, *trv; 42 struct stat sbuf; 43 u_int pid; 44 45 pid = getpid(); 46 for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ 47 while (*--trv == 'X') { 48 *trv = (pid % 10) + '0'; 49 pid /= 10; 50 } 51 52 /* 53 * check the target directory; if you have six X's and it 54 * doesn't exist this runs for a *very* long time. 55 */ 56 for (start = trv + 1;; --trv) { 57 if (trv <= path) 58 break; 59 if (*trv == '/') { 60 *trv = '\0'; 61 if (stat(path, &sbuf)) 62 return(0); 63 if (!S_ISDIR(sbuf.st_mode)) { 64 errno = ENOTDIR; 65 return(0); 66 } 67 *trv = '/'; 68 break; 69 } 70 } 71 72 for (;;) { 73 if (doopen) { 74 if ((*doopen = 75 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 76 return(1); 77 if (errno != EEXIST) 78 return(0); 79 } 80 else if (stat(path, &sbuf)) 81 return(errno == ENOENT ? 1 : 0); 82 83 /* tricky little algorithm for backward compatibility */ 84 for (trv = start;;) { 85 if (!*trv) 86 return(0); 87 if (*trv == 'z') 88 *trv++ = 'a'; 89 else { 90 if (isdigit(*trv)) 91 *trv = 'a'; 92 else 93 ++*trv; 94 break; 95 } 96 } 97 } 98 /*NOTREACHED*/ 99 } 100