update dev300-m58
[ooovba.git] / sal / osl / unx / tempfile.c
blobfdb4833dee6d26b193a0124aa5c4e4312140a624
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.11 $
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 #ifdef MACOSX
57 const char *pValue = getenv( "TMPDIR" );
59 /* If TMPDIR environment variable is not set, use "/tmp" instead
60 of P_tmpdir because its value is "/var/tmp" and it is not
61 deleted on system start up */
62 if ( !pValue )
63 pValue = "/tmp";
64 #else
66 const char *pValue = getenv( "TEMP" );
68 if ( !pValue )
70 pValue = getenv( "TMP" );
71 #if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD)
72 if ( !pValue )
73 pValue = P_tmpdir;
74 #endif
76 #endif /* MACOSX */
78 if ( pValue )
80 oslFileError error;
81 rtl_uString *ustrTempPath = NULL;
83 rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
84 OSL_ASSERT(ustrTempPath != NULL);
85 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
86 rtl_uString_release( ustrTempPath );
88 return error;
90 else
91 return osl_File_E_NOENT;
94 /******************************************************************
95 * Generates a random unique file name. We're using the scheme
96 * from the standard c-lib function mkstemp to generate a more
97 * or less random unique file name
99 * @param rand_name
100 * receives the random name
101 ******************************************************************/
103 static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
104 static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
106 #define RAND_NAME_LENGTH 6
108 static void osl_gen_random_name_impl_(rtl_uString** rand_name)
110 static uint64_t value;
112 char buffer[RAND_NAME_LENGTH];
113 struct timeval tv;
114 uint64_t v;
115 int i;
117 gettimeofday(&tv, NULL);
119 value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
121 v = value;
123 for (i = 0; i < RAND_NAME_LENGTH; i++)
125 buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
126 v /= COUNT_OF_LETTERS;
129 rtl_string2UString(
130 rand_name,
131 buffer,
132 RAND_NAME_LENGTH,
133 RTL_TEXTENCODING_ASCII_US,
134 OSTRING_TO_OUSTRING_CVTFLAGS);
135 OSL_ASSERT(*rand_name != NULL);
138 /*****************************************************************
139 * Helper function
140 * Either use the directory provided or the result of
141 * osl_getTempDirUrl and return it as system path and file url
142 ****************************************************************/
144 static oslFileError osl_setup_base_directory_impl_(
145 rtl_uString* pustrDirectoryURL,
146 rtl_uString** ppustr_base_dir)
148 rtl_uString* dir_url = 0;
149 rtl_uString* dir = 0;
150 oslFileError error = osl_File_E_None;
152 if (pustrDirectoryURL)
153 rtl_uString_assign(&dir_url, pustrDirectoryURL);
154 else
155 error = osl_getTempDirURL(&dir_url);
157 if (osl_File_E_None == error)
159 error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
160 rtl_uString_release(dir_url);
163 if (osl_File_E_None == error)
165 rtl_uString_assign(ppustr_base_dir, dir);
166 rtl_uString_release(dir);
169 return error;
172 /*****************************************************************
173 * osl_setup_createTempFile_impl
174 * validate input parameter, setup variables
175 ****************************************************************/
177 static oslFileError osl_setup_createTempFile_impl_(
178 rtl_uString* pustrDirectoryURL,
179 oslFileHandle* pHandle,
180 rtl_uString** ppustrTempFileURL,
181 rtl_uString** ppustr_base_dir,
182 sal_Bool* b_delete_on_close)
184 oslFileError osl_error;
186 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
188 if ((0 == pHandle) && (0 == ppustrTempFileURL))
190 osl_error = osl_File_E_INVAL;
192 else
194 osl_error = osl_setup_base_directory_impl_(
195 pustrDirectoryURL, ppustr_base_dir);
197 *b_delete_on_close = (0 == ppustrTempFileURL);
200 return osl_error;
203 /*****************************************************************
204 * Create a unique file in the specified directory and return
205 * it's name
206 ****************************************************************/
208 static oslFileError osl_create_temp_file_impl_(
209 const rtl_uString* pustr_base_directory,
210 oslFileHandle* file_handle,
211 rtl_uString** ppustr_temp_file_name)
213 rtl_uString* rand_name = 0;
214 sal_uInt32 len_base_dir = 0;
215 rtl_uString* tmp_file_path = 0;
216 rtl_uString* tmp_file_url = 0;
217 sal_Int32 capacity = 0;
218 oslFileError osl_error = osl_File_E_None;
219 sal_Int32 offset_file_name;
220 const sal_Unicode* puchr;
222 OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
223 OSL_PRECOND(file_handle, "Invalid Parameter");
224 OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
226 len_base_dir = rtl_uString_getLength(pustr_base_directory);
228 rtl_uStringbuffer_newFromStr_WithLength(
229 &tmp_file_path,
230 rtl_uString_getStr((rtl_uString*)pustr_base_directory),
231 len_base_dir);
233 rtl_uStringbuffer_ensureCapacity(
234 &tmp_file_path,
235 &capacity,
236 (len_base_dir + 1 + RAND_NAME_LENGTH));
238 offset_file_name = len_base_dir;
240 puchr = rtl_uString_getStr(tmp_file_path);
242 /* ensure that the last character is a '/' */
244 if ((sal_Unicode)'/' != puchr[len_base_dir - 1])
246 rtl_uStringbuffer_insert_ascii(
247 &tmp_file_path,
248 &capacity,
249 len_base_dir,
250 "/",
253 offset_file_name++;
256 while(1) /* try until success */
258 osl_gen_random_name_impl_(&rand_name);
260 rtl_uStringbuffer_insert(
261 &tmp_file_path,
262 &capacity,
263 offset_file_name,
264 rtl_uString_getStr(rand_name),
265 rtl_uString_getLength(rand_name));
267 osl_error = osl_getFileURLFromSystemPath(
268 tmp_file_path, &tmp_file_url);
270 if (osl_File_E_None == osl_error)
272 /* RW permission for the user only! */
273 mode_t old_mode = umask(077);
275 osl_error = osl_openFile(
276 tmp_file_url,
277 file_handle,
278 osl_File_OpenFlag_Read |
279 osl_File_OpenFlag_Write |
280 osl_File_OpenFlag_Create);
282 umask(old_mode);
285 /* in case of error osl_File_E_EXIST we simply try again else we give up */
287 if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
289 if (rand_name)
290 rtl_uString_release(rand_name);
292 if (tmp_file_url)
293 rtl_uString_release(tmp_file_url);
295 break;
297 } /* while(1) */
299 if (osl_File_E_None == osl_error)
300 rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
302 if (tmp_file_path)
303 rtl_uString_release(tmp_file_path);
305 return osl_error;
308 /*****************************************************************
309 * osl_createTempFile
310 *****************************************************************/
312 oslFileError SAL_CALL osl_createTempFile(
313 rtl_uString* pustrDirectoryURL,
314 oslFileHandle* pHandle,
315 rtl_uString** ppustrTempFileURL)
317 rtl_uString* base_directory = 0;
318 rtl_uString* temp_file_name = 0;
319 oslFileHandle temp_file_handle;
320 sal_Bool b_delete_on_close;
321 oslFileError osl_error;
323 osl_error = osl_setup_createTempFile_impl_(
324 pustrDirectoryURL,
325 pHandle,
326 ppustrTempFileURL,
327 &base_directory,
328 &b_delete_on_close);
330 if (osl_File_E_None != osl_error)
331 return osl_error;
333 osl_error = osl_create_temp_file_impl_(
334 base_directory, &temp_file_handle, &temp_file_name);
336 if (osl_File_E_None == osl_error)
338 rtl_uString* temp_file_url = 0;
340 /* assuming this works */
341 osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
343 if (b_delete_on_close)
345 osl_error = osl_removeFile(temp_file_url);
347 if (osl_File_E_None == osl_error)
348 *pHandle = temp_file_handle;
349 else
350 osl_closeFile(temp_file_handle);
352 else
354 if (pHandle)
355 *pHandle = temp_file_handle;
356 else
357 osl_closeFile(temp_file_handle);
359 rtl_uString_assign(ppustrTempFileURL, temp_file_url);
362 if (temp_file_url)
363 rtl_uString_release(temp_file_url);
365 if (temp_file_name)
366 rtl_uString_release(temp_file_name);
369 if (base_directory)
370 rtl_uString_release(base_directory);
372 return osl_error;