xref: /aoo4110/main/sal/osl/w32/tempfile.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #define UNICODE
25 #define _UNICODE
26 #define _WIN32_WINNT_0x0500
27 #include "systools/win32/uwinapi.h"
28 
29 #include "osl/file.h"
30 
31 #include "file_error.h"
32 #include "file_url.h"
33 #include "path_helper.hxx"
34 
35 #include "osl/diagnose.h"
36 
37 #include <malloc.h>
38 #include <tchar.h>
39 
40 //#####################################################
41 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
42 
43 // Allocate n number of t's on the stack return a pointer to it in p
44 #ifdef __MINGW32__
45 #define STACK_ALLOC(p, t, n) (p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));
46 #else
47 #define STACK_ALLOC(p, t, n) __try {(p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));} \
48                              __except(EXCEPTION_EXECUTE_HANDLER) {(p) = 0;}
49 #endif
50 
51 extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle(HANDLE hFile, sal_uInt32 uFlags);
52 
53 //#####################################################
54 // Temp file functions
55 //#####################################################
56 
osl_setup_base_directory_impl_(rtl_uString * pustrDirectoryURL,rtl_uString ** ppustr_base_dir)57 static oslFileError osl_setup_base_directory_impl_(
58 	rtl_uString*  pustrDirectoryURL,
59 	rtl_uString** ppustr_base_dir)
60 {
61 	rtl_uString* dir_url = 0;
62 	rtl_uString* dir     = 0;
63 	oslFileError error   = osl_File_E_None;
64 
65 	if (pustrDirectoryURL)
66 		rtl_uString_assign(&dir_url, pustrDirectoryURL);
67 	else
68 		error = osl_getTempDirURL(&dir_url);
69 
70 	if (osl_File_E_None == error)
71 	{
72         error = _osl_getSystemPathFromFileURL(dir_url, &dir, sal_False);
73         rtl_uString_release(dir_url);
74 	}
75 
76 	if (osl_File_E_None == error )
77 	{
78 		rtl_uString_assign(ppustr_base_dir, dir);
79 		rtl_uString_release(dir);
80 	}
81 
82 	return error;
83 }
84 
85 //#####################################################
osl_setup_createTempFile_impl_(rtl_uString * pustrDirectoryURL,oslFileHandle * pHandle,rtl_uString ** ppustrTempFileURL,rtl_uString ** ppustr_base_dir,sal_Bool * b_delete_on_close)86 static oslFileError osl_setup_createTempFile_impl_(
87 	rtl_uString*   pustrDirectoryURL,
88 	oslFileHandle* pHandle,
89 	rtl_uString**  ppustrTempFileURL,
90 	rtl_uString**  ppustr_base_dir,
91 	sal_Bool*      b_delete_on_close)
92 {
93 	oslFileError osl_error;
94 
95 	OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
96 
97 	if ((0 == pHandle) && (0 == ppustrTempFileURL))
98 	{
99 		osl_error = osl_File_E_INVAL;
100 	}
101 	else
102 	{
103 		osl_error = osl_setup_base_directory_impl_(
104 			pustrDirectoryURL, ppustr_base_dir);
105 
106 		*b_delete_on_close = (sal_Bool)(0 == ppustrTempFileURL);
107 	}
108 
109 	return osl_error;
110 }
111 
112 //#####################################################
osl_win32_GetTempFileName_impl_(rtl_uString * base_directory,LPWSTR temp_file_name)113 static oslFileError osl_win32_GetTempFileName_impl_(
114 	rtl_uString* base_directory, LPWSTR temp_file_name)
115 {
116 	oslFileError osl_error = osl_File_E_None;
117 
118 	if (0 == GetTempFileNameW(
119 			reinterpret_cast<LPCWSTR>(rtl_uString_getStr(base_directory)),
120 			L"",
121 			0,
122 			temp_file_name))
123 	{
124 		osl_error = oslTranslateFileError(GetLastError());
125 	}
126 
127 	return osl_error;
128 }
129 
130 //#####################################################
osl_win32_CreateFile_impl_(LPCWSTR file_name,sal_Bool b_delete_on_close,oslFileHandle * p_handle)131 static sal_Bool osl_win32_CreateFile_impl_(
132 	LPCWSTR file_name, sal_Bool b_delete_on_close, oslFileHandle* p_handle)
133 {
134 	DWORD  flags = FILE_ATTRIBUTE_NORMAL;
135 	HANDLE hFile;
136 
137 	OSL_ASSERT(p_handle);
138 
139 	if (b_delete_on_close)
140 		flags |= FILE_FLAG_DELETE_ON_CLOSE;
141 
142 	hFile = CreateFileW(
143 		file_name,
144 		GENERIC_READ | GENERIC_WRITE,
145 		0,
146 		NULL,
147 		TRUNCATE_EXISTING,
148 		flags,
149 		NULL);
150 
151 	// @@@ ERROR HANDLING @@@
152 	if (IsValidHandle(hFile))
153 		*p_handle = osl_createFileHandleFromOSHandle(hFile, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
154 
155 	return (sal_Bool)IsValidHandle(hFile);
156 }
157 
158 //#############################################
osl_createTempFile_impl_(rtl_uString * base_directory,LPWSTR tmp_name,sal_Bool b_delete_on_close,oslFileHandle * pHandle,rtl_uString ** ppustrTempFileURL)159 static oslFileError osl_createTempFile_impl_(
160 	rtl_uString*   base_directory,
161 	LPWSTR         tmp_name,
162 	sal_Bool       b_delete_on_close,
163 	oslFileHandle* pHandle,
164 	rtl_uString**  ppustrTempFileURL)
165 {
166 	oslFileError osl_error;
167 
168 	do
169 	{
170 		osl_error = osl_win32_GetTempFileName_impl_(base_directory, tmp_name);
171 
172 		/*  if file could not be opened try again */
173 
174 		if ((osl_File_E_None != osl_error) || (0 == pHandle) ||
175 			osl_win32_CreateFile_impl_(tmp_name, b_delete_on_close, pHandle))
176 			break;
177 
178 	} while(1); // try until success
179 
180 	if ((osl_File_E_None == osl_error) && !b_delete_on_close)
181 	{
182 		rtl_uString* pustr = 0;
183 		rtl_uString_newFromStr(&pustr, reinterpret_cast<const sal_Unicode*>(tmp_name));
184 		osl_getFileURLFromSystemPath(pustr, ppustrTempFileURL);
185 		rtl_uString_release(pustr);
186 	}
187 
188 	return osl_error;
189 }
190 
191 //#############################################
osl_createTempFile(rtl_uString * pustrDirectoryURL,oslFileHandle * pHandle,rtl_uString ** ppustrTempFileURL)192 oslFileError SAL_CALL osl_createTempFile(
193     rtl_uString*   pustrDirectoryURL,
194     oslFileHandle* pHandle,
195     rtl_uString**  ppustrTempFileURL)
196 {
197     rtl_uString*    base_directory = 0;
198     LPWSTR          tmp_name;
199     sal_Bool        b_delete_on_close;
200     oslFileError    osl_error;
201 
202     osl_error = osl_setup_createTempFile_impl_(
203         pustrDirectoryURL,
204         pHandle,
205         ppustrTempFileURL,
206         &base_directory,
207         &b_delete_on_close);
208 
209     if (osl_File_E_None != osl_error)
210         return osl_error;
211 
212     /* allocate enough space on the stack, the file name can not be longer than MAX_PATH */
213     STACK_ALLOC(tmp_name, WCHAR, (rtl_uString_getLength(base_directory) + MAX_PATH));
214 
215     if (tmp_name)
216     {
217         osl_createTempFile_impl_(
218             base_directory,
219             tmp_name,
220             b_delete_on_close,
221             pHandle,
222             ppustrTempFileURL);
223     }
224     else // stack alloc failed
225     {
226         osl_error = osl_File_E_NOMEM;
227     }
228 
229     if (base_directory)
230         rtl_uString_release(base_directory);
231 
232     return osl_error;
233 }
234 
235 //#############################################
osl_getTempDirURL(rtl_uString ** pustrTempDir)236 oslFileError SAL_CALL osl_getTempDirURL(rtl_uString** pustrTempDir)
237 {
238     ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
239 	LPWSTR	lpBuffer = ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer);
240 	DWORD	nBufferLength = aBuffer.getBufSizeInSymbols() - 1;
241 
242 	DWORD			nLength;
243 	oslFileError	error;
244 
245     nLength = GetTempPathW( aBuffer.getBufSizeInSymbols(), lpBuffer );
246 
247     if ( nLength > nBufferLength )
248     {
249         // the provided path has invalid length
250         error = osl_File_E_NOENT;
251     }
252     else if ( nLength )
253 	{
254 		rtl_uString	*ustrTempPath = NULL;
255 
256 		if ( '\\' == lpBuffer[nLength-1] )
257 			lpBuffer[nLength-1] = 0;
258 
259 		rtl_uString_newFromStr( &ustrTempPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
260 
261 		error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
262 
263 		rtl_uString_release( ustrTempPath );
264 	}
265 	else
266 		error = oslTranslateFileError( GetLastError() );
267 
268 	return error;
269 }
270 
271