/* Copyright (C) 2000 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysys_priv.h" #include #if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) #include /* needed for tmp dir writability check, which is currently done only under DOSish OS's */ #endif #if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) #define DELIM ';' #else #define DELIM ':' #endif my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) { /* Get information into which directories temporary files should be placed: If pathlist is specified: use this information (stage 0). Else: Try, in turn, environment variables TMPDIR, TEMPDIR, TMP, TEMP (Windows; others only use TMPDIR). (Call these attempts stage 1 through stage 4.) Assume that this is a list of directories separated by ';' (Windows) or ':' (others). For each such directory, check whether it exists and is writable. If yes, add it to a list of tmp directories; otherwise, ignore this entry. As soon as one of the stages yields one or more tmp directries, return without checking subsequent stages. If none is successful, try '\' as a last resort (stage 5). This will be returned without writability check. Gisbert W. Selke, 2006-11-18, for free use within MySQL. */ char *end, *copy; char buff[FN_REFLEN]; DYNAMIC_ARRAY t_arr; #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) struct _stat stat_buffer; /* writability check: currently done only under DOSish OS's, should be used generally. */ #endif uint tmpnam_trycount; my_bool tmpnam_lasttry=FALSE; pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&t_arr, sizeof(char*), 1, 5)) return TRUE; tmpnam_trycount=0; tmpnam_lasttry=FALSE; while (!t_arr.elements) { switch(tmpnam_trycount) { case 0 : break; /* Try initial assignment */ case 1 : pathlist=getenv("TMPDIR"); break; /* Try this next if possible */ #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) case 2 : pathlist=getenv("TEMPDIR"); break; /* Try these only under DOSish OS's */ case 3 : pathlist=getenv("TMP"); break; case 4 : pathlist=getenv("TEMP"); break; #endif default : pathlist=(char*) P_tmpdir; tmpnam_lasttry=TRUE; break; /* Last resort */ } if ((pathlist && pathlist[0]) || tmpnam_lasttry) { do { end=strcend(pathlist, DELIM); convert_dirname(buff, pathlist, end); #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) /* The putative dirname now has a directory delimiter at its end, which is not liked by _stat. So we remove it temporarily before we check whether directory exists and is writable. */ copy = (char *)memchr(buff, '\0', FN_REFLEN) - 1; if ((copy-buff > 0) && (*copy == FN_LIBCHAR) && ((copy-buff == 0) || (*(copy-1) != FN_DEVCHAR))) { *copy = '\0'; } else { copy = NULL; } /* writability check: currently done only under DOSish OS's, should be used generally: Use only writable directories, if possible, but make sure we're never without at least one. */ if (tmpnam_lasttry || ((_stat(buff, &stat_buffer) >= 0) && (stat_buffer.st_mode & _S_IFDIR) && (stat_buffer.st_mode & _S_IWRITE) ) ) { /* Restore final dir delimiter if we removed it earlier on: */ if (copy) *copy = FN_LIBCHAR; if (!(copy=my_strdup(buff, MYF(MY_WME)))) return TRUE; if (insert_dynamic(&t_arr, (gptr)©)) return TRUE; } #else /* For other OS's, we currently don't check accessibility and writability, but only because I (gws) cannot test it. So, the whole ifdef monkeying should really be removed so that all OS's get the same treatment. */ if (!(copy=my_strdup(buff, MYF(MY_WME)))) return TRUE; if (insert_dynamic(&t_arr, (gptr)©)) return TRUE; #endif pathlist=end+1; } while (*end); } tmpnam_trycount++; } freeze_size(&t_arr); tmpdir->list=(char **)t_arr.buffer; tmpdir->max=t_arr.elements-1; tmpdir->cur=0; return FALSE; } char *my_tmpdir(MY_TMPDIR *tmpdir) { char *dir; pthread_mutex_lock(&tmpdir->mutex); dir=tmpdir->list[tmpdir->cur]; tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1; pthread_mutex_unlock(&tmpdir->mutex); return dir; } void free_tmpdir(MY_TMPDIR *tmpdir) { uint i; for (i=0; i<=tmpdir->max; i++) my_free(tmpdir->list[i], MYF(0)); my_free((gptr)tmpdir->list, MYF(0)); pthread_mutex_destroy(&tmpdir->mutex); }