MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mf_tempfile.c
1 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "mysys_priv.h"
17 #include <m_string.h>
18 #include "my_static.h"
19 #include "mysys_err.h"
20 #include <errno.h>
21 #ifdef HAVE_PATHS_H
22 #include <paths.h>
23 #endif
24 
25 
26 
27 /*
28  @brief
29  Create a temporary file with unique name in a given directory
30 
31  @details
32  create_temp_file
33  to pointer to buffer where temporary filename will be stored
34  dir directory where to create the file
35  prefix prefix the filename with this
36  mode Flags to use for my_create/my_open
37  MyFlags Magic flags
38 
39  @return
40  File descriptor of opened file if success
41  -1 and sets errno if fails.
42 
43  @note
44  The behaviour of this function differs a lot between
45  implementation, it's main use is to generate a file with
46  a name that does not already exist.
47 
48  When passing O_TEMPORARY flag in "mode" the file should
49  be automatically deleted
50 
51  The implementation using mkstemp should be considered the
52  reference implementation when adding a new or modifying an
53  existing one
54 
55 */
56 
57 File create_temp_file(char *to, const char *dir, const char *prefix,
58  int mode __attribute__((unused)),
59  myf MyFlags __attribute__((unused)))
60 {
61  File file= -1;
62 #ifdef __WIN__
63  TCHAR path_buf[MAX_PATH-14];
64 #endif
65 
66  DBUG_ENTER("create_temp_file");
67  DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
68 #if defined (__WIN__)
69 
70  /*
71  Use GetTempPath to determine path for temporary files.
72  This is because the documentation for GetTempFileName
73  has the following to say about this parameter:
74  "If this parameter is NULL, the function fails."
75  */
76  if (!dir)
77  {
78  if(GetTempPath(sizeof(path_buf), path_buf) > 0)
79  dir = path_buf;
80  }
81  /*
82  Use GetTempFileName to generate a unique filename, create
83  the file and release it's handle
84  - uses up to the first three letters from prefix
85  */
86  if (GetTempFileName(dir, prefix, 0, to) == 0)
87  DBUG_RETURN(-1);
88 
89  DBUG_PRINT("info", ("name: %s", to));
90 
91  /*
92  Open the file without the "open only if file doesn't already exist"
93  since the file has already been created by GetTempFileName
94  */
95  if ((file= my_open(to, (mode & ~O_EXCL), MyFlags)) < 0)
96  {
97  /* Open failed, remove the file created by GetTempFileName */
98  int tmp= my_errno;
99  (void) my_delete(to, MYF(0));
100  my_errno= tmp;
101  }
102 
103 #elif defined(HAVE_MKSTEMP)
104  {
105  char prefix_buff[30];
106  uint pfx_len;
107  File org_file;
108 
109  pfx_len= (uint) (strmov(strnmov(prefix_buff,
110  prefix ? prefix : "tmp.",
111  sizeof(prefix_buff)-7),"XXXXXX") -
112  prefix_buff);
113  if (!dir && ! (dir =getenv("TMPDIR")))
114  dir=P_tmpdir;
115  if (strlen(dir)+ pfx_len > FN_REFLEN-2)
116  {
117  errno=my_errno= ENAMETOOLONG;
118  DBUG_RETURN(file);
119  }
120  strmov(convert_dirname(to,dir,NullS),prefix_buff);
121  org_file=mkstemp(to);
122  if (mode & O_TEMPORARY)
123  (void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
124  file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
125  EE_CANTCREATEFILE, MyFlags);
126  /* If we didn't manage to register the name, remove the temp file */
127  if (org_file >= 0 && file < 0)
128  {
129  int tmp=my_errno;
130  close(org_file);
131  (void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
132  my_errno=tmp;
133  }
134  }
135 #elif defined(HAVE_TEMPNAM)
136  {
137  extern char **environ;
138 
139  char *res,**old_env,*temp_env[1];
140  if (dir && !dir[0])
141  { /* Change empty string to current dir */
142  to[0]= FN_CURLIB;
143  to[1]= 0;
144  dir=to;
145  }
146 
147  old_env= (char**) environ;
148  if (dir)
149  { /* Don't use TMPDIR if dir is given */
150  environ=(const char**) temp_env;
151  temp_env[0]=0;
152  }
153 
154  if ((res=tempnam((char*) dir, (char*) prefix)))
155  {
156  strmake(to,res,FN_REFLEN-1);
157  (*free)(res);
158  file=my_create(to,0,
159  (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW |
160  O_TEMPORARY | O_SHORT_LIVED),
161  MYF(MY_WME));
162 
163  }
164  else
165  {
166  DBUG_PRINT("error",("Got error: %d from tempnam",errno));
167  }
168 
169  environ=(const char**) old_env;
170  }
171 #else
172 #error No implementation found for create_temp_file
173 #endif
174  if (file >= 0)
175  thread_safe_increment(my_tmp_file_created,&THR_LOCK_open);
176  DBUG_RETURN(file);
177 }