tdf#154546 skip dispatch when presenter controller is not set
[LibreOffice.git] / sal / osl / unx / tempfile.cxx
blob29a4d453f80c2fc2406429da96f9562912c9bb9f
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.hxx"
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.hxx"
33 #include "file_impl.hxx"
35 #include <cassert>
37 oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
39 oslFileError error;
40 /* described in environ(7) */
41 const char *pValue = getenv( "TMPDIR" );
42 rtl_uString *ustrTempPath = nullptr;
44 if ( !pValue )
45 pValue = getenv( "TEMP" );
47 if ( !pValue )
48 pValue = getenv( "TMP" );
50 if ( !pValue )
51 pValue = "/tmp";
53 auto nLen = strlen(pValue);
54 while (nLen > 1 && pValue[nLen - 1] == '/') // Allow path consisting of single "/"
55 --nLen;
56 rtl_string2UString( &ustrTempPath, pValue, nLen, osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
57 assert(ustrTempPath);
58 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
59 rtl_uString_release( ustrTempPath );
61 return error;
64 /******************************************************************
65 * Generates a random unique file name. We're using the scheme
66 * from the standard c-lib function mkstemp to generate a more
67 * or less random unique file name
69 * @param rand_name
70 * receives the random name
71 ******************************************************************/
73 const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
74 const int COUNT_OF_LETTERS = SAL_N_ELEMENTS(LETTERS) - 1;
76 #define RAND_NAME_LENGTH 6
78 static void osl_gen_random_name_impl_(rtl_uString** rand_name)
80 static uint64_t value;
82 char buffer[RAND_NAME_LENGTH];
83 struct timeval tv;
84 uint64_t v;
85 int i;
87 gettimeofday(&tv, nullptr);
89 value += (static_cast<uint64_t>(tv.tv_usec) << 16) ^ tv.tv_sec ^ getpid();
91 v = value;
93 for (i = 0; i < RAND_NAME_LENGTH; i++)
95 buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
96 v /= COUNT_OF_LETTERS;
99 rtl_string2UString(
100 rand_name,
101 buffer,
102 RAND_NAME_LENGTH,
103 RTL_TEXTENCODING_ASCII_US,
104 OSTRING_TO_OUSTRING_CVTFLAGS);
106 assert(*rand_name);
109 /*****************************************************************
110 * Helper function
111 * Either use the directory provided or the result of
112 * osl_getTempDirUrl and return it as system path and file url
113 ****************************************************************/
115 static oslFileError osl_setup_base_directory_impl_(
116 rtl_uString* pustrDirectoryURL,
117 rtl_uString** ppustr_base_dir)
119 rtl_uString* dir_url = nullptr;
120 rtl_uString* dir = nullptr;
121 oslFileError error = osl_File_E_None;
123 if (pustrDirectoryURL)
124 rtl_uString_assign(&dir_url, pustrDirectoryURL);
125 else
126 error = osl_getTempDirURL(&dir_url);
128 if (error == osl_File_E_None)
130 error = getSystemPathFromFileURL_Ex(dir_url, &dir);
131 rtl_uString_release(dir_url);
134 if (error == osl_File_E_None)
136 rtl_uString_assign(ppustr_base_dir, dir);
137 rtl_uString_release(dir);
140 return error;
143 /*****************************************************************
144 * osl_setup_createTempFile_impl
145 * validate input parameter, setup variables
146 ****************************************************************/
148 static oslFileError osl_setup_createTempFile_impl_(
149 rtl_uString* pustrDirectoryURL,
150 oslFileHandle* pHandle,
151 rtl_uString** ppustrTempFileURL,
152 rtl_uString** ppustr_base_dir,
153 bool* b_delete_on_close)
155 oslFileError osl_error;
157 OSL_PRECOND(((nullptr != pHandle) || (nullptr != ppustrTempFileURL)), "Invalid parameter!");
159 if ((pHandle == nullptr) && (ppustrTempFileURL == nullptr))
161 osl_error = osl_File_E_INVAL;
163 else
165 osl_error = osl_setup_base_directory_impl_(
166 pustrDirectoryURL, ppustr_base_dir);
168 *b_delete_on_close = (ppustrTempFileURL == nullptr);
171 return osl_error;
174 /*****************************************************************
175 * Create a unique file in the specified directory and return
176 * its name
177 ****************************************************************/
179 static oslFileError osl_create_temp_file_impl_(
180 const rtl_uString* pustr_base_directory,
181 oslFileHandle* file_handle,
182 rtl_uString** ppustr_temp_file_name)
184 rtl_uString* rand_name = nullptr;
185 sal_uInt32 len_base_dir = 0;
186 rtl_uString* tmp_file_path = nullptr;
187 rtl_uString* tmp_file_url = nullptr;
188 sal_Int32 capacity = 0;
189 oslFileError osl_error = osl_File_E_None;
190 sal_Int32 offset_file_name;
191 const sal_Unicode* puchr;
193 OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
194 OSL_PRECOND(file_handle, "Invalid Parameter");
195 OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
197 len_base_dir = rtl_uString_getLength(pustr_base_directory);
199 rtl_uString_new_WithLength(
200 &tmp_file_path,
201 (len_base_dir + 1 + RAND_NAME_LENGTH));
202 capacity = len_base_dir + 1 + RAND_NAME_LENGTH;
204 rtl_uStringbuffer_insert(
205 &tmp_file_path,
206 &capacity,
208 rtl_uString_getStr(const_cast<rtl_uString*>(pustr_base_directory)),
209 len_base_dir);
211 offset_file_name = len_base_dir;
213 puchr = rtl_uString_getStr(tmp_file_path);
215 /* ensure that the last character is a '/' */
217 if (puchr[len_base_dir - 1] != '/')
219 rtl_uStringbuffer_insert_ascii(
220 &tmp_file_path,
221 &capacity,
222 len_base_dir,
223 "/",
226 offset_file_name++;
229 while(true) /* try until success */
231 osl_gen_random_name_impl_(&rand_name);
233 rtl_uStringbuffer_insert(
234 &tmp_file_path,
235 &capacity,
236 offset_file_name,
237 rtl_uString_getStr(rand_name),
238 rtl_uString_getLength(rand_name));
240 osl_error = osl_getFileURLFromSystemPath(
241 tmp_file_path, &tmp_file_url);
243 if (osl_error == osl_File_E_None)
245 osl_error = openFile(
246 tmp_file_url,
247 file_handle,
248 osl_File_OpenFlag_Read |
249 osl_File_OpenFlag_Write |
250 osl_File_OpenFlag_Create,
251 S_IRUSR | S_IWUSR);
254 /* in case of error osl_File_E_EXIST we simply try again else we give up */
256 if (osl_error != osl_File_E_EXIST)
258 rtl_uString_release(rand_name);
260 if (tmp_file_url)
261 rtl_uString_release(tmp_file_url);
263 break;
265 } /* while(1) */
267 if (osl_error == osl_File_E_None)
268 rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
270 rtl_uString_release(tmp_file_path);
272 return osl_error;
275 oslFileError SAL_CALL osl_createTempFile(
276 rtl_uString* pustrDirectoryURL,
277 oslFileHandle* pHandle,
278 rtl_uString** ppustrTempFileURL)
280 rtl_uString* base_directory = nullptr;
281 oslFileHandle temp_file_handle = nullptr;
282 bool b_delete_on_close;
283 oslFileError osl_error;
285 osl_error = osl_setup_createTempFile_impl_(
286 pustrDirectoryURL,
287 pHandle,
288 ppustrTempFileURL,
289 &base_directory,
290 &b_delete_on_close);
292 if (osl_error != osl_File_E_None)
293 return osl_error;
295 rtl_uString* temp_file_name = nullptr;
296 osl_error = osl_create_temp_file_impl_(
297 base_directory, &temp_file_handle, &temp_file_name);
299 rtl_uString* temp_file_url = nullptr;
300 if (osl_error == osl_File_E_None)
302 osl_error = osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
303 rtl_uString_release(temp_file_name);
306 if (osl_error == osl_File_E_None)
308 if (b_delete_on_close)
310 osl_error = osl_removeFile(temp_file_url);
312 if (osl_error == osl_File_E_None)
314 *pHandle = temp_file_handle;
315 temp_file_handle = nullptr;
318 else
320 if (pHandle)
322 *pHandle = temp_file_handle;
323 temp_file_handle = nullptr;
326 rtl_uString_assign(ppustrTempFileURL, temp_file_url);
329 rtl_uString_release(temp_file_url);
332 if (temp_file_handle)
333 osl_closeFile(temp_file_handle);
335 rtl_uString_release(base_directory);
337 return osl_error;
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */