1 | /* Copyright (C) 1999, 2001-2002, 2006 Free Software Foundation, Inc.
|
---|
2 | This file is part of the GNU C Library.
|
---|
3 |
|
---|
4 | This program is free software; you can redistribute it and/or modify
|
---|
5 | it under the terms of the GNU General Public License as published by
|
---|
6 | the Free Software Foundation; either version 2, or (at your option)
|
---|
7 | any later version.
|
---|
8 |
|
---|
9 | This program 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
|
---|
12 | GNU General Public License for more details.
|
---|
13 |
|
---|
14 | You should have received a copy of the GNU General Public License
|
---|
15 | along with this program; if not, write to the Free Software Foundation,
|
---|
16 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
---|
17 |
|
---|
18 | /* Extracted from sysdeps/posix/tempname.c. */
|
---|
19 |
|
---|
20 | #include <config.h>
|
---|
21 |
|
---|
22 | /* Specification. */
|
---|
23 | #include "tmpdir.h"
|
---|
24 |
|
---|
25 | #include <stdbool.h>
|
---|
26 | #include <stdlib.h>
|
---|
27 | #include <string.h>
|
---|
28 |
|
---|
29 | #include <errno.h>
|
---|
30 | #ifndef __set_errno
|
---|
31 | # define __set_errno(Val) errno = (Val)
|
---|
32 | #endif
|
---|
33 |
|
---|
34 | #include <stdio.h>
|
---|
35 | #ifndef P_tmpdir
|
---|
36 | # define P_tmpdir "/tmp"
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | #include <sys/stat.h>
|
---|
40 |
|
---|
41 | #if _LIBC
|
---|
42 | # define struct_stat64 struct stat64
|
---|
43 | #else
|
---|
44 | # define struct_stat64 struct stat
|
---|
45 | # define __xstat64(version, path, buf) stat (path, buf)
|
---|
46 | #endif
|
---|
47 |
|
---|
48 | #if ! (HAVE___SECURE_GETENV || _LIBC)
|
---|
49 | # define __secure_getenv getenv
|
---|
50 | #endif
|
---|
51 |
|
---|
52 | /* Pathname support.
|
---|
53 | ISSLASH(C) tests whether C is a directory separator character.
|
---|
54 | */
|
---|
55 | #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
|
---|
56 | /* Win32, Cygwin, OS/2, DOS */
|
---|
57 | # define ISSLASH(C) ((C) == '/' || (C) == '\\')
|
---|
58 | #else
|
---|
59 | /* Unix */
|
---|
60 | # define ISSLASH(C) ((C) == '/')
|
---|
61 | #endif
|
---|
62 |
|
---|
63 |
|
---|
64 | /* Return nonzero if DIR is an existent directory. */
|
---|
65 | static bool
|
---|
66 | direxists (const char *dir)
|
---|
67 | {
|
---|
68 | struct_stat64 buf;
|
---|
69 | return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode);
|
---|
70 | }
|
---|
71 |
|
---|
72 | /* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is
|
---|
73 | non-null and exists, uses it; otherwise uses the first of $TMPDIR,
|
---|
74 | P_tmpdir, /tmp that exists. Copies into TMPL a template suitable
|
---|
75 | for use with mk[s]temp. Will fail (-1) if DIR is non-null and
|
---|
76 | doesn't exist, none of the searched dirs exists, or there's not
|
---|
77 | enough space in TMPL. */
|
---|
78 | int
|
---|
79 | path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
|
---|
80 | bool try_tmpdir)
|
---|
81 | {
|
---|
82 | const char *d;
|
---|
83 | size_t dlen, plen;
|
---|
84 |
|
---|
85 | if (!pfx || !pfx[0])
|
---|
86 | {
|
---|
87 | pfx = "file";
|
---|
88 | plen = 4;
|
---|
89 | }
|
---|
90 | else
|
---|
91 | {
|
---|
92 | plen = strlen (pfx);
|
---|
93 | if (plen > 5)
|
---|
94 | plen = 5;
|
---|
95 | }
|
---|
96 |
|
---|
97 | if (try_tmpdir)
|
---|
98 | {
|
---|
99 | d = __secure_getenv ("TMPDIR");
|
---|
100 | if (d != NULL && direxists (d))
|
---|
101 | dir = d;
|
---|
102 | else if (dir != NULL && direxists (dir))
|
---|
103 | /* nothing */ ;
|
---|
104 | else
|
---|
105 | dir = NULL;
|
---|
106 | }
|
---|
107 | if (dir == NULL)
|
---|
108 | {
|
---|
109 | if (direxists (P_tmpdir))
|
---|
110 | dir = P_tmpdir;
|
---|
111 | else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
|
---|
112 | dir = "/tmp";
|
---|
113 | else
|
---|
114 | {
|
---|
115 | __set_errno (ENOENT);
|
---|
116 | return -1;
|
---|
117 | }
|
---|
118 | }
|
---|
119 |
|
---|
120 | dlen = strlen (dir);
|
---|
121 | while (dlen >= 1 && ISSLASH (dir[dlen - 1]))
|
---|
122 | dlen--; /* remove trailing slashes */
|
---|
123 |
|
---|
124 | /* check we have room for "${dir}/${pfx}XXXXXX\0" */
|
---|
125 | if (tmpl_len < dlen + 1 + plen + 6 + 1)
|
---|
126 | {
|
---|
127 | __set_errno (EINVAL);
|
---|
128 | return -1;
|
---|
129 | }
|
---|
130 |
|
---|
131 | sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx);
|
---|
132 | return 0;
|
---|
133 | }
|
---|