OSDN Git Service

Initial revision
[pf3gnuchains/pf3gnuchains3x.git] / newlib / libc / stdio / tmpnam.c
1 /*
2  * tmpname.c
3  * Original Author:     G. Haley
4  */
5
6 /*
7 FUNCTION
8 <<tmpnam>>, <<tempnam>>---name for a temporary file
9
10 INDEX
11         tmpnam
12 INDEX
13         tempnam
14 INDEX
15         _tmpnam_r
16 INDEX
17         _tempnam_r
18
19 ANSI_SYNOPSIS
20         #include <stdio.h>
21         char *tmpnam(char *<[s]>);
22         char *tempnam(char *<[dir]>, char *<[pfx]>);
23         char *_tmpnam_r(void *<[reent]>, char *<[s]>);
24         char *_tempnam_r(void *<[reent]>, char *<[dir]>, char *<[pfx]>);
25
26 TRAD_SYNOPSIS
27         #include <stdio.h>
28         char *tmpnam(<[s]>)
29         char *<[s]>;
30
31         char *tempnam(<[dir]>, <[pfx]>)
32         char *<[dir]>;
33         char *<[pfx]>;
34
35         char *_tmpnam_r(<[reent]>, <[s]>)
36         char *<[reent]>;
37         char *<[s]>;
38
39         char *_tempnam_r(<[reent]>, <[dir]>, <[pfx]>)
40         char *<[reent]>;
41         char *<[dir]>;
42         char *<[pfx]>;
43
44 DESCRIPTION
45 Use either of these functions to generate a name for a temporary file.
46 The generated name is guaranteed to avoid collision with other files
47 (for up to <<TMP_MAX>> calls of either function).
48
49 <<tmpnam>> generates file names with the value of <<P_tmpdir>>
50 (defined in `<<stdio.h>>') as the leading directory component of the path.
51
52 You can use the <<tmpnam>> argument <[s]> to specify a suitable area
53 of memory for the generated filename; otherwise, you can call
54 <<tmpnam(NULL)>> to use an internal static buffer.
55
56 <<tempnam>> allows you more control over the generated filename: you
57 can use the argument <[dir]> to specify the path to a directory for
58 temporary files, and you can use the argument <[pfx]> to specify a
59 prefix for the base filename.
60
61 If <[dir]> is <<NULL>>, <<tempnam>> will attempt to use the value of
62 environment variable <<TMPDIR>> instead; if there is no such value,
63 <<tempnam>> uses the value of <<P_tmpdir>> (defined in `<<stdio.h>>').
64
65 If you don't need any particular prefix to the basename of temporary
66 files, you can pass <<NULL>> as the <[pfx]> argument to <<tempnam>>.
67
68 <<_tmpnam_r>> and <<_tempnam_r>> are reentrant versions of <<tmpnam>>
69 and <<tempnam>> respectively.  The extra argument <[reent]> is a
70 pointer to a reentrancy structure.
71
72 WARNINGS
73 The generated filenames are suitable for temporary files, but do not
74 in themselves make files temporary.  Files with these names must still
75 be explicitly removed when you no longer want them.
76
77 If you supply your own data area <[s]> for <<tmpnam>>, you must ensure
78 that it has room for at least <<L_tmpnam>> elements of type <<char>>.
79
80 RETURNS
81 Both <<tmpnam>> and <<tempnam>> return a pointer to the newly
82 generated filename.
83
84 PORTABILITY
85 ANSI C requires <<tmpnam>>, but does not specify the use of
86 <<P_tmpdir>>.  The System V Interface Definition (Issue 2) requires
87 both <<tmpnam>> and <<tempnam>>.
88
89 Supporting OS subroutines required: <<close>>,  <<fstat>>, <<getpid>>,
90 <<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>.
91
92 The global pointer <<environ>> is also required.
93 */
94
95 #include <_ansi.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include <string.h>
99 #include <fcntl.h>
100 #include <reent.h>
101 #include <errno.h>
102
103 /* Try to open the file specified, if it can't be opened then try
104    another one.  Return nonzero if successful, otherwise zero.  */
105
106 static int
107 worker (ptr, result, part1, part2, part3, part4)
108      struct _reent *ptr;
109      char *result;
110      _CONST char *part1;
111      _CONST char *part2;
112      int part3;
113      int *part4;
114 {
115   /*  Generate the filename and make sure that there isn't one called
116       it already.  */
117
118   while (1)
119     {
120       int t;
121       _sprintf_r (ptr, result, "%s/%s%x.%x", part1, part2, part3, *part4);
122       (*part4)++;
123       t = _open_r (ptr, result, O_RDONLY, 0);
124       if (t == -1)
125         {
126           if (ptr->_errno == ENOSYS)
127             {
128               result[0] = '\0';
129               return 0;
130             }
131           break;
132         }
133       _close_r (ptr, t);
134     }
135   return 1;
136 }
137
138 char *
139 _DEFUN (_tmpnam_r, (p, s),
140         struct _reent *p _AND
141         char *s)
142 {
143   char *result;
144   int pid;
145
146   if (s == NULL)
147     {
148       /* ANSI states we must use an internal static buffer if s is NULL */
149       result = p->_emergency;
150     }
151   else
152     {
153       result = s;
154     }
155   pid = _getpid_r (p);
156
157   if (worker (p, result, P_tmpdir, "t", pid, &p->_inc))
158     {
159       p->_inc++;
160       return result;
161     }
162
163   return NULL;
164 }
165
166 char *
167 _DEFUN (_tempnam_r, (p, dir, pfx),
168         struct _reent *p _AND
169         _CONST char *dir _AND
170         _CONST char *pfx)
171 {
172   char *filename;
173   int length;
174   _CONST char *prefix = (pfx) ? pfx : "";
175   if (dir == NULL && (dir = getenv ("TMPDIR")) == NULL)
176     dir = P_tmpdir;
177
178   /* two 8 digit numbers + . / */
179   length = strlen (dir) + strlen (prefix) + (4 * sizeof (int)) + 2 + 1;
180
181   filename = _malloc_r (p, length);
182   if (filename)
183     {
184       if (! worker (p, filename, dir, prefix,
185                     _getpid_r (p) ^ (int) (_POINTER_INT) p, &p->_inc))
186         return NULL;
187     }
188   return filename;
189 }
190
191 #ifndef _REENT_ONLY
192
193 char *
194 _DEFUN (tempnam, (dir, pfx),
195         _CONST char *dir _AND
196         _CONST char *pfx)
197 {
198   return _tempnam_r (_REENT, dir, pfx);
199 }
200
201 char *
202 _DEFUN (tmpnam, (s),
203         char *s)
204 {
205   return _tmpnam_r (_REENT, s);
206 }
207
208 #endif