mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
ba22c3f29a
Bug#68338 RFE: make tmpdir a build-time configurable option Background: Some distributions use tmpfs for mounting /tmp by default, which has some advantages, but brings also new issues. Fedora started using tmpfs on /tmp in version 18 for example. If not configured otherwise in my.cnf, MySQL uses system's constant P_tmpdir expanded to /tmp on Linux. This can introduce some problems with limited space in /tmp and also some data loss in case of replication slave [1]. In case distributions would like to use /var/tmp, which should be better for MySQL purposes, then we have to patch the source or change tmpdir option in my.cnf, which is however not updated in case it has already existed. Thus, it would be useful to be able to specify default tmpdir path using a configure option, while using P_tmpdir in case it is not defined explicitly. Based on a contribution from Honza Horak
177 lines
4.9 KiB
C
177 lines
4.9 KiB
C
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
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; version 2 of the License.
|
|
|
|
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#include "mysys_priv.h"
|
|
#include <m_string.h>
|
|
#include "my_static.h"
|
|
#include "mysys_err.h"
|
|
#include <errno.h>
|
|
#ifdef HAVE_PATHS_H
|
|
#include <paths.h>
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
@brief
|
|
Create a temporary file with unique name in a given directory
|
|
|
|
@details
|
|
create_temp_file
|
|
to pointer to buffer where temporary filename will be stored
|
|
dir directory where to create the file
|
|
prefix prefix the filename with this
|
|
mode Flags to use for my_create/my_open
|
|
MyFlags Magic flags
|
|
|
|
@return
|
|
File descriptor of opened file if success
|
|
-1 and sets errno if fails.
|
|
|
|
@note
|
|
The behaviour of this function differs a lot between
|
|
implementation, it's main use is to generate a file with
|
|
a name that does not already exist.
|
|
|
|
When passing O_TEMPORARY flag in "mode" the file should
|
|
be automatically deleted
|
|
|
|
The implementation using mkstemp should be considered the
|
|
reference implementation when adding a new or modifying an
|
|
existing one
|
|
|
|
*/
|
|
|
|
File create_temp_file(char *to, const char *dir, const char *prefix,
|
|
int mode __attribute__((unused)),
|
|
myf MyFlags __attribute__((unused)))
|
|
{
|
|
File file= -1;
|
|
#ifdef __WIN__
|
|
TCHAR path_buf[MAX_PATH-14];
|
|
#endif
|
|
|
|
DBUG_ENTER("create_temp_file");
|
|
DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
|
|
#if defined (__WIN__)
|
|
|
|
/*
|
|
Use GetTempPath to determine path for temporary files.
|
|
This is because the documentation for GetTempFileName
|
|
has the following to say about this parameter:
|
|
"If this parameter is NULL, the function fails."
|
|
*/
|
|
if (!dir)
|
|
{
|
|
if(GetTempPath(sizeof(path_buf), path_buf) > 0)
|
|
dir = path_buf;
|
|
}
|
|
/*
|
|
Use GetTempFileName to generate a unique filename, create
|
|
the file and release it's handle
|
|
- uses up to the first three letters from prefix
|
|
*/
|
|
if (GetTempFileName(dir, prefix, 0, to) == 0)
|
|
DBUG_RETURN(-1);
|
|
|
|
DBUG_PRINT("info", ("name: %s", to));
|
|
|
|
/*
|
|
Open the file without the "open only if file doesn't already exist"
|
|
since the file has already been created by GetTempFileName
|
|
*/
|
|
if ((file= my_open(to, (mode & ~O_EXCL), MyFlags)) < 0)
|
|
{
|
|
/* Open failed, remove the file created by GetTempFileName */
|
|
int tmp= my_errno;
|
|
(void) my_delete(to, MYF(0));
|
|
my_errno= tmp;
|
|
}
|
|
|
|
#elif defined(HAVE_MKSTEMP)
|
|
{
|
|
char prefix_buff[30];
|
|
uint pfx_len;
|
|
File org_file;
|
|
|
|
pfx_len= (uint) (strmov(strnmov(prefix_buff,
|
|
prefix ? prefix : "tmp.",
|
|
sizeof(prefix_buff)-7),"XXXXXX") -
|
|
prefix_buff);
|
|
if (!dir && ! (dir =getenv("TMPDIR")))
|
|
dir= DEFAULT_TMPDIR;
|
|
if (strlen(dir)+ pfx_len > FN_REFLEN-2)
|
|
{
|
|
errno=my_errno= ENAMETOOLONG;
|
|
DBUG_RETURN(file);
|
|
}
|
|
strmov(convert_dirname(to,dir,NullS),prefix_buff);
|
|
org_file=mkstemp(to);
|
|
if (mode & O_TEMPORARY)
|
|
(void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
|
|
file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
|
|
EE_CANTCREATEFILE, MyFlags);
|
|
/* If we didn't manage to register the name, remove the temp file */
|
|
if (org_file >= 0 && file < 0)
|
|
{
|
|
int tmp=my_errno;
|
|
close(org_file);
|
|
(void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
|
|
my_errno=tmp;
|
|
}
|
|
}
|
|
#elif defined(HAVE_TEMPNAM)
|
|
{
|
|
extern char **environ;
|
|
|
|
char *res,**old_env,*temp_env[1];
|
|
if (dir && !dir[0])
|
|
{ /* Change empty string to current dir */
|
|
to[0]= FN_CURLIB;
|
|
to[1]= 0;
|
|
dir=to;
|
|
}
|
|
|
|
old_env= (char**) environ;
|
|
if (dir)
|
|
{ /* Don't use TMPDIR if dir is given */
|
|
environ=(const char**) temp_env;
|
|
temp_env[0]=0;
|
|
}
|
|
|
|
if ((res=tempnam((char*) dir, (char*) prefix)))
|
|
{
|
|
strmake(to,res,FN_REFLEN-1);
|
|
(*free)(res);
|
|
file=my_create(to,0,
|
|
(int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW |
|
|
O_TEMPORARY | O_SHORT_LIVED),
|
|
MYF(MY_WME));
|
|
|
|
}
|
|
else
|
|
{
|
|
DBUG_PRINT("error",("Got error: %d from tempnam",errno));
|
|
}
|
|
|
|
environ=(const char**) old_env;
|
|
}
|
|
#else
|
|
#error No implementation found for create_temp_file
|
|
#endif
|
|
if (file >= 0)
|
|
thread_safe_increment(my_tmp_file_created,&THR_LOCK_open);
|
|
DBUG_RETURN(file);
|
|
}
|