xref: /AOO41X/main/sal/osl/os2/tempfile.c (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir /*****************************************************************/
29*cdf0e10cSrcweir /* Includes                                                      */
30*cdf0e10cSrcweir /*****************************************************************/
31*cdf0e10cSrcweir 
32*cdf0e10cSrcweir #include <stdio.h>
33*cdf0e10cSrcweir #include <stdlib.h>
34*cdf0e10cSrcweir #include <sys/types.h>
35*cdf0e10cSrcweir #include <sys/stat.h>
36*cdf0e10cSrcweir #include <sys/time.h>
37*cdf0e10cSrcweir #include "system.h"
38*cdf0e10cSrcweir #include <osl/file.h>
39*cdf0e10cSrcweir #include <osl/thread.h>
40*cdf0e10cSrcweir #include <rtl/ustrbuf.h>
41*cdf0e10cSrcweir #include <osl/diagnose.h>
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #ifndef _FILE_URL_H_
44*cdf0e10cSrcweir #include "file_url.h"
45*cdf0e10cSrcweir #endif
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir /*****************************************************************/
48*cdf0e10cSrcweir /* osl_getTempFirURL                                             */
49*cdf0e10cSrcweir /*****************************************************************/
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
52*cdf0e10cSrcweir {
53*cdf0e10cSrcweir     const char *pValue = getenv( "TEMP" );
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir     if ( !pValue )
56*cdf0e10cSrcweir 	{
57*cdf0e10cSrcweir         pValue = getenv( "TMP" );
58*cdf0e10cSrcweir #if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD) || defined (MACOSX)
59*cdf0e10cSrcweir 		if ( !pValue )
60*cdf0e10cSrcweir 			pValue = P_tmpdir;
61*cdf0e10cSrcweir #endif
62*cdf0e10cSrcweir 	}
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir 	if ( pValue )
65*cdf0e10cSrcweir 	{
66*cdf0e10cSrcweir 		oslFileError error;
67*cdf0e10cSrcweir 		rtl_uString	*ustrTempPath = NULL;
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir 		rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
70*cdf0e10cSrcweir         OSL_ASSERT(ustrTempPath != NULL);
71*cdf0e10cSrcweir 		error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
72*cdf0e10cSrcweir 		rtl_uString_release( ustrTempPath );
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir 		return error;
75*cdf0e10cSrcweir 	}
76*cdf0e10cSrcweir 	else
77*cdf0e10cSrcweir 		return osl_File_E_NOENT;
78*cdf0e10cSrcweir }
79*cdf0e10cSrcweir 
80*cdf0e10cSrcweir /******************************************************************
81*cdf0e10cSrcweir  * Generates a random unique file name. We're using the scheme
82*cdf0e10cSrcweir  * from the standard c-lib function mkstemp to generate a more
83*cdf0e10cSrcweir  * or less random unique file name
84*cdf0e10cSrcweir  *
85*cdf0e10cSrcweir  * @param rand_name
86*cdf0e10cSrcweir  *        receives the random name
87*cdf0e10cSrcweir  ******************************************************************/
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir static const char LETTERS[]        = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
90*cdf0e10cSrcweir static const int  COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir #define RAND_NAME_LENGTH 6
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir static void osl_gen_random_name_impl_(rtl_uString** rand_name)
95*cdf0e10cSrcweir {
96*cdf0e10cSrcweir 	static uint64_t value;
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir 	char     buffer[RAND_NAME_LENGTH];
99*cdf0e10cSrcweir 	struct   timeval tv;
100*cdf0e10cSrcweir 	uint64_t v;
101*cdf0e10cSrcweir 	int      i;
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir 	gettimeofday(&tv, NULL);
104*cdf0e10cSrcweir 
105*cdf0e10cSrcweir 	value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
106*cdf0e10cSrcweir 
107*cdf0e10cSrcweir 	v = value;
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir 	for (i = 0; i < RAND_NAME_LENGTH; i++)
110*cdf0e10cSrcweir 	{
111*cdf0e10cSrcweir 		buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
112*cdf0e10cSrcweir 		v        /= COUNT_OF_LETTERS;
113*cdf0e10cSrcweir 	}
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir 	rtl_string2UString(
116*cdf0e10cSrcweir 			rand_name,
117*cdf0e10cSrcweir 			buffer,
118*cdf0e10cSrcweir 			RAND_NAME_LENGTH,
119*cdf0e10cSrcweir 			RTL_TEXTENCODING_ASCII_US,
120*cdf0e10cSrcweir 			OSTRING_TO_OUSTRING_CVTFLAGS);
121*cdf0e10cSrcweir     OSL_ASSERT(*rand_name != NULL);
122*cdf0e10cSrcweir }
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir /*****************************************************************
125*cdf0e10cSrcweir  * Helper function
126*cdf0e10cSrcweir  * Either use the directory provided or the result of
127*cdf0e10cSrcweir  * osl_getTempDirUrl and return it as system path and file url
128*cdf0e10cSrcweir  ****************************************************************/
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir static oslFileError osl_setup_base_directory_impl_(
131*cdf0e10cSrcweir 	rtl_uString*  pustrDirectoryURL,
132*cdf0e10cSrcweir 	rtl_uString** ppustr_base_dir)
133*cdf0e10cSrcweir {
134*cdf0e10cSrcweir 	rtl_uString* dir_url = 0;
135*cdf0e10cSrcweir 	rtl_uString* dir     = 0;
136*cdf0e10cSrcweir     oslFileError error   = osl_File_E_None;
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir 	if (pustrDirectoryURL)
139*cdf0e10cSrcweir 		rtl_uString_assign(&dir_url, pustrDirectoryURL);
140*cdf0e10cSrcweir 	else
141*cdf0e10cSrcweir 		error = osl_getTempDirURL(&dir_url);
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir     if (osl_File_E_None == error)
144*cdf0e10cSrcweir 	{
145*cdf0e10cSrcweir         error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
146*cdf0e10cSrcweir 		rtl_uString_release(dir_url);
147*cdf0e10cSrcweir 	}
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir 	if (osl_File_E_None == error)
150*cdf0e10cSrcweir 	{
151*cdf0e10cSrcweir 		rtl_uString_assign(ppustr_base_dir, dir);
152*cdf0e10cSrcweir 		rtl_uString_release(dir);
153*cdf0e10cSrcweir 	}
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir     return error;
156*cdf0e10cSrcweir }
157*cdf0e10cSrcweir 
158*cdf0e10cSrcweir /*****************************************************************
159*cdf0e10cSrcweir  * osl_setup_createTempFile_impl
160*cdf0e10cSrcweir  * validate input parameter, setup variables
161*cdf0e10cSrcweir  ****************************************************************/
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir  static oslFileError osl_setup_createTempFile_impl_(
164*cdf0e10cSrcweir  	rtl_uString*   pustrDirectoryURL,
165*cdf0e10cSrcweir 	oslFileHandle* pHandle,
166*cdf0e10cSrcweir 	rtl_uString**  ppustrTempFileURL,
167*cdf0e10cSrcweir 	rtl_uString**  ppustr_base_dir,
168*cdf0e10cSrcweir 	sal_Bool*	   b_delete_on_close)
169*cdf0e10cSrcweir  {
170*cdf0e10cSrcweir  	oslFileError osl_error;
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir 	OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir 	if ((0 == pHandle) && (0 == ppustrTempFileURL))
175*cdf0e10cSrcweir 	{
176*cdf0e10cSrcweir 		osl_error = osl_File_E_INVAL;
177*cdf0e10cSrcweir 	}
178*cdf0e10cSrcweir 	else
179*cdf0e10cSrcweir 	{
180*cdf0e10cSrcweir 		osl_error = osl_setup_base_directory_impl_(
181*cdf0e10cSrcweir 			pustrDirectoryURL, ppustr_base_dir);
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir 		*b_delete_on_close = (0 == ppustrTempFileURL);
184*cdf0e10cSrcweir 	}
185*cdf0e10cSrcweir 
186*cdf0e10cSrcweir 	return osl_error;
187*cdf0e10cSrcweir  }
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir /*****************************************************************
190*cdf0e10cSrcweir  * Create a unique file in the specified directory and return
191*cdf0e10cSrcweir  * it's name
192*cdf0e10cSrcweir  ****************************************************************/
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir static oslFileError osl_create_temp_file_impl_(
195*cdf0e10cSrcweir 	const rtl_uString* pustr_base_directory,
196*cdf0e10cSrcweir 	oslFileHandle* file_handle,
197*cdf0e10cSrcweir 	rtl_uString** ppustr_temp_file_name)
198*cdf0e10cSrcweir {
199*cdf0e10cSrcweir 	rtl_uString*        rand_name        = 0;
200*cdf0e10cSrcweir 	sal_uInt32          len_base_dir     = 0;
201*cdf0e10cSrcweir 	rtl_uString*        tmp_file_path    = 0;
202*cdf0e10cSrcweir 	rtl_uString*        tmp_file_url     = 0;
203*cdf0e10cSrcweir 	sal_Int32           capacity         = 0;
204*cdf0e10cSrcweir 	oslFileError        osl_error        = osl_File_E_None;
205*cdf0e10cSrcweir 	sal_Int32           offset_file_name;
206*cdf0e10cSrcweir 	const sal_Unicode*  puchr;
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir 	OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
209*cdf0e10cSrcweir 	OSL_PRECOND(file_handle, "Invalid Parameter");
210*cdf0e10cSrcweir 	OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir 	len_base_dir = rtl_uString_getLength(pustr_base_directory);
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir 	rtl_uStringbuffer_newFromStr_WithLength(
215*cdf0e10cSrcweir 		&tmp_file_path,
216*cdf0e10cSrcweir 		rtl_uString_getStr((rtl_uString*)pustr_base_directory),
217*cdf0e10cSrcweir 		len_base_dir);
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir 	rtl_uStringbuffer_ensureCapacity(
220*cdf0e10cSrcweir 		&tmp_file_path,
221*cdf0e10cSrcweir 		&capacity,
222*cdf0e10cSrcweir 		(len_base_dir + 1 + RAND_NAME_LENGTH));
223*cdf0e10cSrcweir 
224*cdf0e10cSrcweir 	offset_file_name = len_base_dir;
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir 	puchr = rtl_uString_getStr(tmp_file_path);
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir 	/* ensure that the last character is a '\' */
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir 	if ((sal_Unicode)'\\' != puchr[len_base_dir - 1])
231*cdf0e10cSrcweir 	{
232*cdf0e10cSrcweir 		rtl_uStringbuffer_insert_ascii(
233*cdf0e10cSrcweir 			&tmp_file_path,
234*cdf0e10cSrcweir 			&capacity,
235*cdf0e10cSrcweir 			len_base_dir,
236*cdf0e10cSrcweir 			"\\",
237*cdf0e10cSrcweir 			1);
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir 		offset_file_name++;
240*cdf0e10cSrcweir 	}
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir 	while(1) /* try until success */
243*cdf0e10cSrcweir 	{
244*cdf0e10cSrcweir 		osl_gen_random_name_impl_(&rand_name);
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir 		rtl_uStringbuffer_insert(
247*cdf0e10cSrcweir 			&tmp_file_path,
248*cdf0e10cSrcweir 			&capacity,
249*cdf0e10cSrcweir 			offset_file_name,
250*cdf0e10cSrcweir 			rtl_uString_getStr(rand_name),
251*cdf0e10cSrcweir 			rtl_uString_getLength(rand_name));
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 		osl_error = osl_getFileURLFromSystemPath(
254*cdf0e10cSrcweir 		    tmp_file_path, &tmp_file_url);
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir 		if (osl_File_E_None == osl_error)
257*cdf0e10cSrcweir 		{
258*cdf0e10cSrcweir 		    /* RW permission for the user only! */
259*cdf0e10cSrcweir 		    mode_t old_mode = umask(077);
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir 		    osl_error = osl_openFile(
262*cdf0e10cSrcweir 			    tmp_file_url,
263*cdf0e10cSrcweir 			    file_handle,
264*cdf0e10cSrcweir 			    osl_File_OpenFlag_Read |
265*cdf0e10cSrcweir 			    osl_File_OpenFlag_Write |
266*cdf0e10cSrcweir 			    osl_File_OpenFlag_Create);
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir 			umask(old_mode);
269*cdf0e10cSrcweir 		}
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir 		/* in case of error osl_File_E_EXIST we simply try again else we give up */
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir 		if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
274*cdf0e10cSrcweir 		{
275*cdf0e10cSrcweir 			if (rand_name)
276*cdf0e10cSrcweir 				rtl_uString_release(rand_name);
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir 			if (tmp_file_url)
279*cdf0e10cSrcweir 				rtl_uString_release(tmp_file_url);
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir 			break;
282*cdf0e10cSrcweir 		}
283*cdf0e10cSrcweir 	} /* while(1) */
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir 	if (osl_File_E_None == osl_error)
286*cdf0e10cSrcweir 		rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
287*cdf0e10cSrcweir 
288*cdf0e10cSrcweir 	if (tmp_file_path)
289*cdf0e10cSrcweir 		rtl_uString_release(tmp_file_path);
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir 	return osl_error;
292*cdf0e10cSrcweir }
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir /*****************************************************************
295*cdf0e10cSrcweir  * osl_createTempFile
296*cdf0e10cSrcweir  *****************************************************************/
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir oslFileError SAL_CALL osl_createTempFile(
299*cdf0e10cSrcweir 	rtl_uString*   pustrDirectoryURL,
300*cdf0e10cSrcweir 	oslFileHandle* pHandle,
301*cdf0e10cSrcweir 	rtl_uString**  ppustrTempFileURL)
302*cdf0e10cSrcweir {
303*cdf0e10cSrcweir 	rtl_uString*  base_directory     = 0;
304*cdf0e10cSrcweir 	rtl_uString*  temp_file_name     = 0;
305*cdf0e10cSrcweir 	oslFileHandle temp_file_handle;
306*cdf0e10cSrcweir 	sal_Bool      b_delete_on_close;
307*cdf0e10cSrcweir 	oslFileError  osl_error;
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir 	osl_error = osl_setup_createTempFile_impl_(
310*cdf0e10cSrcweir 		pustrDirectoryURL,
311*cdf0e10cSrcweir 		pHandle,
312*cdf0e10cSrcweir 		ppustrTempFileURL,
313*cdf0e10cSrcweir 		&base_directory,
314*cdf0e10cSrcweir 		&b_delete_on_close);
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir 	if (osl_File_E_None != osl_error)
317*cdf0e10cSrcweir 		return osl_error;
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir 	osl_error = osl_create_temp_file_impl_(
320*cdf0e10cSrcweir 	    base_directory, &temp_file_handle, &temp_file_name);
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir 	if (osl_File_E_None == osl_error)
323*cdf0e10cSrcweir 	{
324*cdf0e10cSrcweir 		rtl_uString* temp_file_url = 0;
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir 		/* assuming this works */
327*cdf0e10cSrcweir 		osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir 		if (b_delete_on_close)
330*cdf0e10cSrcweir 		{
331*cdf0e10cSrcweir 			osl_error = osl_removeFile(temp_file_url);
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir 			if (osl_File_E_None == osl_error)
334*cdf0e10cSrcweir 				*pHandle = temp_file_handle;
335*cdf0e10cSrcweir 			else
336*cdf0e10cSrcweir 				osl_closeFile(temp_file_handle);
337*cdf0e10cSrcweir 		}
338*cdf0e10cSrcweir 		else
339*cdf0e10cSrcweir 		{
340*cdf0e10cSrcweir 			if (pHandle)
341*cdf0e10cSrcweir 				*pHandle = temp_file_handle;
342*cdf0e10cSrcweir 			else
343*cdf0e10cSrcweir 				osl_closeFile(temp_file_handle);
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 			rtl_uString_assign(ppustrTempFileURL, temp_file_url);
346*cdf0e10cSrcweir         }
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir 		if (temp_file_url)
349*cdf0e10cSrcweir 			rtl_uString_release(temp_file_url);
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir         if (temp_file_name)
352*cdf0e10cSrcweir             rtl_uString_release(temp_file_name);
353*cdf0e10cSrcweir 	}
354*cdf0e10cSrcweir 
355*cdf0e10cSrcweir     if (base_directory)
356*cdf0e10cSrcweir     	rtl_uString_release(base_directory);
357*cdf0e10cSrcweir 
358*cdf0e10cSrcweir     return osl_error;
359*cdf0e10cSrcweir }
360