xref: /csrg-svn/lib/libc/stdio/mktemp.c (revision 61180)
130888Sbostic /*
2*61180Sbostic  * Copyright (c) 1987, 1993
3*61180Sbostic  *	The Regents of the University of California.  All rights reserved.
432701Sbostic  *
542625Sbostic  * %sccs.include.redist.c%
630888Sbostic  */
730888Sbostic 
826570Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*61180Sbostic static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 06/04/93";
1034436Sbostic #endif /* LIBC_SCCS and not lint */
1113260Sroot 
1230888Sbostic #include <sys/types.h>
1332155Sbostic #include <sys/stat.h>
1446611Sbostic #include <fcntl.h>
1532155Sbostic #include <errno.h>
1630888Sbostic #include <stdio.h>
1754995Sbostic #include <ctype.h>
1830888Sbostic 
1946611Sbostic static int _gettemp();
2046611Sbostic 
mkstemp(path)2139307Sbostic mkstemp(path)
2239307Sbostic 	char *path;
2330888Sbostic {
2439307Sbostic 	int fd;
2530888Sbostic 
2639307Sbostic 	return (_gettemp(path, &fd) ? fd : -1);
2730888Sbostic }
2830888Sbostic 
2913260Sroot char *
mktemp(path)3039307Sbostic mktemp(path)
3139307Sbostic 	char *path;
3213260Sroot {
3339307Sbostic 	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
3430888Sbostic }
3513260Sroot 
3630888Sbostic static
_gettemp(path,doopen)3739307Sbostic _gettemp(path, doopen)
3839307Sbostic 	char *path;
3939307Sbostic 	register int *doopen;
4030888Sbostic {
4139307Sbostic 	extern int errno;
4239307Sbostic 	register char *start, *trv;
4339307Sbostic 	struct stat sbuf;
4439307Sbostic 	u_int pid;
4530888Sbostic 
4613260Sroot 	pid = getpid();
4739307Sbostic 	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
4830888Sbostic 	while (*--trv == 'X') {
4930888Sbostic 		*trv = (pid % 10) + '0';
5013260Sroot 		pid /= 10;
5113260Sroot 	}
5230888Sbostic 
5330888Sbostic 	/*
5439307Sbostic 	 * check the target directory; if you have six X's and it
5539307Sbostic 	 * doesn't exist this runs for a *very* long time.
5630888Sbostic 	 */
5739307Sbostic 	for (start = trv + 1;; --trv) {
5839307Sbostic 		if (trv <= path)
5939307Sbostic 			break;
6039307Sbostic 		if (*trv == '/') {
6139307Sbostic 			*trv = '\0';
6239307Sbostic 			if (stat(path, &sbuf))
6339307Sbostic 				return(0);
6439307Sbostic 			if (!S_ISDIR(sbuf.st_mode)) {
6539307Sbostic 				errno = ENOTDIR;
6639307Sbostic 				return(0);
6739307Sbostic 			}
6839307Sbostic 			*trv = '/';
6939307Sbostic 			break;
7039307Sbostic 		}
7113260Sroot 	}
7230888Sbostic 
7330888Sbostic 	for (;;) {
7432155Sbostic 		if (doopen) {
7539307Sbostic 			if ((*doopen =
7639307Sbostic 			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
7739307Sbostic 				return(1);
7839307Sbostic 			if (errno != EEXIST)
7939307Sbostic 				return(0);
8032155Sbostic 		}
8139307Sbostic 		else if (stat(path, &sbuf))
8239307Sbostic 			return(errno == ENOENT ? 1 : 0);
8332155Sbostic 
8430888Sbostic 		/* tricky little algorithm for backward compatibility */
8530888Sbostic 		for (trv = start;;) {
8630888Sbostic 			if (!*trv)
8739307Sbostic 				return(0);
8830888Sbostic 			if (*trv == 'z')
8930888Sbostic 				*trv++ = 'a';
9030888Sbostic 			else {
9130888Sbostic 				if (isdigit(*trv))
9230888Sbostic 					*trv = 'a';
9330888Sbostic 				else
9430888Sbostic 					++*trv;
9530888Sbostic 				break;
9630888Sbostic 			}
9730888Sbostic 		}
9830888Sbostic 	}
9930888Sbostic 	/*NOTREACHED*/
10013260Sroot }
101