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