xref: /AOO41X/main/tools/source/fsys/tempfile.cxx (revision 24c56ab9f1bd1305754aa2f564704f38ff57627e)
189b56da7SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
389b56da7SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
489b56da7SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
589b56da7SAndrew Rist  * distributed with this work for additional information
689b56da7SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
789b56da7SAndrew Rist  * to you under the Apache License, Version 2.0 (the
889b56da7SAndrew Rist  * "License"); you may not use this file except in compliance
989b56da7SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
1189b56da7SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
1389b56da7SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1489b56da7SAndrew Rist  * software distributed under the License is distributed on an
1589b56da7SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1689b56da7SAndrew Rist  * KIND, either express or implied.  See the License for the
1789b56da7SAndrew Rist  * specific language governing permissions and limitations
1889b56da7SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
2089b56da7SAndrew Rist  *************************************************************/
2189b56da7SAndrew Rist 
2289b56da7SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_tools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <tools/tempfile.hxx>
28cdf0e10cSrcweir #include "comdep.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <rtl/ustring.hxx>
31cdf0e10cSrcweir #include <osl/file.hxx>
32cdf0e10cSrcweir #include <rtl/instance.hxx>
33cdf0e10cSrcweir #include <tools/time.hxx>
34cdf0e10cSrcweir #include <tools/debug.hxx>
35cdf0e10cSrcweir #include <stdio.h>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir #ifdef UNX
38cdf0e10cSrcweir #define _MAX_PATH 260
39cdf0e10cSrcweir #endif
40cdf0e10cSrcweir 
41cdf0e10cSrcweir using namespace osl;
42cdf0e10cSrcweir 
43cdf0e10cSrcweir namespace { struct TempNameBase_Impl : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; }
44cdf0e10cSrcweir 
45cdf0e10cSrcweir struct TempFile_Impl
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     String      aName;
48cdf0e10cSrcweir     sal_Bool    bIsDirectory;
49cdf0e10cSrcweir };
50cdf0e10cSrcweir 
GetSystemTempDir_Impl()51cdf0e10cSrcweir String GetSystemTempDir_Impl()
52cdf0e10cSrcweir {
53cdf0e10cSrcweir     char sBuf[_MAX_PATH];
54cdf0e10cSrcweir     const char *pDir = TempDirImpl(sBuf);
55cdf0e10cSrcweir 
56cdf0e10cSrcweir 	::rtl::OString aTmpA( pDir );
57cdf0e10cSrcweir     ::rtl::OUString aTmp = ::rtl::OStringToOUString( aTmpA, osl_getThreadTextEncoding() );
58cdf0e10cSrcweir     rtl::OUString aRet;
59cdf0e10cSrcweir     FileBase::getFileURLFromSystemPath( aTmp, aRet );
60cdf0e10cSrcweir     String aName = aRet;
61cdf0e10cSrcweir     if( aName.GetChar(aName.Len()-1) != '/' )
62cdf0e10cSrcweir         aName += '/';
63cdf0e10cSrcweir     return aName;
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
66cdf0e10cSrcweir #define TMPNAME_SIZE  ( 1 + 5 + 5 + 4 + 1 )
ConstructTempDir_Impl(const String * pParent)67cdf0e10cSrcweir String ConstructTempDir_Impl( const String* pParent )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir     String aName;
70cdf0e10cSrcweir     if ( pParent && pParent->Len() )
71cdf0e10cSrcweir     {
72cdf0e10cSrcweir         // if parent given try to use it
73cdf0e10cSrcweir         rtl::OUString aTmp( *pParent );
74cdf0e10cSrcweir         rtl::OUString aRet;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir         // test for valid filename
77cdf0e10cSrcweir         {
78cdf0e10cSrcweir             ::osl::DirectoryItem aItem;
79cdf0e10cSrcweir             sal_Int32 i = aRet.getLength();
80cdf0e10cSrcweir             if ( aRet[i-1] == '/' )
81cdf0e10cSrcweir                 i--;
82cdf0e10cSrcweir 
83*24c56ab9SHerbert Dürr             if ( DirectoryItem::get( ::rtl::OUString( aRet.getStr(), i ), aItem ) == FileBase::E_None )
84cdf0e10cSrcweir                 aName = aRet;
85cdf0e10cSrcweir         }
86cdf0e10cSrcweir     }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     if ( !aName.Len() )
89cdf0e10cSrcweir     {
90cdf0e10cSrcweir         // if no parent or invalid parent : use system directory
91cdf0e10cSrcweir 	::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
92cdf0e10cSrcweir         if ( !rTempNameBase_Impl.getLength() )
93cdf0e10cSrcweir             rTempNameBase_Impl = GetSystemTempDir_Impl();
94cdf0e10cSrcweir         aName = rTempNameBase_Impl;
95cdf0e10cSrcweir     }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir     // Make sure that directory ends with a separator
98cdf0e10cSrcweir     xub_StrLen i = aName.Len();
99cdf0e10cSrcweir     if( i>0 && aName.GetChar(i-1) != '/' )
100cdf0e10cSrcweir         aName += '/';
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     return aName;
103cdf0e10cSrcweir }
104cdf0e10cSrcweir 
CreateTempName_Impl(String & rName,sal_Bool bKeep,sal_Bool bDir=sal_True)105cdf0e10cSrcweir void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
106cdf0e10cSrcweir {
107cdf0e10cSrcweir     // add a suitable tempname
108cdf0e10cSrcweir     // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
109cdf0e10cSrcweir 	// ER 13.07.00  why not radix 36 [0-9A-Z] ?!?
110cdf0e10cSrcweir 	const unsigned nRadix = 26;
111cdf0e10cSrcweir     String aName( rName );
112cdf0e10cSrcweir     aName += String::CreateFromAscii( "sv" );
113cdf0e10cSrcweir 
114cdf0e10cSrcweir     rName.Erase();
115cdf0e10cSrcweir     static unsigned long u = Time::GetSystemTicks();
116cdf0e10cSrcweir     for ( unsigned long nOld = u; ++u != nOld; )
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         u %= (nRadix*nRadix*nRadix);
119cdf0e10cSrcweir         String aTmp( aName );
120cdf0e10cSrcweir         aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix );
121cdf0e10cSrcweir         aTmp += String::CreateFromAscii( ".tmp" );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir         if ( bDir )
124cdf0e10cSrcweir         {
125cdf0e10cSrcweir             FileBase::RC err = Directory::create( aTmp );
126cdf0e10cSrcweir             if (  err == FileBase::E_None )
127cdf0e10cSrcweir             {
128cdf0e10cSrcweir                 // !bKeep: only for creating a name, not a file or directory
129cdf0e10cSrcweir                 if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
130cdf0e10cSrcweir                     rName = aTmp;
131cdf0e10cSrcweir                 break;
132cdf0e10cSrcweir             }
133cdf0e10cSrcweir             else if ( err != FileBase::E_EXIST )
134cdf0e10cSrcweir             {
135cdf0e10cSrcweir                 // if f.e. name contains invalid chars stop trying to create dirs
136cdf0e10cSrcweir                 break;
137cdf0e10cSrcweir             }
138cdf0e10cSrcweir         }
139cdf0e10cSrcweir         else
140cdf0e10cSrcweir         {
141cdf0e10cSrcweir             DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
142cdf0e10cSrcweir             File aFile( aTmp );
143cdf0e10cSrcweir             FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
144cdf0e10cSrcweir             if (  err == FileBase::E_None )
145cdf0e10cSrcweir             {
146cdf0e10cSrcweir                 rName = aTmp;
147cdf0e10cSrcweir                 aFile.close();
148cdf0e10cSrcweir                 break;
149cdf0e10cSrcweir             }
150cdf0e10cSrcweir             else if ( err != FileBase::E_EXIST )
151cdf0e10cSrcweir             {
152cdf0e10cSrcweir                  // if f.e. name contains invalid chars stop trying to create files
153cdf0e10cSrcweir                  break;
154cdf0e10cSrcweir             }
155cdf0e10cSrcweir         }
156cdf0e10cSrcweir     }
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
CreateTempName(const String * pParent)159cdf0e10cSrcweir String TempFile::CreateTempName( const String* pParent )
160cdf0e10cSrcweir {
161cdf0e10cSrcweir     // get correct directory
162cdf0e10cSrcweir     String aName = ConstructTempDir_Impl( pParent );
163cdf0e10cSrcweir 
164cdf0e10cSrcweir     // get TempFile name with default naming scheme
165cdf0e10cSrcweir     CreateTempName_Impl( aName, sal_False );
166cdf0e10cSrcweir 
167cdf0e10cSrcweir     // convert to file URL
168cdf0e10cSrcweir     rtl::OUString aTmp;
169cdf0e10cSrcweir     if ( aName.Len() )
170cdf0e10cSrcweir 		aTmp = aName;
171cdf0e10cSrcweir     return aTmp;
172cdf0e10cSrcweir }
173cdf0e10cSrcweir 
TempFile(const String * pParent,sal_Bool bDirectory)174cdf0e10cSrcweir TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
175cdf0e10cSrcweir     : pImp( new TempFile_Impl )
176cdf0e10cSrcweir     , bKillingFileEnabled( sal_False )
177cdf0e10cSrcweir {
178cdf0e10cSrcweir     pImp->bIsDirectory = bDirectory;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     // get correct directory
181cdf0e10cSrcweir     pImp->aName = ConstructTempDir_Impl( pParent );
182cdf0e10cSrcweir 
183cdf0e10cSrcweir     // get TempFile with default naming scheme
184cdf0e10cSrcweir     CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
185cdf0e10cSrcweir }
186cdf0e10cSrcweir 
TempFile(const String & rLeadingChars,const String * pExtension,const String * pParent,sal_Bool bDirectory)187cdf0e10cSrcweir TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory )
188cdf0e10cSrcweir     : pImp( new TempFile_Impl )
189cdf0e10cSrcweir     , bKillingFileEnabled( sal_False )
190cdf0e10cSrcweir {
191cdf0e10cSrcweir     pImp->bIsDirectory = bDirectory;
192cdf0e10cSrcweir 
193cdf0e10cSrcweir     // get correct directory
194cdf0e10cSrcweir     String aName = ConstructTempDir_Impl( pParent );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir     // now use special naming scheme ( name takes leading chars and an index counting up from zero
197cdf0e10cSrcweir     aName += rLeadingChars;
198cdf0e10cSrcweir     for ( sal_Int32 i=0;; i++ )
199cdf0e10cSrcweir     {
200cdf0e10cSrcweir         String aTmp( aName );
201cdf0e10cSrcweir         aTmp += String::CreateFromInt32( i );
202cdf0e10cSrcweir         if ( pExtension )
203cdf0e10cSrcweir             aTmp += *pExtension;
204cdf0e10cSrcweir         else
205cdf0e10cSrcweir             aTmp += String::CreateFromAscii( ".tmp" );
206cdf0e10cSrcweir         if ( bDirectory )
207cdf0e10cSrcweir         {
208cdf0e10cSrcweir             FileBase::RC err = Directory::create( aTmp );
209cdf0e10cSrcweir             if ( err == FileBase::E_None )
210cdf0e10cSrcweir             {
211cdf0e10cSrcweir                 pImp->aName = aTmp;
212cdf0e10cSrcweir                 break;
213cdf0e10cSrcweir             }
214cdf0e10cSrcweir             else if ( err != FileBase::E_EXIST )
215cdf0e10cSrcweir                 // if f.e. name contains invalid chars stop trying to create dirs
216cdf0e10cSrcweir                 break;
217cdf0e10cSrcweir         }
218cdf0e10cSrcweir         else
219cdf0e10cSrcweir         {
220cdf0e10cSrcweir             File aFile( aTmp );
221cdf0e10cSrcweir             FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
222cdf0e10cSrcweir             if ( err == FileBase::E_None )
223cdf0e10cSrcweir             {
224cdf0e10cSrcweir                 pImp->aName = aTmp;
225cdf0e10cSrcweir                 aFile.close();
226cdf0e10cSrcweir                 break;
227cdf0e10cSrcweir             }
228cdf0e10cSrcweir             else if ( err != FileBase::E_EXIST )
229cdf0e10cSrcweir                 // if f.e. name contains invalid chars stop trying to create dirs
230cdf0e10cSrcweir                 break;
231cdf0e10cSrcweir         }
232cdf0e10cSrcweir     }
233cdf0e10cSrcweir }
234cdf0e10cSrcweir 
~TempFile()235cdf0e10cSrcweir TempFile::~TempFile()
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     if ( bKillingFileEnabled )
238cdf0e10cSrcweir     {
239cdf0e10cSrcweir         if ( pImp->bIsDirectory )
240cdf0e10cSrcweir         {
241cdf0e10cSrcweir             // at the moment no recursiv algorithm present
242cdf0e10cSrcweir             Directory::remove( pImp->aName );
243cdf0e10cSrcweir         }
244cdf0e10cSrcweir         else
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             File::remove( pImp->aName );
247cdf0e10cSrcweir         }
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     delete pImp;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
IsValid() const253cdf0e10cSrcweir sal_Bool TempFile::IsValid() const
254cdf0e10cSrcweir {
255cdf0e10cSrcweir     return pImp->aName.Len() != 0;
256cdf0e10cSrcweir }
257cdf0e10cSrcweir 
GetName() const258cdf0e10cSrcweir String TempFile::GetName() const
259cdf0e10cSrcweir {
260cdf0e10cSrcweir     rtl::OUString aTmp;
261cdf0e10cSrcweir 	aTmp = pImp->aName;
262cdf0e10cSrcweir     return aTmp;
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
SetTempNameBaseDirectory(const String & rBaseName)265cdf0e10cSrcweir String TempFile::SetTempNameBaseDirectory( const String &rBaseName )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     String aName( rBaseName );
268cdf0e10cSrcweir 
269cdf0e10cSrcweir     ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     FileBase::RC err= Directory::create( aName );
272cdf0e10cSrcweir     if ( err == FileBase::E_None || err == FileBase::E_EXIST )
273cdf0e10cSrcweir     {
274cdf0e10cSrcweir         rTempNameBase_Impl  = aName;
275cdf0e10cSrcweir         rTempNameBase_Impl += String( '/' );
276cdf0e10cSrcweir 
277cdf0e10cSrcweir         TempFile aBase( NULL, sal_True );
278cdf0e10cSrcweir         if ( aBase.IsValid() )
279cdf0e10cSrcweir             rTempNameBase_Impl = aBase.pImp->aName;
280cdf0e10cSrcweir     }
281cdf0e10cSrcweir 
282cdf0e10cSrcweir     rtl::OUString aTmp;
283cdf0e10cSrcweir     aTmp = rTempNameBase_Impl;
284cdf0e10cSrcweir     return aTmp;
285cdf0e10cSrcweir }
286cdf0e10cSrcweir 
GetTempNameBaseDirectory()287cdf0e10cSrcweir String TempFile::GetTempNameBaseDirectory()
288cdf0e10cSrcweir {
289cdf0e10cSrcweir     ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
290cdf0e10cSrcweir     if ( !rTempNameBase_Impl.getLength() )
291cdf0e10cSrcweir         rTempNameBase_Impl = GetSystemTempDir_Impl();
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     rtl::OUString aTmp;
294cdf0e10cSrcweir     aTmp = rTempNameBase_Impl;
295cdf0e10cSrcweir     return aTmp;
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
298