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.cxx,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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #include <tools/tempfile.hxx>
37 #include <rtl/ustring.hxx>
38 #include <osl/file.hxx>
39 #include <rtl/instance.hxx>
40 #include <tools/time.hxx>
41 #include <tools/debug.hxx>
50 namespace { struct TempNameBase_Impl
: public rtl::Static
< ::rtl::OUString
, TempNameBase_Impl
> {}; }
55 sal_Bool bIsDirectory
;
58 String
GetSystemTempDir_Impl()
61 const char *pDir
= TempDirImpl(sBuf
);
63 ::rtl::OString
aTmpA( pDir
);
64 ::rtl::OUString aTmp
= ::rtl::OStringToOUString( aTmpA
, osl_getThreadTextEncoding() );
66 FileBase::getFileURLFromSystemPath( aTmp
, aRet
);
68 if( aName
.GetChar(aName
.Len()-1) != '/' )
73 #define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 )
74 String
ConstructTempDir_Impl( const String
* pParent
)
77 if ( pParent
&& pParent
->Len() )
79 // if parent given try to use it
80 rtl::OUString
aTmp( *pParent
);
83 // test for valid filename
85 ::osl::DirectoryItem aItem
;
86 sal_Int32 i
= aRet
.getLength();
87 if ( aRet
[i
-1] == '/' )
90 if ( DirectoryItem::get( ::rtl::OUString( aRet
, i
), aItem
) == FileBase::E_None
)
97 // if no parent or invalid parent : use system directory
98 ::rtl::OUString
& rTempNameBase_Impl
= TempNameBase_Impl::get();
99 if ( !rTempNameBase_Impl
.getLength() )
100 rTempNameBase_Impl
= GetSystemTempDir_Impl();
101 aName
= rTempNameBase_Impl
;
104 // Make sure that directory ends with a separator
105 xub_StrLen i
= aName
.Len();
106 if( i
>0 && aName
.GetChar(i
-1) != '/' )
112 void CreateTempName_Impl( String
& rName
, sal_Bool bKeep
, sal_Bool bDir
= sal_True
)
114 // add a suitable tempname
115 // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
116 // ER 13.07.00 why not radix 36 [0-9A-Z] ?!?
117 const unsigned nRadix
= 26;
118 String
aName( rName
);
119 aName
+= String::CreateFromAscii( "sv" );
122 static unsigned long u
= Time::GetSystemTicks();
123 for ( unsigned long nOld
= u
; ++u
!= nOld
; )
125 u
%= (nRadix
*nRadix
*nRadix
);
126 String
aTmp( aName
);
127 aTmp
+= String::CreateFromInt32( (sal_Int32
) (unsigned) u
, nRadix
);
128 aTmp
+= String::CreateFromAscii( ".tmp" );
132 FileBase::RC err
= Directory::create( aTmp
);
133 if ( err
== FileBase::E_None
)
135 // !bKeep: only for creating a name, not a file or directory
136 if ( bKeep
|| Directory::remove( aTmp
) == FileBase::E_None
)
140 else if ( err
!= FileBase::E_EXIST
)
142 // if f.e. name contains invalid chars stop trying to create dirs
148 DBG_ASSERT( bKeep
, "Too expensive, use directory for creating name!" );
150 FileBase::RC err
= aFile
.open(osl_File_OpenFlag_Create
);
151 if ( err
== FileBase::E_None
)
157 else if ( err
!= FileBase::E_EXIST
)
159 // if f.e. name contains invalid chars stop trying to create files
166 String
TempFile::CreateTempName( const String
* pParent
)
168 // get correct directory
169 String aName
= ConstructTempDir_Impl( pParent
);
171 // get TempFile name with default naming scheme
172 CreateTempName_Impl( aName
, sal_False
);
174 // convert to file URL
181 TempFile::TempFile( const String
* pParent
, sal_Bool bDirectory
)
182 : pImp( new TempFile_Impl
)
183 , bKillingFileEnabled( sal_False
)
185 pImp
->bIsDirectory
= bDirectory
;
187 // get correct directory
188 pImp
->aName
= ConstructTempDir_Impl( pParent
);
190 // get TempFile with default naming scheme
191 CreateTempName_Impl( pImp
->aName
, sal_True
, bDirectory
);
194 TempFile::TempFile( const String
& rLeadingChars
, const String
* pExtension
, const String
* pParent
, sal_Bool bDirectory
)
195 : pImp( new TempFile_Impl
)
196 , bKillingFileEnabled( sal_False
)
198 pImp
->bIsDirectory
= bDirectory
;
200 // get correct directory
201 String aName
= ConstructTempDir_Impl( pParent
);
203 // now use special naming scheme ( name takes leading chars and an index counting up from zero
204 aName
+= rLeadingChars
;
205 for ( sal_Int32 i
=0;; i
++ )
207 String
aTmp( aName
);
208 aTmp
+= String::CreateFromInt32( i
);
212 aTmp
+= String::CreateFromAscii( ".tmp" );
215 FileBase::RC err
= Directory::create( aTmp
);
216 if ( err
== FileBase::E_None
)
221 else if ( err
!= FileBase::E_EXIST
)
222 // if f.e. name contains invalid chars stop trying to create dirs
228 FileBase::RC err
= aFile
.open(osl_File_OpenFlag_Create
);
229 if ( err
== FileBase::E_None
)
235 else if ( err
!= FileBase::E_EXIST
)
236 // if f.e. name contains invalid chars stop trying to create dirs
242 TempFile::~TempFile()
244 if ( bKillingFileEnabled
)
246 if ( pImp
->bIsDirectory
)
248 // at the moment no recursiv algorithm present
249 Directory::remove( pImp
->aName
);
253 File::remove( pImp
->aName
);
260 sal_Bool
TempFile::IsValid() const
262 return pImp
->aName
.Len() != 0;
265 String
TempFile::GetName() const
272 String
TempFile::SetTempNameBaseDirectory( const String
&rBaseName
)
274 String
aName( rBaseName
);
276 ::rtl::OUString
& rTempNameBase_Impl
= TempNameBase_Impl::get();
278 FileBase::RC err
= Directory::create( aName
);
279 if ( err
== FileBase::E_None
|| err
== FileBase::E_EXIST
)
281 rTempNameBase_Impl
= aName
;
282 rTempNameBase_Impl
+= String( '/' );
284 TempFile
aBase( NULL
, sal_True
);
285 if ( aBase
.IsValid() )
286 rTempNameBase_Impl
= aBase
.pImp
->aName
;
290 aTmp
= rTempNameBase_Impl
;
294 String
TempFile::GetTempNameBaseDirectory()
296 ::rtl::OUString
& rTempNameBase_Impl
= TempNameBase_Impl::get();
297 if ( !rTempNameBase_Impl
.getLength() )
298 rTempNameBase_Impl
= GetSystemTempDir_Impl();
301 aTmp
= rTempNameBase_Impl
;