GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
tempname.c
Go to the documentation of this file.
1 /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8 
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13 
14 You should have received a copy of the GNU General Public
15 License along with the GNU C Library; see the file COPYING. If
16 not, write to the Free Software Foundation, Inc., 51 Franklin Street,
17 Fifth Floor, Boston, MA 02110-1301, USA. */
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 #ifndef HAVE_TEMPNAM
24 
25 #include <errno.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include <sys/types.h>
32 #include <unistd.h>
33 
34 #include <fcntl.h>
35 
36 #include "statdefs.h"
37 
38 #ifndef FILENAME_MAX
39 #ifdef MAXPATHLEN
40 #define FILENAME_MAX MAXPATHLEN
41 #else
42 #define FILENAME_MAX 1024
43 #endif
44 #endif
45 
46 #ifndef P_tmpdir
47 #define P_tmpdir "/usr/tmp/"
48 #endif
49 
50 /* Return nonzero if DIR is an existent directory. */
51 static int
52 diraccess (const char *dir)
53 {
54  struct stat buf;
55  return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);
56 }
57 
58 /* Return nonzero if FILE exists. */
59 static int
60 exists (const char *file)
61 {
62  /* We can stat the file even if we can't read its data. */
63  struct stat st;
64  int save = errno;
65  if (stat (file, &st) == 0)
66  return 1;
67  else
68  {
69  /* We report that the file exists if stat failed for a reason other
70  than nonexistence. In this case, it may or may not exist, and we
71  don't know; but reporting that it does exist will never cause any
72  trouble, while reporting that it doesn't exist when it does would
73  violate the interface of __stdio_gen_tempname. */
74  int exists = errno != ENOENT;
75  errno = save;
76  return exists;
77  }
78 }
79 
80 
81 /* These are the characters used in temporary filenames. */
82 static const char letters[] =
83  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
84 
85 /* Generate a temporary filename and return it (in a static buffer). If
86  STREAMPTR is not NULL, open a stream "w+b" on the file and set
87  *STREAMPTR to it. If DIR_SEARCH is nonzero, DIR and PFX are used as
88  described for tempnam. If not, a temporary filename in P_tmpdir with no
89  special prefix is generated. If LENPTR is not NULL, *LENPTR is set the
90  to length (including the terminating '\0') of the resultant filename,
91  which is returned. This goes through a cyclic pattern of all possible
92  filenames consisting of five decimal digits of the current pid and three
93  of the characters in `letters'. Data for tempnam and tmpnam is kept
94  separate, but when tempnam is using P_tmpdir and no prefix (i.e, it is
95  identical to tmpnam), the same data is used. Each potential filename is
96  tested for an already-existing file of the same name, and no name of an
97  existing file will be returned. When the cycle reaches its end
98  (12345ZZZ), NULL is returned. */
99 char *
100 __stdio_gen_tempname (const char *dir, const char *pfx,
101  int dir_search, size_t *lenptr,
102  FILE **streamptr)
103 {
104  int saverrno = errno;
105  static const char tmpdir[] = P_tmpdir;
106  static size_t indices[2];
107  size_t *idx;
108  static char buf[FILENAME_MAX];
109  static pid_t oldpid = (pid_t) 0;
110  pid_t pid = getpid ();
111  register size_t len, plen, dlen;
112 
113  if (dir_search)
114  {
115  register const char *d = getenv ("TMPDIR");
116  if (d != NULL && !diraccess (d))
117  d = NULL;
118  if (d == NULL && dir != NULL && diraccess (dir))
119  d = dir;
120  if (d == NULL && diraccess (tmpdir))
121  d = tmpdir;
122  if (d == NULL && diraccess ("/tmp"))
123  d = "/tmp";
124  if (d == NULL)
125  {
126  errno = ENOENT;
127  return NULL;
128  }
129  dir = d;
130  }
131  else
132  dir = tmpdir;
133 
134  dlen = strlen (dir);
135 
136  /* Remove trailing slashes from the directory name. */
137  while (dlen > 1 && dir[dlen - 1] == '/')
138  --dlen;
139 
140  if (pfx != NULL && *pfx != '\0')
141  {
142  plen = strlen (pfx);
143  if (plen > 5)
144  plen = 5;
145  }
146  else
147  plen = 0;
148 
149  if (dir != tmpdir && !strcmp (dir, tmpdir))
150  dir = tmpdir;
151  idx = &indices[(plen == 0 && dir == tmpdir) ? 1 : 0];
152 
153  if (pid != oldpid)
154  {
155  oldpid = pid;
156  indices[0] = indices[1] = 0;
157  }
158 
159  len = dlen + 1 + plen + 5 + 3;
160  for (; *idx < ((sizeof (letters) - 1) * (sizeof (letters) - 1) *
161  (sizeof (letters) - 1));
162  ++*idx)
163  {
164  /* Construct a file name and see if it already exists.
165 
166  We use a single counter in *IDX to cycle each of three
167  character positions through each of 62 possible letters. */
168 
169  if (sizeof (buf) < len)
170  return NULL;
171 
172  sprintf (buf, "%.*s/%.*s%.5d%c%c%c",
173  (int) dlen, dir, (int) plen,
174  pfx, pid % 100000,
175  letters[*idx
176  % (sizeof (letters) - 1)],
177  letters[(*idx / (sizeof (letters) - 1))
178  % (sizeof (letters) - 1)],
179  letters[(*idx / ((sizeof (letters) - 1) *
180  (sizeof (letters) - 1)))
181  % (sizeof (letters) - 1)]
182  );
183 
184  if (! buf || strlen (buf) != (int) len)
185  return NULL;
186 
187  if (streamptr != NULL)
188  abort ();
189  else if (exists (buf))
190  continue;
191 
192  /* If the file already existed we have continued the loop above,
193  so we only get here when we have a winning name to return. */
194 
195  errno = saverrno;
196 
197  if (lenptr != NULL)
198  *lenptr = len + 1;
199  return buf;
200  }
201 
202  /* We got out of the loop because we ran out of combinations to try. */
203  errno = EEXIST; /* ? */
204  return NULL;
205 }
206 
207 #endif