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