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