~ubuntu-branches/ubuntu/utopic/gettext/utopic

« back to all changes in this revision

Viewing changes to gettext-tools/gnulib-lib/tempname.c

  • Committer: Colin Watson
  • Date: 2010-08-01 21:36:08 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: cjwatson@canonical.com-20100801213608-yy7vkm8lpatep3ci
merge from Debian 0.18.1.1-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* tempname.c - generate the name of a temporary file.
2
2
 
3
 
   Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4
 
   2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation,
5
 
   Inc.
 
3
   Copyright (C) 1991-2003, 2005-2007, 2009-2010 Free Software Foundation, Inc.
6
4
 
7
5
   This program is free software: you can redistribute it and/or modify
8
6
   it under the terms of the GNU General Public License as published by
40
38
# define TMP_MAX 238328
41
39
#endif
42
40
#ifndef __GT_FILE
43
 
# define __GT_FILE      0
44
 
# define __GT_BIGFILE   1
45
 
# define __GT_DIR       2
46
 
# define __GT_NOCREATE  3
 
41
# define __GT_FILE      0
 
42
# define __GT_DIR       1
 
43
# define __GT_NOCREATE  2
 
44
#endif
 
45
#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR       \
 
46
               || GT_NOCREATE != __GT_NOCREATE)
 
47
# error report this to bug-gnulib@gnu.org
47
48
#endif
48
49
 
49
50
#include <stddef.h>
59
60
 
60
61
#if _LIBC
61
62
# define struct_stat64 struct stat64
62
 
# define small_open __open
63
 
# define large_open __open64
64
63
#else
65
64
# define struct_stat64 struct stat
66
 
# define small_open open
67
 
# define large_open open
68
65
# define __gen_tempname gen_tempname
69
66
# define __getpid getpid
70
67
# define __gettimeofday gettimeofday
71
68
# define __mkdir mkdir
 
69
# define __open open
 
70
# define __open64 open
72
71
# define __lxstat64(version, file, buf) lstat (file, buf)
73
72
# define __xstat64(version, file, buf) stat (file, buf)
74
73
#endif
81
80
# include <hp-timing.h>
82
81
# if HP_TIMING_AVAIL
83
82
#  define RANDOM_BITS(Var) \
84
 
  if (__builtin_expect (value == UINT64_C (0), 0))                            \
85
 
    {                                                                         \
86
 
      /* If this is the first time this function is used initialize           \
87
 
         the variable we accumulate the value in to some somewhat             \
88
 
         random value.  If we'd not do this programs at startup time          \
89
 
         might have a reduced set of possible names, at least on slow         \
90
 
         machines.  */                                                        \
91
 
      struct timeval tv;                                                      \
92
 
      __gettimeofday (&tv, NULL);                                             \
93
 
      value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;                      \
94
 
    }                                                                         \
 
83
  if (__builtin_expect (value == UINT64_C (0), 0))                            \
 
84
    {                                                                         \
 
85
      /* If this is the first time this function is used initialize           \
 
86
         the variable we accumulate the value in to some somewhat             \
 
87
         random value.  If we'd not do this programs at startup time          \
 
88
         might have a reduced set of possible names, at least on slow         \
 
89
         machines.  */                                                        \
 
90
      struct timeval tv;                                                      \
 
91
      __gettimeofday (&tv, NULL);                                             \
 
92
      value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;                      \
 
93
    }                                                                         \
95
94
  HP_TIMING_NOW (Var)
96
95
# endif
97
96
#endif
122
121
   enough space in TMPL. */
123
122
int
124
123
__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
125
 
               int try_tmpdir)
 
124
               int try_tmpdir)
