Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / sal / osl / unx / tempfile.cxx
blobbbe3c27e0d39284f83bf596b286c98f219871ed2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include "system.h"
26 #include <osl/file.h>
27 #include <osl/thread.h>
28 #include <rtl/ustrbuf.h>
29 #include <osl/diagnose.h>
30 #include <sal/macros.h>
32 #include "file_url.h"
33 #include "file_impl.hxx"
35 oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
37 oslFileError error;
38 /* described in environ(7) */
39 const char *pValue = getenv( "TMPDIR" );
40 rtl_uString *ustrTempPath = NULL;
42 if ( !pValue )
43 pValue = getenv( "TEMP" );
45 if ( !pValue )
46 pValue = getenv( "TMP" );
48 if ( !pValue )
49 pValue = "/tmp";
51 rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
52 OSL_ASSERT(ustrTempPath != NULL);
53 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
54 rtl_uString_release( ustrTempPath );
56 return error;
59 /******************************************************************
60 * Generates a random unique file name. We're using the scheme
61 * from the standard c-lib function mkstemp to generate a more
62 * or less random unique file name
64 * @param rand_name
65 * receives the random name
66 ******************************************************************/
68 static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
69 static const int COUNT_OF_LETTERS = SAL_N_ELEMENTS(LETTERS) - 1;
71 #define RAND_NAME_LENGTH 6
73 static void osl_gen_random_name_impl_(rtl_uString** rand_name)
75 static uint64_t value;
77 char buffer[RAND_NAME_LENGTH];
78 struct timeval tv;
79 uint64_t v;
80 int i;
82 gettimeofday(&tv, NULL);
84 value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
86 v = value;
88 for (i = 0; i < RAND_NAME_LENGTH; i++)
90 buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
91 v /= COUNT_OF_LETTERS;
94 rtl_string2UString(
95 rand_name,
96 buffer,
97 RAND_NAME_LENGTH,
98 RTL_TEXTENCODING_ASCII_US,
99 OSTRING_TO_OUSTRING_CVTFLAGS);
100 OSL_ASSERT(*rand_name != NULL);
103 /*****************************************************************
104 * Helper function
105 * Either use the directory provided or the result of
106 * osl_getTempDirUrl and return it as system path and file url
107 ****************************************************************/
109 static oslFileError osl_setup_base_directory_impl_(
110 rtl_uString* pustrDirectoryURL,
111 rtl_uString** ppustr_base_dir)
113 rtl_uString* dir_url = 0;
114 rtl_uString* dir = 0;
115 oslFileError error = osl_File_E_None;
117 if (pustrDirectoryURL)
118 rtl_uString_assign(&dir_url, pustrDirectoryURL);
119 else
120 error = osl_getTempDirURL(&dir_url);
122 if (osl_File_E_None == error)
124 error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir);
125 rtl_uString_release(dir_url);
128 if (osl_File_E_None == error)
130 rtl_uString_assign(ppustr_base_dir, dir);
131 rtl_uString_release(dir);
134 return error;
137 /*****************************************************************
138 * osl_setup_createTempFile_impl
139 * validate input parameter, setup variables
140 ****************************************************************/
142 static oslFileError osl_setup_createTempFile_impl_(
143 rtl_uString* pustrDirectoryURL,
144 oslFileHandle* pHandle,
145 rtl_uString** ppustrTempFileURL,
146 rtl_uString** ppustr_base_dir,
147 sal_Bool* b_delete_on_close)
149 oslFileError osl_error;
151 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
153 if ((0 == pHandle) && (0 == ppustrTempFileURL))
155 osl_error = osl_File_E_INVAL;
157 else
159 osl_error = osl_setup_base_directory_impl_(
160 pustrDirectoryURL, ppustr_base_dir);
162 *b_delete_on_close = (0 == ppustrTempFileURL);
165 return osl_error;
168 /*****************************************************************
169 * Create a unique file in the specified directory and return
170 * its name
171 ****************************************************************/
173 static oslFileError osl_create_temp_file_impl_(
174 const rtl_uString* pustr_base_directory,
175 oslFileHandle* file_handle,
176 rtl_uString** ppustr_temp_file_name)
178 rtl_uString* rand_name = 0;
179 sal_uInt32 len_base_dir = 0;
180 rtl_uString* tmp_file_path = 0;
181 rtl_uString* tmp_file_url = 0;
182 sal_Int32 capacity = 0;
183 oslFileError osl_error = osl_File_E_None;
184 sal_Int32 offset_file_name;
185 const sal_Unicode* puchr;
187 OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
188 OSL_PRECOND(file_handle, "Invalid Parameter");
189 OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
191 len_base_dir = rtl_uString_getLength(pustr_base_directory);
193 rtl_uStringbuffer_newFromStr_WithLength(
194 &tmp_file_path,
195 rtl_uString_getStr((rtl_uString*)pustr_base_directory),
196 len_base_dir);
198 rtl_uStringbuffer_ensureCapacity(
199 &tmp_file_path,
200 &capacity,
201 (len_base_dir + 1 + RAND_NAME_LENGTH));
203 offset_file_name = len_base_dir;
205 puchr = rtl_uString_getStr(tmp_file_path);
207 /* ensure that the last character is a '/' */
209 if ((sal_Unicode)'/' != puchr[len_base_dir - 1])
211 rtl_uStringbuffer_insert_ascii(
212 &tmp_file_path,
213 &capacity,
214 len_base_dir,
215 "/",
218 offset_file_name++;
221 while(true) /* try until success */
223 osl_gen_random_name_impl_(&rand_name);
225 rtl_uStringbuffer_insert(
226 &tmp_file_path,
227 &capacity,
228 offset_file_name,
229 rtl_uString_getStr(rand_name),
230 rtl_uString_getLength(rand_name));
232 osl_error = osl_getFileURLFromSystemPath(
233 tmp_file_path, &tmp_file_url);
235 if (osl_File_E_None == osl_error)
237 osl_error = openFile(
238 tmp_file_url,
239 file_handle,
240 osl_File_OpenFlag_Read |
241 osl_File_OpenFlag_Write |
242 osl_File_OpenFlag_Create,
243 S_IRUSR | S_IWUSR);
246 /* in case of error osl_File_E_EXIST we simply try again else we give up */
248 if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
250 rtl_uString_release(rand_name);
252 if (tmp_file_url)
253 rtl_uString_release(tmp_file_url);
255 break;
257 } /* while(1) */
259 if (osl_File_E_None == osl_error)
260 rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
262 rtl_uString_release(tmp_file_path);
264 return osl_error;
267 oslFileError SAL_CALL osl_createTempFile(
268 rtl_uString* pustrDirectoryURL,
269 oslFileHandle* pHandle,
270 rtl_uString** ppustrTempFileURL)
272 rtl_uString* base_directory = 0;
273 rtl_uString* temp_file_name = 0;
274 oslFileHandle temp_file_handle;
275 sal_Bool b_delete_on_close;
276 oslFileError osl_error;
278 osl_error = osl_setup_createTempFile_impl_(
279 pustrDirectoryURL,
280 pHandle,
281 ppustrTempFileURL,
282 &base_directory,
283 &b_delete_on_close);
285 if (osl_File_E_None != osl_error)
286 return osl_error;
288 osl_error = osl_create_temp_file_impl_(
289 base_directory, &temp_file_handle, &temp_file_name);
291 if (osl_File_E_None == osl_error)
293 rtl_uString* temp_file_url = 0;
295 /* assuming this works */
296 osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
298 if (b_delete_on_close)
300 osl_error = osl_removeFile(temp_file_url);
302 if (osl_File_E_None == osl_error)
303 *pHandle = temp_file_handle;
304 else
305 osl_closeFile(temp_file_handle);
307 else
309 if (pHandle)
310 *pHandle = temp_file_handle;
311 else
312 osl_closeFile(temp_file_handle);
314 rtl_uString_assign(ppustrTempFileURL, temp_file_url);
317 rtl_uString_release(temp_file_url);
319 rtl_uString_release(temp_file_name);
322 rtl_uString_release(base_directory);
324 return osl_error;
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */