1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 Without limiting anything contained in the foregoing, this file,
15 which is part of C Driver for MySQL (Connector/C), is also subject to the
16 Universal FOSS Exception, version 1.0, a copy of which can be found at
17 http://oss.oracle.com/licenses/universal-foss-exception.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License, version 2.0, for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
27
28 #include "mysys_priv.h"
29 #include <m_string.h>
30 #include "my_static.h"
31 #include "mysys_err.h"
32 #include <errno.h>
33 #include "my_thread_local.h"
34
35
36 /*
37 @brief
38 Create a temporary file with unique name in a given directory
39
40 @details
41 create_temp_file
42 to pointer to buffer where temporary filename will be stored
43 dir directory where to create the file
44 prefix prefix the filename with this
45 mode Flags to use for my_create/my_open
46 MyFlags Magic flags
47
48 @return
49 File descriptor of opened file if success
50 -1 and sets errno if fails.
51
52 @note
53 The behaviour of this function differs a lot between
54 implementation, it's main use is to generate a file with
55 a name that does not already exist.
56
57 When passing O_TEMPORARY flag in "mode" the file should
58 be automatically deleted
59
60 The implementation using mkstemp should be considered the
61 reference implementation when adding a new or modifying an
62 existing one
63
64 */
65
create_temp_file(char * to,const char * dir,const char * prefix,int mode,myf MyFlags)66 File create_temp_file(char *to, const char *dir, const char *prefix,
67 int mode, myf MyFlags)
68 {
69 File file= -1;
70 #ifdef _WIN32
71 TCHAR path_buf[MAX_PATH-14];
72 #endif
73
74 DBUG_ENTER("create_temp_file");
75 DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
76 #if defined(_WIN32)
77
78 /*
79 Use GetTempPath to determine path for temporary files.
80 This is because the documentation for GetTempFileName
81 has the following to say about this parameter:
82 "If this parameter is NULL, the function fails."
83 */
84 if (!dir)
85 {
86 if(GetTempPath(sizeof(path_buf), path_buf) > 0)
87 dir = path_buf;
88 }
89 /*
90 Use GetTempFileName to generate a unique filename, create
91 the file and release it's handle
92 - uses up to the first three letters from prefix
93 */
94 if (GetTempFileName(dir, prefix, 0, to) == 0)
95 DBUG_RETURN(-1);
96
97 DBUG_PRINT("info", ("name: %s", to));
98
99 /*
100 Open the file without the "open only if file doesn't already exist"
101 since the file has already been created by GetTempFileName
102 */
103 if ((file= my_open(to, (mode & ~O_EXCL), MyFlags)) < 0)
104 {
105 /* Open failed, remove the file created by GetTempFileName */
106 int tmp= my_errno();
107 (void) my_delete(to, MYF(0));
108 set_my_errno(tmp);
109 }
110
111 #else /* mkstemp() is available on all non-Windows supported platforms. */
112 {
113 char prefix_buff[30];
114 uint pfx_len;
115 File org_file;
116
117 pfx_len= (uint) (my_stpcpy(my_stpnmov(prefix_buff,
118 prefix ? prefix : "tmp.",
119 sizeof(prefix_buff)-7),"XXXXXX") -
120 prefix_buff);
121 if (!dir && ! (dir =getenv("TMPDIR")))
122 dir= DEFAULT_TMPDIR;
123 if (strlen(dir)+ pfx_len > FN_REFLEN-2)
124 {
125 errno=ENAMETOOLONG;
126 set_my_errno(ENAMETOOLONG);
127 DBUG_RETURN(file);
128 }
129 my_stpcpy(convert_dirname(to,dir,NullS),prefix_buff);
130 org_file=mkstemp(to);
131 if (mode & O_TEMPORARY)
132 (void) my_delete(to, MYF(MY_WME));
133 file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
134 EE_CANTCREATEFILE, MyFlags);
135 /* If we didn't manage to register the name, remove the temp file */
136 if (org_file >= 0 && file < 0)
137 {
138 int tmp=my_errno();
139 close(org_file);
140 (void) my_delete(to, MYF(MY_WME));
141 set_my_errno(tmp);
142 }
143 }
144 #endif
145 if (file >= 0)
146 {
147 mysql_mutex_lock(&THR_LOCK_open);
148 my_tmp_file_created++;
149 mysql_mutex_unlock(&THR_LOCK_open);
150 }
151 DBUG_RETURN(file);
152 }
153