xref: /trunk/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