OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [misc/] [internals/] [tempname.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* Copyright (C) 1991,92,93,94,95,96,97,98,99 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
/* March 11, 2002       Manuel Novoa III
20
 *
21
 * Modify code to remove dependency on libgcc long long arith support funcs.
22
 */
23
 
24
#include <stddef.h>
25
#include <stdint.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <errno.h>
30
#include <fcntl.h>
31
#include <unistd.h>
32
#include <assert.h>
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <sys/time.h>
36
#include "tempname.h"
37
 
38
 
39
/* Return nonzero if DIR is an existent directory.  */
40
static int direxists (const char *dir)
41
{
42
    struct stat buf;
43
    return stat(dir, &buf) == 0 && S_ISDIR (buf.st_mode);
44
}
45
 
46
/* Path search algorithm, for tmpnam, tmpfile, etc.  If DIR is
47
   non-null and exists, uses it; otherwise uses the first of $TMPDIR,
48
   P_tmpdir, /tmp that exists.  Copies into TMPL a template suitable
49
   for use with mk[s]temp.  Will fail (-1) if DIR is non-null and
50
   doesn't exist, none of the searched dirs exists, or there's not
51
   enough space in TMPL. */
52
int __path_search (char *tmpl, size_t tmpl_len, const char *dir,
53
        const char *pfx, int try_tmpdir)
54
{
55
    //const char *d;
56
    size_t dlen, plen;
57
 
58
    if (!pfx || !pfx[0])
59
    {
60
        pfx = "file";
61
        plen = 4;
62
    }
63
    else
64
    {
65
        plen = strlen (pfx);
66
        if (plen > 5)
67
            plen = 5;
68
    }
69
 
70
#if 0
71
    if (try_tmpdir)
72
    {
73
        d = __secure_getenv ("TMPDIR");
74
        if (d != NULL && direxists (d))
75
            dir = d;
76
        else if (dir != NULL && direxists (dir))
77
            /* nothing */ ;
78
        else
79
            dir = NULL;
80
    }
81
#endif  
82
    if (dir == NULL)
83
    {
84
        if (direxists (P_tmpdir))
85
            dir = P_tmpdir;
86
        else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
87
            dir = "/tmp";
88
        else
89
        {
90
            __set_errno (ENOENT);
91
            return -1;
92
        }
93
    }
94
 
95
    dlen = strlen (dir);
96
    while (dlen > 1 && dir[dlen - 1] == '/')
97
        dlen--;                 /* remove trailing slashes */
98
 
99
    /* check we have room for "${dir}/${pfx}XXXXXX\0" */
100
    if (tmpl_len < dlen + 1 + plen + 6 + 1)
101
    {
102
        __set_errno (EINVAL);
103
        return -1;
104
    }
105
 
106
    sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx);
107
    return 0;
108
}
109
 
110
/* These are the characters used in temporary filenames.  */
111
static const char letters[] =
112
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
113
 
114
/* Generate a temporary file name based on TMPL.  TMPL must match the
115
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
116
   does not exist at the time of the call to __gen_tempname.  TMPL is
117
   overwritten with the result.
118
 
119
   KIND may be one of:
120
   __GT_NOCREATE:       simply verify that the name does not exist
121
                        at the time of the call.
122
   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
123
                        and return a read-write fd.  The file is mode 0600.
124
   __GT_BIGFILE:        same as __GT_FILE but use open64().
125
   __GT_DIR:            create a directory, which will be mode 0700.
126
 
127
   We use a clever algorithm to get hard-to-predict names. */
128
int __gen_tempname (char *tmpl, int kind)
129
{
130
    char *XXXXXX;
131
    struct timeval tv;
132
    uint32_t high, low, rh;
133
    unsigned int k;
134
    int len, i, count, fd, save_errno = errno;
135
    static uint64_t value; /* Do not initialize this,
136
                              or lock it for multi-threaded
137
                              apps -- the messier the better */
138
 
139
    len = strlen (tmpl);
140
    if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
141
    {
142
        __set_errno (EINVAL);
143
        return -1;
144
    }
145
 
146
    /* This is where the Xs start.  */
147
    XXXXXX = &tmpl[len - 6];
148
 
149
    /* Get some more or less random data.  */
150
    gettimeofday (&tv, NULL);
151
    value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
152
 
153
    for (count = 0; count < TMP_MAX; value += 7777, ++count)
154
    {
155
        low = value & UINT32_MAX;
156
        high = value >> 32;
157
 
158
        for (i = 0 ; i < 6 ; i++) {
159
            rh = high % 62;
160
            high /= 62;
161
#define L ((UINT32_MAX % 62 + 1) % 62)
162
            k = (low % 62) + (L * rh);
163
#undef L
164
#define H ((UINT32_MAX / 62) + ((UINT32_MAX % 62 + 1) / 62))
165
            low = (low / 62) + (H * rh) + (k / 62);
166
#undef H
167
            k %= 62;
168
            XXXXXX[i] = letters[k];
169
        }
170
 
171
        switch(kind) {
172
            case __GT_NOCREATE:
173
                {
174
                    struct stat st;
175
                    if (stat (tmpl, &st) < 0)
176
                    {
177
                        if (errno == ENOENT)
178
                        {
179
                            __set_errno (save_errno);
180
                            return 0;
181
                        }
182
                        else
183
                            /* Give up now. */
184
                            return -1;
185
                    }
186
                    else
187
                        continue;
188
                }
189
            case __GT_FILE:
190
                fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
191
                break;
192
#if defined __UCLIBC_HAS_LFS__
193
            case __GT_BIGFILE:
194
                fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
195
                break;
196
#endif
197
            case __GT_DIR:
198
                fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
199
                break;
200
            default:
201
                fd = -1;
202
                assert (! "invalid KIND in __gen_tempname");
203
        }
204
 
205
        if (fd >= 0) {
206
            __set_errno (save_errno);
207
            return fd;
208
        }
209
        else if (errno != EEXIST)
210
            /* Any other error will apply also to other names we might
211
               try, and there are 2^32 or so of them, so give up now. */
212
            return -1;
213
    }
214
 
215
    /* We got out of the loop because we ran out of combinations to try.  */
216
    __set_errno (EEXIST);
217
    return -1;
218
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.