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
)
56 const char *pValue
= getenv( "TEMP" );
60 pValue
= getenv( "TMP" );
61 #if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD) || defined (MACOSX)
70 rtl_uString
*ustrTempPath
= NULL
;
72 rtl_string2UString( &ustrTempPath
, pValue
, strlen( pValue
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
73 OSL_ASSERT(ustrTempPath
!= NULL
);
74 error
= osl_getFileURLFromSystemPath( ustrTempPath
, pustrTempDir
);
75 rtl_uString_release( ustrTempPath
);
80 return osl_File_E_NOENT
;
83 /******************************************************************
84 * Generates a random unique file name. We're using the scheme
85 * from the standard c-lib function mkstemp to generate a more
86 * or less random unique file name
89 * receives the random name
90 ******************************************************************/
92 static const char LETTERS
[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
93 static const int COUNT_OF_LETTERS
= sizeof(LETTERS
)/sizeof(LETTERS
[0]) - 1;
95 #define RAND_NAME_LENGTH 6
97 static void osl_gen_random_name_impl_(rtl_uString
** rand_name
)
99 static uint64_t value
;
101 char buffer
[RAND_NAME_LENGTH
];
106 gettimeofday(&tv
, NULL
);
108 value
+= ((uint64_t)tv
.tv_usec
<< 16) ^ tv
.tv_sec
^ getpid();
112 for (i
= 0; i
< RAND_NAME_LENGTH
; i
++)
114 buffer
[i
] = LETTERS
[v
% COUNT_OF_LETTERS
];
115 v
/= COUNT_OF_LETTERS
;
122 RTL_TEXTENCODING_ASCII_US
,
123 OSTRING_TO_OUSTRING_CVTFLAGS
);
124 OSL_ASSERT(*rand_name
!= NULL
);
127 /*****************************************************************
129 * Either use the directory provided or the result of
130 * osl_getTempDirUrl and return it as system path and file url
131 ****************************************************************/
133 static oslFileError
osl_setup_base_directory_impl_(
134 rtl_uString
* pustrDirectoryURL
,
135 rtl_uString
** ppustr_base_dir
)
137 rtl_uString
* dir_url
= 0;
138 rtl_uString
* dir
= 0;
139 oslFileError error
= osl_File_E_None
;
141 if (pustrDirectoryURL
)
142 rtl_uString_assign(&dir_url
, pustrDirectoryURL
);
144 error
= osl_getTempDirURL(&dir_url
);
146 if (osl_File_E_None
== error
)
148 error
= osl_getSystemPathFromFileURL_Ex(dir_url
, &dir
, FURL_DENY_RELATIVE
);
149 rtl_uString_release(dir_url
);
152 if (osl_File_E_None
== error
)
154 rtl_uString_assign(ppustr_base_dir
, dir
);
155 rtl_uString_release(dir
);
161 /*****************************************************************
162 * osl_setup_createTempFile_impl
163 * validate input parameter, setup variables
164 ****************************************************************/
166 static oslFileError
osl_setup_createTempFile_impl_(
167 rtl_uString
* pustrDirectoryURL
,
168 oslFileHandle
* pHandle
,
169 rtl_uString
** ppustrTempFileURL
,
170 rtl_uString
** ppustr_base_dir
,
171 sal_Bool
* b_delete_on_close
)
173 oslFileError osl_error
;
175 OSL_PRECOND(((0 != pHandle
) || (0 != ppustrTempFileURL
)), "Invalid parameter!");
177 if ((0 == pHandle
) && (0 == ppustrTempFileURL
))
179 osl_error
= osl_File_E_INVAL
;
183 osl_error
= osl_setup_base_directory_impl_(
184 pustrDirectoryURL
, ppustr_base_dir
);
186 *b_delete_on_close
= (0 == ppustrTempFileURL
);
192 /*****************************************************************
193 * Create a unique file in the specified directory and return
195 ****************************************************************/
197 static oslFileError
osl_create_temp_file_impl_(
198 const rtl_uString
* pustr_base_directory
,
199 oslFileHandle
* file_handle
,
200 rtl_uString
** ppustr_temp_file_name
)
202 rtl_uString
* rand_name
= 0;
203 sal_uInt32 len_base_dir
= 0;
204 rtl_uString
* tmp_file_path
= 0;
205 rtl_uString
* tmp_file_url
= 0;
206 sal_Int32 capacity
= 0;
207 oslFileError osl_error
= osl_File_E_None
;
208 sal_Int32 offset_file_name
;
209 const sal_Unicode
* puchr
;
211 OSL_PRECOND(pustr_base_directory
, "Invalid Parameter");
212 OSL_PRECOND(file_handle
, "Invalid Parameter");
213 OSL_PRECOND(ppustr_temp_file_name
, "Invalid Parameter");
215 len_base_dir
= rtl_uString_getLength(pustr_base_directory
);
217 rtl_uStringbuffer_newFromStr_WithLength(
219 rtl_uString_getStr((rtl_uString
*)pustr_base_directory
),
222 rtl_uStringbuffer_ensureCapacity(
225 (len_base_dir
+ 1 + RAND_NAME_LENGTH
));
227 offset_file_name
= len_base_dir
;
229 puchr
= rtl_uString_getStr(tmp_file_path
);
231 /* ensure that the last character is a '\' */
233 if ((sal_Unicode
)'\\' != puchr
[len_base_dir
- 1])
235 rtl_uStringbuffer_insert_ascii(
245 while(1) /* try until success */
247 osl_gen_random_name_impl_(&rand_name
);
249 rtl_uStringbuffer_insert(
253 rtl_uString_getStr(rand_name
),
254 rtl_uString_getLength(rand_name
));
256 osl_error
= osl_getFileURLFromSystemPath(
257 tmp_file_path
, &tmp_file_url
);
259 if (osl_File_E_None
== osl_error
)
261 /* RW permission for the user only! */
262 mode_t old_mode
= umask(077);
264 osl_error
= osl_openFile(
267 osl_File_OpenFlag_Read
|
268 osl_File_OpenFlag_Write
|
269 osl_File_OpenFlag_Create
);
274 /* in case of error osl_File_E_EXIST we simply try again else we give up */
276 if ((osl_File_E_None
== osl_error
) || (osl_error
!= osl_File_E_EXIST
))
279 rtl_uString_release(rand_name
);
282 rtl_uString_release(tmp_file_url
);
288 if (osl_File_E_None
== osl_error
)
289 rtl_uString_assign(ppustr_temp_file_name
, tmp_file_path
);
292 rtl_uString_release(tmp_file_path
);
297 /*****************************************************************
299 *****************************************************************/
301 oslFileError SAL_CALL
osl_createTempFile(
302 rtl_uString
* pustrDirectoryURL
,
303 oslFileHandle
* pHandle
,
304 rtl_uString
** ppustrTempFileURL
)
306 rtl_uString
* base_directory
= 0;
307 rtl_uString
* temp_file_name
= 0;
308 oslFileHandle temp_file_handle
;
309 sal_Bool b_delete_on_close
;
310 oslFileError osl_error
;
312 osl_error
= osl_setup_createTempFile_impl_(
319 if (osl_File_E_None
!= osl_error
)
322 osl_error
= osl_create_temp_file_impl_(
323 base_directory
, &temp_file_handle
, &temp_file_name
);
325 if (osl_File_E_None
== osl_error
)
327 rtl_uString
* temp_file_url
= 0;
329 /* assuming this works */
330 osl_getFileURLFromSystemPath(temp_file_name
, &temp_file_url
);
332 if (b_delete_on_close
)
334 osl_error
= osl_removeFile(temp_file_url
);
336 if (osl_File_E_None
== osl_error
)
337 *pHandle
= temp_file_handle
;
339 osl_closeFile(temp_file_handle
);
344 *pHandle
= temp_file_handle
;
346 osl_closeFile(temp_file_handle
);
348 rtl_uString_assign(ppustrTempFileURL
, temp_file_url
);
352 rtl_uString_release(temp_file_url
);
355 rtl_uString_release(temp_file_name
);
359 rtl_uString_release(base_directory
);