merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / tempfile.c
blobe10fffaa5ce27588a67a26cae366217ad11632eb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 /*****************************************************************/
29 /* Includes */
30 /*****************************************************************/
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include "system.h"
38 #include <osl/file.h>
39 #include <osl/thread.h>
40 #include <rtl/ustrbuf.h>
41 #include <osl/diagnose.h>
43 #ifndef _FILE_URL_H_
44 #include "file_url.h"
45 #endif
47 /*****************************************************************/
48 /* osl_getTempFirURL */
49 /*****************************************************************/
51 oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
53 #ifdef MACOSX
54 const char *pValue = getenv( "TMPDIR" );
56 /* If TMPDIR environment variable is not set, use "/tmp" instead
57 of P_tmpdir because its value is "/var/tmp" and it is not
58 deleted on system start up */
59 if ( !pValue )
60 pValue = "/tmp";
61 #else
63 const char *pValue = getenv( "TEMP" );
65 if ( !pValue )
67 pValue = getenv( "TMP" );
68 #if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD)
69 if ( !pValue )
70 pValue = P_tmpdir;
71 #endif
73 #endif /* MACOSX */
75 if ( pValue )
77 oslFileError error;
78 rtl_uString *ustrTempPath = NULL;
80 rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
81 OSL_ASSERT(ustrTempPath != NULL);
82 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
83 rtl_uString_release( ustrTempPath );
85 return error;
87 else
88 return osl_File_E_NOENT;
91 /******************************************************************
92 * Generates a random unique file name. We're using the scheme
93 * from the standard c-lib function mkstemp to generate a more
94 * or less random unique file name
96 * @param rand_name
97 * receives the random name
98 ******************************************************************/
100 static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
101 static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
103 #define RAND_NAME_LENGTH 6
105 static void osl_gen_random_name_impl_(rtl_uString** rand_name)
107 static uint64_t value;
109 char buffer[RAND_NAME_LENGTH];
110 struct timeval tv;
111 uint64_t v;
112 int i;
114 gettimeofday(&tv, NULL);
116 value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
118 v = value;
120 for (i = 0; i < RAND_NAME_LENGTH; i++)
122 buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
123 v /= COUNT_OF_LETTERS;
126 rtl_string2UString(
127 rand_name,
128 buffer,
129 RAND_NAME_LENGTH,
130 RTL_TEXTENCODING_ASCII_US,
131 OSTRING_TO_OUSTRING_CVTFLAGS);
132 OSL_ASSERT(*rand_name != NULL);
135 /*****************************************************************
136 * Helper function
137 * Either use the directory provided or the result of
138 * osl_getTempDirUrl and return it as system path and file url
139 ****************************************************************/
141 static oslFileError osl_setup_base_directory_impl_(
142 rtl_uString* pustrDirectoryURL,
143 rtl_uString** ppustr_base_dir)
145 rtl_uString* dir_url = 0;
146 rtl_uString* dir = 0;
147 oslFileError error = osl_File_E_None;
149 if (pustrDirectoryURL)
150 rtl_uString_assign(&dir_url, pustrDirectoryURL);
151 else
152 error = osl_getTempDirURL(&dir_url);
154 if (osl_File_E_None == error)
156 error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
157 rtl_uString_release(dir_url);
160 if (osl_File_E_None == error)
162 rtl_uString_assign(ppustr_base_dir, dir);
163 rtl_uString_release(dir);
166 return error;
169 /*****************************************************************
170 * osl_setup_createTempFile_impl
171 * validate input parameter, setup variables
172 ****************************************************************/
174 static oslFileError osl_setup_createTempFile_impl_(
175 rtl_uString* pustrDirectoryURL,
176 oslFileHandle* pHandle,
177 rtl_uString** ppustrTempFileURL,
178 rtl_uString** ppustr_base_dir,
179 sal_Bool* b_delete_on_close)
181 oslFileError osl_error;
183 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
185 if ((0 == pHandle) && (0 == ppustrTempFileURL))
187 osl_error = osl_File_E_INVAL;
189 else
191 osl_error = osl_setup_base_directory_impl_(
192 pustrDirectoryURL, ppustr_base_dir);
194 *b_delete_on_close = (0 == ppustrTempFileURL);
197 return osl_error;
200 /*****************************************************************
201 * Create a unique file in the specified directory and return
202 * it's name
203 ****************************************************************/
205 static oslFileError osl_create_temp_file_impl_(
206 const rtl_uString* pustr_base_directory,
207 oslFileHandle* file_handle,
208 rtl_uString** ppustr_temp_file_name)
210 rtl_uString* rand_name = 0;
211 sal_uInt32 len_base_dir = 0;
212 rtl_uString* tmp_file_path = 0;
213 rtl_uString* tmp_file_url = 0;
214 sal_Int32 capacity = 0;
215 oslFileError osl_error = osl_File_E_None;
216 sal_Int32 offset_file_name;
217 const sal_Unicode* puchr;
219 OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
220 OSL_PRECOND(file_handle, "Invalid Parameter");
221 OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
223 len_base_dir = rtl_uString_getLength(pustr_base_directory);
225 rtl_uStringbuffer_newFromStr_WithLength(
226 &tmp_file_path,
227 rtl_uString_getStr((rtl_uString*)pustr_base_directory),
228 len_base_dir);
230 rtl_uStringbuffer_ensureCapacity(
231 &tmp_file_path,
232 &capacity,
233 (len_base_dir + 1 + RAND_NAME_LENGTH));
235 offset_file_name = len_base_dir;
237 puchr = rtl_uString_getStr(tmp_file_path);
239 /* ensure that the last character is a '/' */
241 if ((sal_Unicode)'/' != puchr[len_base_dir - 1])
243 rtl_uStringbuffer_insert_ascii(
244 &tmp_file_path,
245 &capacity,
246 len_base_dir,
247 "/",
250 offset_file_name++;
253 while(1) /* try until success */
255 osl_gen_random_name_impl_(&rand_name);
257 rtl_uStringbuffer_insert(
258 &tmp_file_path,
259 &capacity,
260 offset_file_name,
261 rtl_uString_getStr(rand_name),
262 rtl_uString_getLength(rand_name));
264 osl_error = osl_getFileURLFromSystemPath(
265 tmp_file_path, &tmp_file_url);
267 if (osl_File_E_None == osl_error)
269 /* RW permission for the user only! */
270 mode_t old_mode = umask(077);
272 osl_error = osl_openFile(
273 tmp_file_url,
274 file_handle,
275 osl_File_OpenFlag_Read |
276 osl_File_OpenFlag_Write |
277 osl_File_OpenFlag_Create);
279 umask(old_mode);
282 /* in case of error osl_File_E_EXIST we simply try again else we give up */
284 if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
286 if (rand_name)
287 rtl_uString_release(rand_name);
289 if (tmp_file_url)
290 rtl_uString_release(tmp_file_url);
292 break;
294 } /* while(1) */
296 if (osl_File_E_None == osl_error)
297 rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
299 if (tmp_file_path)
300 rtl_uString_release(tmp_file_path);
302 return osl_error;
305 /*****************************************************************
306 * osl_createTempFile
307 *****************************************************************/
309 oslFileError SAL_CALL osl_createTempFile(
310 rtl_uString* pustrDirectoryURL,
311 oslFileHandle* pHandle,
312 rtl_uString** ppustrTempFileURL)
314 rtl_uString* base_directory = 0;
315 rtl_uString* temp_file_name = 0;
316 oslFileHandle temp_file_handle;
317 sal_Bool b_delete_on_close;
318 oslFileError osl_error;
320 osl_error = osl_setup_createTempFile_impl_(
321 pustrDirectoryURL,
322 pHandle,
323 ppustrTempFileURL,
324 &base_directory,
325 &b_delete_on_close);
327 if (osl_File_E_None != osl_error)
328 return osl_error;
330 osl_error = osl_create_temp_file_impl_(
331 base_directory, &temp_file_handle, &temp_file_name);
333 if (osl_File_E_None == osl_error)
335 rtl_uString* temp_file_url = 0;
337 /* assuming this works */
338 osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
340 if (b_delete_on_close)
342 osl_error = osl_removeFile(temp_file_url);
344 if (osl_File_E_None == osl_error)
345 *pHandle = temp_file_handle;
346 else
347 osl_closeFile(temp_file_handle);
349 else
351 if (pHandle)
352 *pHandle = temp_file_handle;
353 else
354 osl_closeFile(temp_file_handle);
356 rtl_uString_assign(ppustrTempFileURL, temp_file_url);
359 if (temp_file_url)
360 rtl_uString_release(temp_file_url);
362 if (temp_file_name)
363 rtl_uString_release(temp_file_name);
366 if (base_directory)
367 rtl_uString_release(base_directory);
369 return osl_error;