Changed license terms to the plain LGPL thru-out.
[bpt/guile.git] / libguile / mkstemp.c
1 /* Copyright (C) 1991, 1992, 1996, 1998, 2001 Free Software Foundation, Inc.
2 This file is derived from mkstemps.c from the GNU Libiberty Library
3 which in turn is derived from the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21 #if HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include "libguile/__scm.h"
26
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #include <errno.h>
34 #include <stdio.h>
35 #include <fcntl.h>
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42 #ifdef __MINGW32__
43 #include <process.h>
44 #endif
45
46 #ifndef TMP_MAX
47 #define TMP_MAX 16384
48 #endif
49
50 /* Generate a unique temporary file name from TEMPLATE.
51
52 TEMPLATE has the form:
53
54 <path>/ccXXXXXX
55
56 The last six characters of TEMPLATE must be "XXXXXX"; they are
57 replaced with a string that makes the filename unique.
58
59 Returns a file descriptor open on the file for reading and writing. */
60 int
61 mkstemp (template)
62 char *template;
63 {
64 static const char letters[]
65 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
66 static scm_t_uint64 value;
67 #ifdef HAVE_GETTIMEOFDAY
68 struct timeval tv;
69 #endif
70 char *XXXXXX;
71 size_t len;
72 int count;
73
74 len = strlen (template);
75
76 if ((int) len < 6
77 || strncmp (&template[len - 6], "XXXXXX", 6))
78 {
79 return -1;
80 }
81
82 XXXXXX = &template[len - 6];
83
84 #ifdef HAVE_GETTIMEOFDAY
85 /* Get some more or less random data. */
86 gettimeofday (&tv, NULL);
87 value += ((scm_t_uint64) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
88 #else
89 value += getpid ();
90 #endif
91
92 for (count = 0; count < TMP_MAX; ++count)
93 {
94 scm_t_uint64 v = value;
95 int fd;
96
97 /* Fill in the random bits. */
98 XXXXXX[0] = letters[v % 62];
99 v /= 62;
100 XXXXXX[1] = letters[v % 62];
101 v /= 62;
102 XXXXXX[2] = letters[v % 62];
103 v /= 62;
104 XXXXXX[3] = letters[v % 62];
105 v /= 62;
106 XXXXXX[4] = letters[v % 62];
107 v /= 62;
108 XXXXXX[5] = letters[v % 62];
109
110 fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600);
111 if (fd >= 0)
112 /* The file does not exist. */
113 return fd;
114
115 /* This is a random value. It is only necessary that the next
116 TMP_MAX values generated by adding 7777 to VALUE are different
117 with (module 2^32). */
118 value += 7777;
119 }
120
121 /* We return the null string if we can't find a unique file name. */
122 template[0] = '\0';
123 return -1;
124 }