1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "apr_private.h"
17 #include "apr_file_io.h"
18 #include "apr_strings.h"
19 #include "apr_env.h"
20
21
22 /* Try to open a temporary file in the temporary dir, write to it,
23 and then close it. */
test_tempdir(const char * temp_dir,apr_pool_t * p)24 static int test_tempdir(const char *temp_dir, apr_pool_t *p)
25 {
26 apr_file_t *dummy_file;
27 char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL);
28
29 if (apr_file_mktemp(&dummy_file, path, 0, p) == APR_SUCCESS) {
30 if (apr_file_putc('!', dummy_file) == APR_SUCCESS) {
31 if (apr_file_close(dummy_file) == APR_SUCCESS) {
32 return 1;
33 }
34 }
35 }
36 return 0;
37 }
38
39
apr_temp_dir_get(const char ** temp_dir,apr_pool_t * p)40 APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir,
41 apr_pool_t *p)
42 {
43 apr_status_t apr_err;
44 const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
45 const char *try_envs[] = { "TMPDIR", "TMP", "TEMP"};
46 const char *dir;
47 char *cwd;
48 int i;
49
50 /* Our goal is to find a temporary directory suitable for writing
51 into.
52 Here's the order in which we'll try various paths:
53
54 $TMPDIR
55 $TMP
56 $TEMP
57 "C:\TEMP" (windows only)
58 "SYS:\TMP" (netware only)
59 "/tmp"
60 "/var/tmp"
61 "/usr/tmp"
62 P_tmpdir (POSIX define)
63 `pwd`
64
65 NOTE: This algorithm is basically the same one used by Python
66 2.2's tempfile.py module. */
67
68 /* Try the environment first. */
69 for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++) {
70 char *value;
71 apr_err = apr_env_get(&value, try_envs[i], p);
72 if ((apr_err == APR_SUCCESS) && value) {
73 apr_size_t len = strlen(value);
74 if (len && (len < APR_PATH_MAX) && test_tempdir(value, p)) {
75 dir = value;
76 goto end;
77 }
78 }
79 }
80
81 #ifdef WIN32
82 /* Next, on Win32, try the C:\TEMP directory. */
83 if (test_tempdir("C:\\TEMP", p)) {
84 dir = "C:\\TEMP";
85 goto end;
86 }
87 #endif
88 #ifdef NETWARE
89 /* Next, on NetWare, try the SYS:/TMP directory. */
90 if (test_tempdir("SYS:/TMP", p)) {
91 dir = "SYS:/TMP";
92 goto end;
93 }
94 #endif
95
96 /* Next, try a set of hard-coded paths. */
97 for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++) {
98 if (test_tempdir(try_dirs[i], p)) {
99 dir = try_dirs[i];
100 goto end;
101 }
102 }
103
104 #ifdef P_tmpdir
105 /*
106 * If we have it, use the POSIX definition of where
107 * the tmpdir should be
108 */
109 if (test_tempdir(P_tmpdir, p)) {
110 dir = P_tmpdir;
111 goto end;
112 }
113 #endif
114
115 /* Finally, try the current working directory. */
116 if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, p)) {
117 if (test_tempdir(cwd, p)) {
118 dir = cwd;
119 goto end;
120 }
121 }
122
123 /* We didn't find a suitable temp dir anywhere */
124 return APR_EGENERAL;
125
126 end:
127 *temp_dir = apr_pstrdup(p, dir);
128 return APR_SUCCESS;
129 }
130