1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tempfile.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 /*****************************************************************/
33 /*****************************************************************/
37 #include <sys/types.h>
42 #include <osl/thread.h>
43 #include <rtl/ustrbuf.h>
44 #include <osl/diagnose.h>
50 /*****************************************************************/
51 /* osl_getTempFirURL */
52 /*****************************************************************/
54 oslFileError SAL_CALL
osl_getTempDirURL( rtl_uString
** pustrTempDir
)
57 const char *pValue
= getenv( "TMPDIR" );
59 /* If TMPDIR environment variable is not set, use "/tmp" instead
60 of P_tmpdir because its value is "/var/tmp" and it is not
61 deleted on system start up */
66 const char *pValue
= getenv( "TEMP" );
70 pValue
= getenv( "TMP" );
71 #if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD)
81 rtl_uString
*ustrTempPath
= NULL
;
83 rtl_string2UString( &ustrTempPath
, pValue
, strlen( pValue
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
84 OSL_ASSERT(ustrTempPath
!= NULL
);
85 error
= osl_getFileURLFromSystemPath( ustrTempPath
, pustrTempDir
);
86 rtl_uString_release( ustrTempPath
);
91 return osl_File_E_NOENT
;
94 /******************************************************************
95 * Generates a random unique file name. We're using the scheme
96 * from the standard c-lib function mkstemp to generate a more
97 * or less random unique file name
100 * receives the random name
101 ******************************************************************/
103 static const char LETTERS
[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
104 static const int COUNT_OF_LETTERS
= sizeof(LETTERS
)/sizeof(LETTERS
[0]) - 1;
106 #define RAND_NAME_LENGTH 6
108 static void osl_gen_random_name_impl_(rtl_uString
** rand_name
)
110 static uint64_t value
;
112 char buffer
[RAND_NAME_LENGTH
];
117 gettimeofday(&tv
, NULL
);
119 value
+= ((uint64_t)tv
.tv_usec
<< 16) ^ tv
.tv_sec
^ getpid();
123 for (i
= 0; i
< RAND_NAME_LENGTH
; i
++)
125 buffer
[i
] = LETTERS
[v
% COUNT_OF_LETTERS
];
126 v
/= COUNT_OF_LETTERS
;
133 RTL_TEXTENCODING_ASCII_US
,
134 OSTRING_TO_OUSTRING_CVTFLAGS
);
135 OSL_ASSERT(*rand_name
!= NULL
);
138 /*****************************************************************
140 * Either use the directory provided or the result of
141 * osl_getTempDirUrl and return it as system path and file url
142 ****************************************************************/
144 static oslFileError
osl_setup_base_directory_impl_(
145 rtl_uString
* pustrDirectoryURL
,
146 rtl_uString
** ppustr_base_dir
)
148 rtl_uString
* dir_url
= 0;
149 rtl_uString
* dir
= 0;
150 oslFileError error
= osl_File_E_None
;
152 if (pustrDirectoryURL
)
153 rtl_uString_assign(&dir_url
, pustrDirectoryURL
);
155 error
= osl_getTempDirURL(&dir_url
);
157 if (osl_File_E_None
== error
)
159 error
= osl_getSystemPathFromFileURL_Ex(dir_url
, &dir
, FURL_DENY_RELATIVE
);
160 rtl_uString_release(dir_url
);
163 if (osl_File_E_None
== error
)
165 rtl_uString_assign(ppustr_base_dir
, dir
);
166 rtl_uString_release(dir
);
172 /*****************************************************************
173 * osl_setup_createTempFile_impl
174 * validate input parameter, setup variables
175 ****************************************************************/
177 static oslFileError
osl_setup_createTempFile_impl_(
178 rtl_uString
* pustrDirectoryURL
,
179 oslFileHandle
* pHandle
,
180 rtl_uString
** ppustrTempFileURL
,
181 rtl_uString
** ppustr_base_dir
,
182 sal_Bool
* b_delete_on_close
)
184 oslFileError osl_error
;
186 OSL_PRECOND(((0 != pHandle
) || (0 != ppustrTempFileURL
)), "Invalid parameter!");
188 if ((0 == pHandle
) && (0 == ppustrTempFileURL
))
190 osl_error
= osl_File_E_INVAL
;
194 osl_error
= osl_setup_base_directory_impl_(
195 pustrDirectoryURL
, ppustr_base_dir
);
197 *b_delete_on_close
= (0 == ppustrTempFileURL
);
203 /*****************************************************************
204 * Create a unique file in the specified directory and return
206 ****************************************************************/
208 static oslFileError
osl_create_temp_file_impl_(
209 const rtl_uString
* pustr_base_directory
,
210 oslFileHandle
* file_handle
,
211 rtl_uString
** ppustr_temp_file_name
)
213 rtl_uString
* rand_name
= 0;
214 sal_uInt32 len_base_dir
= 0;
215 rtl_uString
* tmp_file_path
= 0;
216 rtl_uString
* tmp_file_url
= 0;
217 sal_Int32 capacity
= 0;
218 oslFileError osl_error
= osl_File_E_None
;
219 sal_Int32 offset_file_name
;
220 const sal_Unicode
* puchr
;
222 OSL_PRECOND(pustr_base_directory
, "Invalid Parameter");
223 OSL_PRECOND(file_handle
, "Invalid Parameter");
224 OSL_PRECOND(ppustr_temp_file_name
, "Invalid Parameter");
226 len_base_dir
= rtl_uString_getLength(pustr_base_directory
);
228 rtl_uStringbuffer_newFromStr_WithLength(
230 rtl_uString_getStr((rtl_uString
*)pustr_base_directory
),
233 rtl_uStringbuffer_ensureCapacity(
236 (len_base_dir
+ 1 + RAND_NAME_LENGTH
));
238 offset_file_name
= len_base_dir
;
240 puchr
= rtl_uString_getStr(tmp_file_path
);
242 /* ensure that the last character is a '/' */
244 if ((sal_Unicode
)'/' != puchr
[len_base_dir
- 1])
246 rtl_uStringbuffer_insert_ascii(
256 while(1) /* try until success */
258 osl_gen_random_name_impl_(&rand_name
);
260 rtl_uStringbuffer_insert(
264 rtl_uString_getStr(rand_name
),
265 rtl_uString_getLength(rand_name
));
267 osl_error
= osl_getFileURLFromSystemPath(
268 tmp_file_path
, &tmp_file_url
);
270 if (osl_File_E_None
== osl_error
)
272 /* RW permission for the user only! */
273 mode_t old_mode
= umask(077);
275 osl_error
= osl_openFile(
278 osl_File_OpenFlag_Read
|
279 osl_File_OpenFlag_Write
|
280 osl_File_OpenFlag_Create
);
285 /* in case of error osl_File_E_EXIST we simply try again else we give up */
287 if ((osl_File_E_None
== osl_error
) || (osl_error
!= osl_File_E_EXIST
))
290 rtl_uString_release(rand_name
);
293 rtl_uString_release(tmp_file_url
);
299 if (osl_File_E_None
== osl_error
)
300 rtl_uString_assign(ppustr_temp_file_name
, tmp_file_path
);
303 rtl_uString_release(tmp_file_path
);
308 /*****************************************************************
310 *****************************************************************/
312 oslFileError SAL_CALL
osl_createTempFile(
313 rtl_uString
* pustrDirectoryURL
,
314 oslFileHandle
* pHandle
,
315 rtl_uString
** ppustrTempFileURL
)
317 rtl_uString
* base_directory
= 0;
318 rtl_uString
* temp_file_name
= 0;
319 oslFileHandle temp_file_handle
;
320 sal_Bool b_delete_on_close
;
321 oslFileError osl_error
;
323 osl_error
= osl_setup_createTempFile_impl_(
330 if (osl_File_E_None
!= osl_error
)
333 osl_error
= osl_create_temp_file_impl_(
334 base_directory
, &temp_file_handle
, &temp_file_name
);
336 if (osl_File_E_None
== osl_error
)
338 rtl_uString
* temp_file_url
= 0;
340 /* assuming this works */
341 osl_getFileURLFromSystemPath(temp_file_name
, &temp_file_url
);
343 if (b_delete_on_close
)
345 osl_error
= osl_removeFile(temp_file_url
);
347 if (osl_File_E_None
== osl_error
)
348 *pHandle
= temp_file_handle
;
350 osl_closeFile(temp_file_handle
);
355 *pHandle
= temp_file_handle
;
357 osl_closeFile(temp_file_handle
);
359 rtl_uString_assign(ppustrTempFileURL
, temp_file_url
);
363 rtl_uString_release(temp_file_url
);
366 rtl_uString_release(temp_file_name
);
370 rtl_uString_release(base_directory
);