1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251875Speter * contributor license agreements.  See the NOTICE file distributed with
3251875Speter * this work for additional information regarding copyright ownership.
4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251875Speter * (the "License"); you may not use this file except in compliance with
6251875Speter * the License.  You may obtain a copy of the License at
7251875Speter *
8251875Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251875Speter *
10251875Speter * Unless required by applicable law or agreed to in writing, software
11251875Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251875Speter * See the License for the specific language governing permissions and
14251875Speter * limitations under the License.
15251875Speter */
16251875Speter#include "apr_private.h"
17251875Speter#include "apr_file_io.h"
18251875Speter#include "apr_strings.h"
19251875Speter#include "apr_env.h"
20251875Speter
21251875Speter
22251875Speter/* Try to open a temporary file in the temporary dir, write to it,
23251875Speter   and then close it. */
24251875Speterstatic int test_tempdir(const char *temp_dir, apr_pool_t *p)
25251875Speter{
26251875Speter    apr_file_t *dummy_file;
27251875Speter    char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL);
28251875Speter
29251875Speter    if (apr_file_mktemp(&dummy_file, path, 0, p) == APR_SUCCESS) {
30251875Speter        if (apr_file_putc('!', dummy_file) == APR_SUCCESS) {
31251875Speter            if (apr_file_close(dummy_file) == APR_SUCCESS) {
32251875Speter                return 1;
33251875Speter            }
34251875Speter        }
35251875Speter    }
36251875Speter    return 0;
37251875Speter}
38251875Speter
39251875Speter
40251875SpeterAPR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir,
41251875Speter                                           apr_pool_t *p)
42251875Speter{
43251875Speter    apr_status_t apr_err;
44251875Speter    const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
45251875Speter    const char *try_envs[] = { "TMPDIR", "TMP", "TEMP"};
46251875Speter    const char *dir;
47251875Speter    char *cwd;
48251875Speter    int i;
49251875Speter
50251875Speter    /* Our goal is to find a temporary directory suitable for writing
51251875Speter       into.
52251875Speter       Here's the order in which we'll try various paths:
53251875Speter
54251875Speter          $TMPDIR
55251875Speter          $TMP
56251875Speter          $TEMP
57251875Speter          "C:\TEMP"     (windows only)
58251875Speter          "SYS:\TMP"    (netware only)
59251875Speter          "/tmp"
60251875Speter          "/var/tmp"
61251875Speter          "/usr/tmp"
62251875Speter          P_tmpdir      (POSIX define)
63251875Speter          `pwd`
64251875Speter
65251875Speter       NOTE: This algorithm is basically the same one used by Python
66251875Speter       2.2's tempfile.py module.  */
67251875Speter
68251875Speter    /* Try the environment first. */
69251875Speter    for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++) {
70251875Speter        char *value;
71251875Speter        apr_err = apr_env_get(&value, try_envs[i], p);
72251875Speter        if ((apr_err == APR_SUCCESS) && value) {
73251875Speter            apr_size_t len = strlen(value);
74251875Speter            if (len && (len < APR_PATH_MAX) && test_tempdir(value, p)) {
75251875Speter                dir = value;
76251875Speter                goto end;
77251875Speter            }
78251875Speter        }
79251875Speter    }
80251875Speter
81251875Speter#ifdef WIN32
82251875Speter    /* Next, on Win32, try the C:\TEMP directory. */
83251875Speter    if (test_tempdir("C:\\TEMP", p)) {
84251875Speter        dir = "C:\\TEMP";
85251875Speter        goto end;
86251875Speter    }
87251875Speter#endif
88251875Speter#ifdef NETWARE
89251875Speter    /* Next, on NetWare, try the SYS:/TMP directory. */
90251875Speter    if (test_tempdir("SYS:/TMP", p)) {
91251875Speter        dir = "SYS:/TMP";
92251875Speter        goto end;
93251875Speter    }
94251875Speter#endif
95251875Speter
96251875Speter    /* Next, try a set of hard-coded paths. */
97251875Speter    for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++) {
98251875Speter        if (test_tempdir(try_dirs[i], p)) {
99251875Speter            dir = try_dirs[i];
100251875Speter            goto end;
101251875Speter        }
102251875Speter    }
103251875Speter
104251875Speter#ifdef P_tmpdir
105251875Speter    /*
106251875Speter     * If we have it, use the POSIX definition of where
107251875Speter     * the tmpdir should be
108251875Speter     */
109251875Speter    if (test_tempdir(P_tmpdir, p)) {
110251875Speter        dir = P_tmpdir;
111251875Speter        goto end;
112251875Speter    }
113251875Speter#endif
114251875Speter
115251875Speter    /* Finally, try the current working directory. */
116251875Speter    if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, p)) {
117251875Speter        if (test_tempdir(cwd, p)) {
118251875Speter            dir = cwd;
119251875Speter	    goto end;
120251875Speter        }
121251875Speter    }
122251875Speter
123251875Speter    /* We didn't find a suitable temp dir anywhere */
124251875Speter    return APR_EGENERAL;
125251875Speter
126251875Speterend:
127251875Speter    *temp_dir = apr_pstrdup(p, dir);
128251875Speter    return APR_SUCCESS;
129251875Speter}
130