merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / os2 / tempfile.c
blob8ca6af31f0c37ee4af3e7cae2214b7baeb1c5cd8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tempfile.c,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 /*****************************************************************/
32 /* Includes */
33 /*****************************************************************/
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 #include "system.h"
41 #include <osl/file.h>
42 #include <osl/thread.h>
43 #include <rtl/ustrbuf.h>
44 #include <osl/diagnose.h>
46 #ifndef _FILE_URL_H_
47 #include "file_url.h"
48 #endif
50 /*****************************************************************/
51 /* osl_getTempFirURL */
52 /*****************************************************************/
54 oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
56 const char *pValue = getenv( "TEMP" );
58 if ( !pValue )
60 pValue = getenv( "TMP" );
61 #if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD) || defined (MACOSX)
62 if ( !pValue )
63 pValue = P_tmpdir;
64 #endif
67 if ( pValue )
69 oslFileError error;
70 rtl_uString *ustrTempPath = NULL;
72 rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
73 OSL_ASSERT(ustrTempPath != NULL);
74 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
75 rtl_uString_release( ustrTempPath );
77 return error;
79 else
80 return osl_File_E_NOENT;
83 /******************************************************************
84 * Generates a random unique file name. We're using the scheme
85 * from the standard c-lib function mkstemp to generate a more
86 * or less random unique file name
88 * @param rand_name
89 * receives the random name
90 ******************************************************************/
92 static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
93 static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
95 #define RAND_NAME_LENGTH 6
97 static void osl_gen_random_name_impl_(rtl_uString** rand_name)
99 static uint64_t value;
101 char buffer[RAND_NAME_LENGTH];
102 struct timeval tv;
103 uint64_t v;
104 int i;
106 gettimeofday(&tv, NULL);
108 value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
110 v = value;
112 for (i = 0; i < RAND_NAME_LENGTH; i++)
114 buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
115 v /= COUNT_OF_LETTERS;
118 rtl_string2UString(
119 rand_name,
120 buffer,
121 RAND_NAME_LENGTH,
122 RTL_TEXTENCODING_ASCII_US,
123 OSTRING_TO_OUSTRING_CVTFLAGS);
124 OSL_ASSERT(*rand_name != NULL);
127 /*****************************************************************
128 * Helper function
129 * Either use the directory provided or the result of
130 * osl_getTempDirUrl and return it as system path and file url
131 ****************************************************************/
133 static oslFileError osl_setup_base_directory_impl_(
134 rtl_uString* pustrDirectoryURL,
135 rtl_uString** ppustr_base_dir)
137 rtl_uString* dir_url = 0;
138 rtl_uString* dir = 0;
139 oslFileError error = osl_File_E_None;
141 if (pustrDirectoryURL)
142 rtl_uString_assign(&dir_url, pustrDirectoryURL);
143 else
144 error = osl_getTempDirURL(&dir_url);
146 if (osl_File_E_None == error)
148 error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
149 rtl_uString_release(dir_url);
152 if (osl_File_E_None == error)
154 rtl_uString_assign(ppustr_base_dir, dir);
155 rtl_uString_release(dir);
158 return error;
161 /*****************************************************************
162 * osl_setup_createTempFile_impl
163 * validate input parameter, setup variables
164 ****************************************************************/
166 static oslFileError osl_setup_createTempFile_impl_(
167 rtl_uString* pustrDirectoryURL,
168 oslFileHandle* pHandle,
169 rtl_uString** ppustrTempFileURL,
170 rtl_uString** ppustr_base_dir,
171 sal_Bool* b_delete_on_close)
173 oslFileError osl_error;
175 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
177 if ((0 == pHandle) && (0 == ppustrTempFileURL))
179 osl_error = osl_File_E_INVAL;
181 else
183 osl_error = osl_setup_base_directory_impl_(
184 pustrDirectoryURL, ppustr_base_dir);
186 *b_delete_on_close = (0 == ppustrTempFileURL);
189 return osl_error;
192 /*****************************************************************
193 * Create a unique file in the specified directory and return
194 * it's name
195 ****************************************************************/
197 static oslFileError osl_create_temp_file_impl_(
198 const rtl_uString* pustr_base_directory,
199 oslFileHandle* file_handle,
200 rtl_uString** ppustr_temp_file_name)
202 rtl_uString* rand_name = 0;
203 sal_uInt32 len_base_dir = 0;
204 rtl_uString* tmp_file_path = 0;
205 rtl_uString* tmp_file_url = 0;
206 sal_Int32 capacity = 0;
207 oslFileError osl_error = osl_File_E_None;
208 sal_Int32 offset_file_name;
209 const sal_Unicode* puchr;
211 OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
212 OSL_PRECOND(file_handle, "Invalid Parameter");
213 OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
215 len_base_dir = rtl_uString_getLength(pustr_base_directory);
217 rtl_uStringbuffer_newFromStr_WithLength(
218 &tmp_file_path,
219 rtl_uString_getStr((rtl_uString*)pustr_base_directory),
220 len_base_dir);
222 rtl_uStringbuffer_ensureCapacity(
223 &tmp_file_path,
224 &capacity,
225 (len_base_dir + 1 + RAND_NAME_LENGTH));
227 offset_file_name = len_base_dir;
229 puchr = rtl_uString_getStr(tmp_file_path);
231 /* ensure that the last character is a '\' */
233 if ((sal_Unicode)'\\' != puchr[len_base_dir - 1])
235 rtl_uStringbuffer_insert_ascii(
236 &tmp_file_path,
237 &capacity,
238 len_base_dir,
239 "\\",
242 offset_file_name++;
245 while(1) /* try until success */
247 osl_gen_random_name_impl_(&rand_name);
249 rtl_uStringbuffer_insert(
250 &tmp_file_path,
251 &capacity,
252 offset_file_name,
253 rtl_uString_getStr(rand_name),
254 rtl_uString_getLength(rand_name));
256 osl_error = osl_getFileURLFromSystemPath(
257 tmp_file_path, &tmp_file_url);
259 if (osl_File_E_None == osl_error)
261 /* RW permission for the user only! */
262 mode_t old_mode = umask(077);
264 osl_error = osl_openFile(
265 tmp_file_url,
266 file_handle,
267 osl_File_OpenFlag_Read |
268 osl_File_OpenFlag_Write |
269 osl_File_OpenFlag_Create);
271 umask(old_mode);
274 /* in case of error osl_File_E_EXIST we simply try again else we give up */
276 if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
278 if (rand_name)
279 rtl_uString_release(rand_name);
281 if (tmp_file_url)
282 rtl_uString_release(tmp_file_url);
284 break;
286 } /* while(1) */
288 if (osl_File_E_None == osl_error)
289 rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
291 if (tmp_file_path)
292 rtl_uString_release(tmp_file_path);
294 return osl_error;
297 /*****************************************************************
298 * osl_createTempFile
299 *****************************************************************/
301 oslFileError SAL_CALL osl_createTempFile(
302 rtl_uString* pustrDirectoryURL,
303 oslFileHandle* pHandle,
304 rtl_uString** ppustrTempFileURL)
306 rtl_uString* base_directory = 0;
307 rtl_uString* temp_file_name = 0;
308 oslFileHandle temp_file_handle;
309 sal_Bool b_delete_on_close;
310 oslFileError osl_error;
312 osl_error = osl_setup_createTempFile_impl_(
313 pustrDirectoryURL,
314 pHandle,
315 ppustrTempFileURL,
316 &base_directory,
317 &b_delete_on_close);
319 if (osl_File_E_None != osl_error)
320 return osl_error;
322 osl_error = osl_create_temp_file_impl_(
323 base_directory, &temp_file_handle, &temp_file_name);
325 if (osl_File_E_None == osl_error)
327 rtl_uString* temp_file_url = 0;
329 /* assuming this works */
330 osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
332 if (b_delete_on_close)
334 osl_error = osl_removeFile(temp_file_url);
336 if (osl_File_E_None == osl_error)
337 *pHandle = temp_file_handle;
338 else
339 osl_closeFile(temp_file_handle);
341 else
343 if (pHandle)
344 *pHandle = temp_file_handle;
345 else
346 osl_closeFile(temp_file_handle);
348 rtl_uString_assign(ppustrTempFileURL, temp_file_url);
351 if (temp_file_url)
352 rtl_uString_release(temp_file_url);
354 if (temp_file_name)
355 rtl_uString_release(temp_file_name);
358 if (base_directory)
359 rtl_uString_release(base_directory);
361 return osl_error;