Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : /*****************************************************************/
30 : : /* Includes */
31 : : /*****************************************************************/
32 : :
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>
44 : :
45 : : #ifndef _FILE_URL_H_
46 : : #include "file_url.h"
47 : : #endif
48 : :
49 : 5008 : oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
50 : : {
51 : : oslFileError error;
52 : : /* described in environ(7) */
53 : 5008 : const char *pValue = getenv( "TMPDIR" );
54 : 5008 : rtl_uString *ustrTempPath = NULL;
55 : :
56 [ - + ]: 5008 : if ( !pValue )
57 : 0 : pValue = getenv( "TEMP" );
58 : :
59 [ - + ]: 5008 : if ( !pValue )
60 : 0 : pValue = getenv( "TMP" );
61 : :
62 [ - + ]: 5008 : if ( !pValue )
63 : 0 : pValue = "/tmp";
64 : :
65 : 5008 : rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
66 : : OSL_ASSERT(ustrTempPath != NULL);
67 : 5008 : error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
68 : 5008 : rtl_uString_release( ustrTempPath );
69 : :
70 : 5008 : return error;
71 : : }
72 : :
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
77 : : *
78 : : * @param rand_name
79 : : * receives the random name
80 : : ******************************************************************/
81 : :
82 : : static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
83 : : static const int COUNT_OF_LETTERS = SAL_N_ELEMENTS(LETTERS) - 1;
84 : :
85 : : #define RAND_NAME_LENGTH 6
86 : :
87 : 43348 : static void osl_gen_random_name_impl_(rtl_uString** rand_name)
88 : : {
89 : : static uint64_t value;
90 : :
91 : : char buffer[RAND_NAME_LENGTH];
92 : : struct timeval tv;
93 : : uint64_t v;
94 : : int i;
95 : :
96 : 43348 : gettimeofday(&tv, NULL);
97 : :
98 : 43348 : value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
99 : :
100 : 43348 : v = value;
101 : :
102 [ + + ]: 303436 : for (i = 0; i < RAND_NAME_LENGTH; i++)
103 : : {
104 : 260088 : buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
105 : 260088 : v /= COUNT_OF_LETTERS;
106 : : }
107 : :
108 : 43348 : 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);
115 : 43348 : }
116 : :
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 : : ****************************************************************/
122 : :
123 : 43348 : static oslFileError osl_setup_base_directory_impl_(
124 : : rtl_uString* pustrDirectoryURL,
125 : : rtl_uString** ppustr_base_dir)
126 : : {
127 : 43348 : rtl_uString* dir_url = 0;
128 : 43348 : rtl_uString* dir = 0;
129 : 43348 : oslFileError error = osl_File_E_None;
130 : :
131 [ + + ]: 43348 : if (pustrDirectoryURL)
132 : 38716 : rtl_uString_assign(&dir_url, pustrDirectoryURL);
133 : : else
134 : 4632 : error = osl_getTempDirURL(&dir_url);
135 : :
136 [ + - ]: 43348 : if (osl_File_E_None == error)
137 : : {
138 : 43348 : error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
139 : 43348 : rtl_uString_release(dir_url);
140 : : }
141 : :
142 [ + - ]: 43348 : if (osl_File_E_None == error)
143 : : {
144 : 43348 : rtl_uString_assign(ppustr_base_dir, dir);
145 : 43348 : rtl_uString_release(dir);
146 : : }
147 : :
148 : 43348 : return error;
149 : : }
150 : :
151 : : /*****************************************************************
152 : : * osl_setup_createTempFile_impl
153 : : * validate input parameter, setup variables
154 : : ****************************************************************/
155 : :
156 : 43348 : 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)
162 : : {
163 : : oslFileError osl_error;
164 : :
165 : : OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
166 : :
167 [ + + ][ - + ]: 43348 : if ((0 == pHandle) && (0 == ppustrTempFileURL))
168 : : {
169 : 0 : osl_error = osl_File_E_INVAL;
170 : : }
171 : : else
172 : : {
173 : 43348 : osl_error = osl_setup_base_directory_impl_(
174 : : pustrDirectoryURL, ppustr_base_dir);
175 : :
176 : 43348 : *b_delete_on_close = (0 == ppustrTempFileURL);
177 : : }
178 : :
179 : 43348 : return osl_error;
180 : : }
181 : :
182 : : /*****************************************************************
183 : : * Create a unique file in the specified directory and return
184 : : * it's name
185 : : ****************************************************************/
186 : :
187 : 43348 : 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)
191 : : {
192 : 43348 : rtl_uString* rand_name = 0;
193 : 43348 : sal_uInt32 len_base_dir = 0;
194 : 43348 : rtl_uString* tmp_file_path = 0;
195 : 43348 : rtl_uString* tmp_file_url = 0;
196 : 43348 : sal_Int32 capacity = 0;
197 : 43348 : oslFileError osl_error = osl_File_E_None;
198 : : sal_Int32 offset_file_name;
199 : : const sal_Unicode* puchr;
200 : :
201 : : OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
202 : : OSL_PRECOND(file_handle, "Invalid Parameter");
203 : : OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
204 : :
205 : 43348 : len_base_dir = rtl_uString_getLength(pustr_base_directory);
206 : :
207 : 43348 : rtl_uStringbuffer_newFromStr_WithLength(
208 : : &tmp_file_path,
209 : 43348 : rtl_uString_getStr((rtl_uString*)pustr_base_directory),
210 : : len_base_dir);
211 : :
212 : 43348 : rtl_uStringbuffer_ensureCapacity(
213 : : &tmp_file_path,
214 : : &capacity,
215 : 43348 : (len_base_dir + 1 + RAND_NAME_LENGTH));
216 : :
217 : 43348 : offset_file_name = len_base_dir;
218 : :
219 : 43348 : puchr = rtl_uString_getStr(tmp_file_path);
220 : :
221 : : /* ensure that the last character is a '/' */
222 : :
223 [ + + ]: 43348 : if ((sal_Unicode)'/' != puchr[len_base_dir - 1])
224 : : {
225 : 43228 : rtl_uStringbuffer_insert_ascii(
226 : : &tmp_file_path,
227 : : &capacity,
228 : : len_base_dir,
229 : : "/",
230 : : 1);
231 : :
232 : 43228 : offset_file_name++;
233 : : }
234 : :
235 : : while(1) /* try until success */
236 : : {
237 : 43348 : osl_gen_random_name_impl_(&rand_name);
238 : :
239 : 86696 : rtl_uStringbuffer_insert(
240 : : &tmp_file_path,
241 : : &capacity,
242 : : offset_file_name,
243 : 43348 : rtl_uString_getStr(rand_name),
244 : : rtl_uString_getLength(rand_name));
245 : :
246 : 43348 : osl_error = osl_getFileURLFromSystemPath(
247 : : tmp_file_path, &tmp_file_url);
248 : :
249 [ + - ]: 43348 : if (osl_File_E_None == osl_error)
250 : : {
251 : : /* RW permission for the user only! */
252 : 43348 : mode_t old_mode = umask(077);
253 : :
254 : 43348 : 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);
260 : :
261 : 43348 : umask(old_mode);
262 : : }
263 : :
264 : : /* in case of error osl_File_E_EXIST we simply try again else we give up */
265 : :
266 [ - + ][ # # ]: 43348 : if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
267 : : {
268 [ + - ]: 43348 : if (rand_name)
269 : 43348 : rtl_uString_release(rand_name);
270 : :
271 [ + - ]: 43348 : if (tmp_file_url)
272 : 43348 : rtl_uString_release(tmp_file_url);
273 : :
274 : 43348 : break;
275 : : }
276 : 0 : } /* while(1) */
277 : :
278 [ + - ]: 43348 : if (osl_File_E_None == osl_error)
279 : 43348 : rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
280 : :
281 [ + - ]: 43348 : if (tmp_file_path)
282 : 43348 : rtl_uString_release(tmp_file_path);
283 : :
284 : 43348 : return osl_error;
285 : : }
286 : :
287 : : /*****************************************************************
288 : : * osl_createTempFile
289 : : *****************************************************************/
290 : :
291 : 43348 : oslFileError SAL_CALL osl_createTempFile(
292 : : rtl_uString* pustrDirectoryURL,
293 : : oslFileHandle* pHandle,
294 : : rtl_uString** ppustrTempFileURL)
295 : : {
296 : 43348 : rtl_uString* base_directory = 0;
297 : 43348 : rtl_uString* temp_file_name = 0;
298 : : oslFileHandle temp_file_handle;
299 : : sal_Bool b_delete_on_close;
300 : : oslFileError osl_error;
301 : :
302 : 43348 : osl_error = osl_setup_createTempFile_impl_(
303 : : pustrDirectoryURL,
304 : : pHandle,
305 : : ppustrTempFileURL,
306 : : &base_directory,
307 : : &b_delete_on_close);
308 : :
309 [ - + ]: 43348 : if (osl_File_E_None != osl_error)
310 : 0 : return osl_error;
311 : :
312 : 43348 : osl_error = osl_create_temp_file_impl_(
313 : : base_directory, &temp_file_handle, &temp_file_name);
314 : :
315 [ + - ]: 43348 : if (osl_File_E_None == osl_error)
316 : : {
317 : 43348 : rtl_uString* temp_file_url = 0;
318 : :
319 : : /* assuming this works */
320 : 43348 : osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
321 : :
322 [ - + ]: 43348 : if (b_delete_on_close)
323 : : {
324 : 0 : osl_error = osl_removeFile(temp_file_url);
325 : :
326 [ # # ]: 0 : if (osl_File_E_None == osl_error)
327 : 0 : *pHandle = temp_file_handle;
328 : : else
329 : 0 : osl_closeFile(temp_file_handle);
330 : : }
331 : : else
332 : : {
333 [ + + ]: 43348 : if (pHandle)
334 : 38476 : *pHandle = temp_file_handle;
335 : : else
336 : 4872 : osl_closeFile(temp_file_handle);
337 : :
338 : 43348 : rtl_uString_assign(ppustrTempFileURL, temp_file_url);
339 : : }
340 : :
341 [ + - ]: 43348 : if (temp_file_url)
342 : 43348 : rtl_uString_release(temp_file_url);
343 : :
344 [ + - ]: 43348 : if (temp_file_name)
345 : 43348 : rtl_uString_release(temp_file_name);
346 : : }
347 : :
348 [ + - ]: 43348 : if (base_directory)
349 : 43348 : rtl_uString_release(base_directory);
350 : :
351 : 43348 : return osl_error;
352 : : }
353 : :
354 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|