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. */ 24static 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 40APR_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 126end: 127 *temp_dir = apr_pstrdup(p, dir); 128 return APR_SUCCESS; 129} 130