source: trunk/third/nautilus-cd-burner/mkdtemp.c @ 21039

Revision 21039, 4.9 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21038, which included commits to RCS files with non-trunk default branches.
Line 
1/* Copyright (C) 1999, 2001-2002 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 Library 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   Library General Public License for more details.
13
14   You should have received a copy of the GNU Library General Public
15   License along with the GNU C Library; see the file COPYING.LIB.  If not,
16   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17   Boston, MA 02111-1307, USA.  */
18
19/* Extracted from misc/mkdtemp.c and sysdeps/posix/tempname.c.  */
20
21#ifdef HAVE_CONFIG_H
22# include "config.h"
23#endif
24
25/* Specification.  */
26#include "mkdtemp.h"
27
28#include <errno.h>
29#ifndef __set_errno
30# define __set_errno(Val) errno = (Val)
31#endif
32
33#include <stddef.h>
34#include <stdlib.h>
35#include <string.h>
36
37#include <stdio.h>
38#ifndef TMP_MAX
39# define TMP_MAX 238328
40#endif
41
42#if HAVE_STDINT_H_WITH_UINTMAX || _LIBC
43# include <stdint.h>
44#endif
45
46#if HAVE_INTTYPES_H_WITH_UINTMAX || _LIBC
47# include <inttypes.h>
48#endif
49
50#if HAVE_UNISTD_H || _LIBC
51# include <unistd.h>
52#endif
53
54#if HAVE_GETTIMEOFDAY || _LIBC
55# if HAVE_SYS_TIME_H || _LIBC
56#  include <sys/time.h>
57# endif
58#else
59# if HAVE_TIME_H || _LIBC
60#  include <time.h>
61# endif
62#endif
63
64#include <sys/stat.h>
65#if STAT_MACROS_BROKEN
66# undef S_ISDIR
67#endif
68#if !defined S_ISDIR && defined S_IFDIR
69# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
70#endif
71#if !S_IRUSR && S_IREAD
72# define S_IRUSR S_IREAD
73#endif
74#if !S_IRUSR
75# define S_IRUSR 00400
76#endif
77#if !S_IWUSR && S_IWRITE
78# define S_IWUSR S_IWRITE
79#endif
80#if !S_IWUSR
81# define S_IWUSR 00200
82#endif
83#if !S_IXUSR && S_IEXEC
84# define S_IXUSR S_IEXEC
85#endif
86#if !S_IXUSR
87# define S_IXUSR 00100
88#endif
89
90#if !_LIBC
91# define __getpid getpid
92# define __gettimeofday gettimeofday
93# define __mkdir mkdir
94#endif
95
96/* Use the widest available unsigned type if uint64_t is not
97   available.  The algorithm below extracts a number less than 62**6
98   (approximately 2**35.725) from uint64_t, so ancient hosts where
99   uintmax_t is only 32 bits lose about 3.725 bits of randomness,
100   which is better than not having mkstemp at all.  */
101#if !defined UINT64_MAX && !defined uint64_t
102# define uint64_t uintmax_t
103#endif
104
105/* These are the characters used in temporary filenames.  */
106static const char letters[] =
107"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
108
109/* Generate a temporary file name based on TMPL.  TMPL must match the
110   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
111   does not exist at the time of the call to __gen_tempname.  TMPL is
112   overwritten with the result.
113
114   KIND is:
115   __GT_DIR:            create a directory, which will be mode 0700.
116
117   We use a clever algorithm to get hard-to-predict names. */
118static int
119gen_tempname (tmpl)
120     char *tmpl;
121{
122  int len;
123  char *XXXXXX;
124  static uint64_t value;
125  uint64_t random_time_bits;
126  int count, fd = -1;
127  int save_errno = errno;
128
129  len = strlen (tmpl);
130  if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
131    {
132      __set_errno (EINVAL);
133      return -1;
134    }
135
136  /* This is where the Xs start.  */
137  XXXXXX = &tmpl[len - 6];
138
139  /* Get some more or less random data.  */
140#ifdef RANDOM_BITS
141  RANDOM_BITS (random_time_bits);
142#else
143# if HAVE_GETTIMEOFDAY || _LIBC
144  {
145    struct timeval tv;
146    __gettimeofday (&tv, NULL);
147    random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
148  }
149# else
150  random_time_bits = time (NULL);
151# endif
152#endif
153  value += random_time_bits ^ __getpid ();
154
155  for (count = 0; count < TMP_MAX; value += 7777, ++count)
156    {
157      uint64_t v = value;
158
159      /* Fill in the random bits.  */
160      XXXXXX[0] = letters[v % 62];
161      v /= 62;
162      XXXXXX[1] = letters[v % 62];
163      v /= 62;
164      XXXXXX[2] = letters[v % 62];
165      v /= 62;
166      XXXXXX[3] = letters[v % 62];
167      v /= 62;
168      XXXXXX[4] = letters[v % 62];
169      v /= 62;
170      XXXXXX[5] = letters[v % 62];
171
172      fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
173
174      if (fd >= 0)
175        {
176          __set_errno (save_errno);
177          return fd;
178        }
179      else if (errno != EEXIST)
180        return -1;
181    }
182
183  /* We got out of the loop because we ran out of combinations to try.  */
184  __set_errno (EEXIST);
185  return -1;
186}
187
188/* Generate a unique temporary directory from TEMPLATE.
189   The last six characters of TEMPLATE must be "XXXXXX";
190   they are replaced with a string that makes the filename unique.
191   The directory is created, mode 700, and its name is returned.
192   (This function comes from OpenBSD.) */
193char *
194mkdtemp (template)
195     char *template;
196{
197  if (gen_tempname (template))
198    return NULL;
199  else
200    return template;
201}
Note: See TracBrowser for help on using the repository browser.