126
125
{
127
126
  const char *d;
128
127
  size_t dlen, plen;
136
135
    {
137
136
      plen = strlen (pfx);
138
137
      if (plen > 5)
139
 
        plen = 5;
 
138
        plen = 5;
140
139
    }
141
140
 
142
141
  if (try_tmpdir)
143
142
    {
144
143
      d = __secure_getenv ("TMPDIR");
145
144
      if (d != NULL && direxists (d))
146
 
        dir = d;
 
145
        dir = d;
147
146
      else if (dir != NULL && direxists (dir))
148
 
        /* nothing */ ;
 
147
        /* nothing */ ;
149
148
      else
150
 
        dir = NULL;
 
149
        dir = NULL;
151
150
    }
152
151
  if (dir == NULL)
153
152
    {
154
153
      if (direxists (P_tmpdir))
155
 
        dir = P_tmpdir;
 
154
        dir = P_tmpdir;
156
155
      else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
157
 
        dir = "/tmp";
 
156
        dir = "/tmp";
158
157
      else
159
 
        {
160
 
          __set_errno (ENOENT);
161
 
          return -1;
162
 
        }
 
158
        {
 
159
          __set_errno (ENOENT);
 
160
          return -1;
 
161
        }
163
162
    }
164
163
 
165
164
  dlen = strlen (dir);
166
165
  while (dlen > 1 && dir[dlen - 1] == '/')
167
 
    dlen--;                     /* remove trailing slashes */
 
166
    dlen--;                     /* remove trailing slashes */
168
167
 
169
168
  /* check we have room for "${dir}/${pfx}XXXXXX\0" */
170
169
  if (tmpl_len < dlen + 1 + plen + 6 + 1)
183
182
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
184
183
 
185
184
/* Generate a temporary file name based on TMPL.  TMPL must match the
186
 
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
187
 
   does not exist at the time of the call to __gen_tempname.  TMPL is
188
 
   overwritten with the result.
 
185
   rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix).
 
186
   The name constructed does not exist at the time of the call to
 
187
   __gen_tempname.  TMPL is overwritten with the result.
189
188
 
190
189
   KIND may be one of:
191
 
   __GT_NOCREATE:       simply verify that the name does not exist
192
 
                        at the time of the call.
193
 
   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
194
 
                        and return a read-write fd.  The file is mode 0600.
195
 
   __GT_BIGFILE:        same as __GT_FILE but use open64().
196
 
   __GT_DIR:            create a directory, which will be mode 0700.
 
190
   __GT_NOCREATE:       simply verify that the name does not exist
 
191
                        at the time of the call.
 
192
   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
 
193
                        and return a read-write fd.  The file is mode 0600.
 
194
   __GT_DIR:            create a directory, which will be mode 0700.
197
195
 
198
196
   We use a clever algorithm to get hard-to-predict names. */
199
197
int
200
 
__gen_tempname (char *tmpl, int kind)
 
198
__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
201
199
{
202
200
  int len;
203
201
  char *XXXXXX;
225
223
#endif
226
224
 
227
225
  len = strlen (tmpl);
228
 
  if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
 
226
  if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6))
229
227
    {
230
228
      __set_errno (EINVAL);
231
229
      return -1;
232
230
    }
233
231
 
234
232
  /* This is where the Xs start.  */
235
 
  XXXXXX = &tmpl[len - 6];
 
233
  XXXXXX = &tmpl[len - 6 - suffixlen];
236
234
 
237
235
  /* Get some more or less random data.  */
238
236
#ifdef RANDOM_BITS
264
262
      XXXXXX[5] = letters[v % 62];
265
263
 
266
264
      switch (kind)
267
 
        {
268
 
        case __GT_FILE:
269
 
          fd = small_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
270
 
          break;
271
 
 
272
 
        case __GT_BIGFILE:
273
 
          fd = large_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
274
 
          break;
275
 
 
276
 
        case __GT_DIR:
277
 
          fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
278
 
          break;
279
 
 
280
 
        case __GT_NOCREATE:
281
 
          /* This case is backward from the other three.  __gen_tempname
282
 
             succeeds if __xstat fails because the name does not exist.
283
 
             Note the continue to bypass the common logic at the bottom
284
 
             of the loop.  */
285
 
          if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
286
 
            {
287
 
              if (errno == ENOENT)
288
 
                {
289
 
                  __set_errno (save_errno);
290
 
                  return 0;
291
 
                }
292
 
              else
293
 
                /* Give up now. */
294
 
                return -1;
295
 
            }
296
 
          continue;
297
 
 
298
 
        default:
299
 
          assert (! "invalid KIND in __gen_tempname");
300
 
        }
 
265
        {
 
266
        case __GT_FILE:
 
267
          fd = __open (tmpl,
 
268
                       (flags & ~O_ACCMODE)
 
269
                       | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
 
270
          break;
 
271
 
 
272
        case __GT_DIR:
 
273
          fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
 
274
          break;
 
275
 
 
276
        case __GT_NOCREATE:
 
277
          /* This case is backward from the other three.  __gen_tempname
 
278
             succeeds if __xstat fails because the name does not exist.
 
279
             Note the continue to bypass the common logic at the bottom
 
280
             of the loop.  */
 
281
          if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
 
282
            {
 
283
              if (errno == ENOENT)
 
284
                {
 
285
                  __set_errno (save_errno);
 
286
                  return 0;
 
287
                }
 
288
              else
 
289
                /* Give up now. */
 
290
                return -1;
 
291
            }
 
292
          continue;
 
293
 
 
294
        default:
 
295
          assert (! "invalid KIND in __gen_tempname");
 
296
          abort ();
 
297
        }
301
298
 
302
299
      if (fd >= 0)
303
 
        {
304
 
          __set_errno (save_errno);
305
 
          return fd;
306
 
        }
 
300
        {
 
301
          __set_errno (save_errno);
 
302
          return fd;
 
303
        }
307
304
      else if (errno != EEXIST)
308
 
        return -1;
 
305
        return -1;
309
306
    }
310
307
 
311
308
  /* We got out of the loop because we ran out of combinations to try.  */