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