Bump for 3.6-28
[LibreOffice.git] / sal / osl / unx / tempfile.c
blob9517e86ef56b402ae2a5ecc77023204df6e4048f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 /*****************************************************************/
30 /* Includes */
31 /*****************************************************************/
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/time.h>
38 #include "system.h"
39 #include <osl/file.h>
40 #include <osl/thread.h>
41 #include <rtl/ustrbuf.h>
42 #include <osl/diagnose.h>
43 #include <sal/macros.h>
45 #ifndef _FILE_URL_H_
46 #include "file_url.h"
47 #endif
49 oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
51 oslFileError error;
52 /* described in environ(7) */
53 const char *pValue = getenv( "TMPDIR" );
54 rtl_uString *ustrTempPath = NULL;
56 if ( !pValue )
57 pValue = getenv( "TEMP" );
59 if ( !pValue )
60 pValue = getenv( "TMP" );
62 if ( !pValue )
63 pValue = "/tmp";
65 rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
66 OSL_ASSERT(ustrTempPath != NULL);
67 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
68 rtl_uString_release( ustrTempPath );
70 return error;
73 /******************************************************************
74 * Generates a random unique file name. We're using the scheme
75 * from the standard c-lib function mkstemp to generate a more
76 * or less random unique file name
78 * @param rand_name
79 * receives the random name
80 ******************************************************************/
82 static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
83 static const int COUNT_OF_LETTERS = SAL_N_ELEMENTS(LETTERS) - 1;
85 #define RAND_NAME_LENGTH 6
87 static void osl_gen_random_name_impl_(rtl_uString** rand_name)
89 static uint64_t value;
91 char buffer[RAND_NAME_LENGTH];
92 struct timeval tv;
93 uint64_t v;
94 int i;
96 gettimeofday(&tv, NULL);
98 value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
100 v = value;
102 for (i = 0; i < RAND_NAME_LENGTH; i++)
104 buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
105 v /= COUNT_OF_LETTERS;
108 rtl_string2UString(
109 rand_name,
110 buffer,
111 RAND_NAME_LENGTH,
112 RTL_TEXTENCODING_ASCII_US,
113 OSTRING_TO_OUSTRING_CVTFLAGS);
114 OSL_ASSERT(*rand_name != NULL);
117 /*****************************************************************
118 * Helper function
119 * Either use the directory provided or the result of
120 * osl_getTempDirUrl and return it as system path and file url
121 ****************************************************************/
123 static oslFileError osl_setup_base_directory_impl_(
124 rtl_uString* pustrDirectoryURL,
125 rtl_uString** ppustr_base_dir)
127 rtl_uString* dir_url = 0;
128 rtl_uString* dir = 0;
129 oslFileError error = osl_File_E_None;
131 if (pustrDirectoryURL)
132 rtl_uString_assign(&dir_url, pustrDirectoryURL);
133 else
134 error = osl_getTempDirURL(&dir_url);
136 if (osl_File_E_None == error)
138 error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
139 rtl_uString_release(dir_url);
142 if (osl_File_E_None == error)
144 rtl_uString_assign(ppustr_base_dir, dir);
145 rtl_uString_release(dir);
148 return error;
151 /*****************************************************************
152 * osl_setup_createTempFile_impl
153 * validate input parameter, setup variables
154 ****************************************************************/
156 static oslFileError osl_setup_createTempFile_impl_(
157 rtl_uString* pustrDirectoryURL,
158 oslFileHandle* pHandle,
159 rtl_uString** ppustrTempFileURL,
160 rtl_uString** ppustr_base_dir,
161 sal_Bool* b_delete_on_close)
163 oslFileError osl_error;
165 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
167 if ((0 == pHandle) && (0 == ppustrTempFileURL))
169 osl_error = osl_File_E_INVAL;
171 else
173 osl_error = osl_setup_base_directory_impl_(
174 pustrDirectoryURL, ppustr_base_dir);
176 *b_delete_on_close = (0 == ppustrTempFileURL);
179 return osl_error;
182 /*****************************************************************
183 * Create a unique file in the specified directory and return
184 * it's name
185 ****************************************************************/
187 static oslFileError osl_create_temp_file_impl_(
188 const rtl_uString* pustr_base_directory,
189 oslFileHandle* file_handle,
190 rtl_uString** ppustr_temp_file_name)
192 rtl_uString* rand_name = 0;
193 sal_uInt32 len_base_dir = 0;
194 rtl_uString* tmp_file_path = 0;
195 rtl_uString* tmp_file_url = 0;
196 sal_Int32 capacity = 0;
197 oslFileError osl_error = osl_File_E_None;
198 sal_Int32 offset_file_name;
199 const sal_Unicode* puchr;
201 OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
202 OSL_PRECOND(file_handle, "Invalid Parameter");
203 OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
205 len_base_dir = rtl_uString_getLength(pustr_base_directory);
207 rtl_uStringbuffer_newFromStr_WithLength(
208 &tmp_file_path,
209 rtl_uString_getStr((rtl_uString*)pustr_base_directory),
210 len_base_dir);
212 rtl_uStringbuffer_ensureCapacity(
213 &tmp_file_path,
214 &capacity,
215 (len_base_dir + 1 + RAND_NAME_LENGTH));
217 offset_file_name = len_base_dir;
219 puchr = rtl_uString_getStr(tmp_file_path);
221 /* ensure that the last character is a '/' */
223 if ((sal_Unicode)'/' != puchr[len_base_dir - 1])
225 rtl_uStringbuffer_insert_ascii(
226 &tmp_file_path,
227 &capacity,
228 len_base_dir,
229 "/",
232 offset_file_name++;
235 while(1) /* try until success */
237 osl_gen_random_name_impl_(&rand_name);
239 rtl_uStringbuffer_insert(
240 &tmp_file_path,
241 &capacity,
242 offset_file_name,
243 rtl_uString_getStr(rand_name),
244 rtl_uString_getLength(rand_name));
246 osl_error = osl_getFileURLFromSystemPath(
247 tmp_file_path, &tmp_file_url);
249 if (osl_File_E_None == osl_error)
251 /* RW permission for the user only! */
252 mode_t old_mode = umask(077);
254 osl_error = osl_openFile(
255 tmp_file_url,
256 file_handle,
257 osl_File_OpenFlag_Read |
258 osl_File_OpenFlag_Write |
259 osl_File_OpenFlag_Create);
261 umask(old_mode);
264 /* in case of error osl_File_E_EXIST we simply try again else we give up */
266 if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
268 if (rand_name)
269 rtl_uString_release(rand_name);
271 if (tmp_file_url)
272 rtl_uString_release(tmp_file_url);
274 break;
276 } /* while(1) */
278 if (osl_File_E_None == osl_error)
279 rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
281 if (tmp_file_path)
282 rtl_uString_release(tmp_file_path);
284 return osl_error;
287 /*****************************************************************
288 * osl_createTempFile
289 *****************************************************************/
291 oslFileError SAL_CALL osl_createTempFile(
292 rtl_uString* pustrDirectoryURL,
293 oslFileHandle* pHandle,
294 rtl_uString** ppustrTempFileURL)
296 rtl_uString* base_directory = 0;
297 rtl_uString* temp_file_name = 0;
298 oslFileHandle temp_file_handle;
299 sal_Bool b_delete_on_close;
300 oslFileError osl_error;
302 osl_error = osl_setup_createTempFile_impl_(
303 pustrDirectoryURL,
304 pHandle,
305 ppustrTempFileURL,
306 &base_directory,
307 &b_delete_on_close);
309 if (osl_File_E_None != osl_error)
310 return osl_error;
312 osl_error = osl_create_temp_file_impl_(
313 base_directory, &temp_file_handle, &temp_file_name);
315 if (osl_File_E_None == osl_error)
317 rtl_uString* temp_file_url = 0;
319 /* assuming this works */
320 osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
322 if (b_delete_on_close)
324 osl_error = osl_removeFile(temp_file_url);
326 if (osl_File_E_None == osl_error)
327 *pHandle = temp_file_handle;
328 else
329 osl_closeFile(temp_file_handle);
331 else
333 if (pHandle)
334 *pHandle = temp_file_handle;
335 else
336 osl_closeFile(temp_file_handle);
338 rtl_uString_assign(ppustrTempFileURL, temp_file_url);
341 if (temp_file_url)
342 rtl_uString_release(temp_file_url);
344 if (temp_file_name)
345 rtl_uString_release(temp_file_name);
348 if (base_directory)
349 rtl_uString_release(base_directory);
351 return osl_error;
354 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */